Browse Source

CI: Add Steam build uploader

derrod 3 years ago
parent
commit
e860b26589

+ 215 - 0
.github/workflows/steam.yml

@@ -0,0 +1,215 @@
+name: Steam Upload
+
+on:
+  release:
+    types:
+    - published
+  workflow_dispatch:
+    inputs:
+      tag:
+        description: 'Tag to fetch and upload (nightly if none)'
+        required: false
+      win_url_override:
+        description: 'Windows build to use (.zip only)'
+        required: false
+      mac_url_override:
+        description: 'Mac build to use (.dmg only)'
+        required: false
+  schedule:
+  - cron: 0 0 * * *
+
+env:
+  WORKFLOW_ID: 583765
+  GIT_NIGHTLY_BRANCH: master
+  STEAM_NIGHTLY_BRANCH: nightly
+  STEAM_STABLE_BRANCH: staging
+  STEAM_BETA_BRANCH: beta_staging
+
+jobs:
+  upload:
+    name: Steam upload
+    runs-on: ubuntu-20.04
+
+    steps:
+    - name: Checkout
+      uses: actions/checkout@v3
+      with:
+        path: source
+
+    - name: Setup 7-Zip (PPA)
+      # The 7-Zip version available in the default ubuntu repos (p7zip) is wildly out-of-date and does not properly support DMG files.
+      run: |
+        sudo add-apt-repository -y ppa:spvkgn/sevenzip
+        sudo apt update -y
+        sudo apt install -y 7-zip
+
+    - name: Get build information
+      id: build-info
+      run: |
+        EVENT='${{ github.event_name }}'
+        if [[ ${EVENT} == 'release' || ( ${EVENT} == 'workflow_dispatch' && -n '${{ github.event.inputs.tag }}') ]]; then
+            if [[ ${EVENT} == "release" ]]; then
+                DESC='${{ github.event.release.tag_name }}'
+                if [[ '${{ github.event.release.prerelease }}' == 'true' ]]; then
+                  BRANCH='${{ env.STEAM_BETA_BRANCH }}'
+                else
+                  BRANCH='${{ env.STEAM_STABLE_BRANCH }}'
+                fi
+                ASSETS_URL='${{ github.event.release.assets_url }}'
+            else
+                RELEASE="$(curl -s '${{ github.api_url }}/repos/obsproject/obs-studio/releases/tags/${{ github.event.inputs.tag }}')"
+                
+                DESC="$(jq -r '.tag_name' <<< ${RELEASE})"
+                if [[ "$(jq -r '.prerelease' <<< ${RELEASE})" == 'true' ]]; then
+                  BRANCH='${{ env.STEAM_BETA_BRANCH }}'
+                else
+                  BRANCH='${{ env.STEAM_STABLE_BRANCH }}'
+                fi
+                ASSETS_URL="$(jq -r '.assets_url' <<< ${RELEASE})"
+            fi
+
+            ASSETS="$(curl -s "${ASSETS_URL}")"
+            WIN_ASSET_URL="$(jq -r '.[] | select(.name|test(".*x64.zip")) .browser_download_url' <<< ${ASSETS})"
+            MAC_ASSET_URL="$(jq -r '.[] | select(.name|test(".*.dmg")) .browser_download_url' <<< ${ASSETS})"
+            TYPE='release'
+        else
+            BRANCH='${{ env.STEAM_NIGHTLY_BRANCH }}'
+            BUILDS="$(curl -s '${{ github.api_url }}/repos/obsproject/obs-studio/actions/workflows/${{ env.WORKFLOW_ID }}/runs?per_page=1&event=push&status=success&branch=${{ env.GIT_NIGHTLY_BRANCH }}')"
+            ARTIFACTS_URL="$(jq -r '.workflow_runs[].artifacts_url' <<< ${BUILDS})"
+            DESC="g$(jq -r '.workflow_runs[].head_sha' <<< "${BUILDS}" | cut -c1-9)"
+
+            ARTIFACTS="$(curl -s ${ARTIFACTS_URL})"
+            WIN_ASSET_URL="$(jq -r '.artifacts[] | select(.name|test(".*win-x64.*")) .archive_download_url' <<< ${ARTIFACTS})"
+            MAC_ASSET_URL="$(jq -r '.artifacts[] | select(.name|test(".*macos-x86_64.*")) .archive_download_url' <<< ${ARTIFACTS})"
+            TYPE='nightly'
+        fi
+
+        # Apply overrides from workflow_dispatch
+        if [[ ${EVENT} == 'workflow_dispatch' ]]; then
+            if [[ -n '${{ github.event.inputs.win_url_override }}' ]]; then
+                WIN_ASSET_URL='${{ github.event.inputs.win_url_override }}'
+            fi
+            
+            if [[ -n '${{ github.event.inputs.mac_url_override }}' ]]; then
+                MAC_ASSET_URL='${{ github.event.inputs.mac_url_override }}'
+            fi
+        fi
+
+        if [[ -z ${WIN_ASSET_URL} || -z ${MAC_ASSET_URL} ]]; then
+            echo "Missing at least one asset URL!"
+            exit 1
+        fi
+
+        # set env variables for subsequent steps
+        echo "::set-output name=type::${TYPE}"
+        echo "::set-output name=branch::${BRANCH}"
+        echo "::set-output name=desc::${DESC}"
+        echo "::set-output name=win_url::${WIN_ASSET_URL}"
+        echo "::set-output name=mac_intel_url::${MAC_ASSET_URL}"
+
+    - name: Restore build cache
+      id: cache
+      uses: actions/cache@v3
+      with:
+        path: ${{ github.workspace }}/steam/build
+        key: ${{ steps.build-info.outputs.branch }}-${{ steps.build-info.outputs.desc }}
+        # Using "restore-keys" will restore the most recent cache for the branch, even if the exact cache doesn't exist.
+        # This doesn't set cache-hit to true so it won't skip the upload for nightlies.
+        restore-keys: ${{ steps.build-info.outputs.branch }}
+
+    - name: Determine if Steam upload should run
+      # If the nightly build has already been uploaded and thus a cache exists skip this and the following steps.
+      # Steam does not prevent us from uploading duplicate builds so this would just pollute the dashboard.
+      # This is a bit of a hack and can fail to work if our cache has been evicted or we somehow have no commits for 7 days,
+      # but it's better than nothing!
+      id: should-run
+      run: |
+        if [[ '${{ steps.build-info.outputs.type }}' == 'release' || '${{ steps.cache.outputs.cache-hit }}' != 'true' ]]; then
+            echo "::set-output name=result::true"
+        else
+            echo "::set-output name=result::false"
+        fi
+
+    - name: Download and prepare builds
+      if: steps.should-run.outputs.result == 'true'
+      run: |
+        echo "::group::Download Windows build"
+        if [[ '${{ steps.build-info.outputs.win_url }}' == *'api.github.com'* ]]; then
+            curl -L -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' '${{ steps.build-info.outputs.win_url }}' -o windows.zip
+        else
+            curl -L '${{ steps.build-info.outputs.win_url }}' -o windows.zip
+        fi
+        echo "::endgroup::"
+      
+        echo "::group::Download Mac build"
+        if [[ '${{ steps.build-info.outputs.mac_intel_url }}' == *'api.github.com'* ]]; then
+            curl -L -H 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' '${{ steps.build-info.outputs.mac_intel_url }}' -o mac_x86.dmg.zip
+        else
+            curl -L '${{ steps.build-info.outputs.mac_intel_url }}' -o mac_x86.dmg
+        fi
+        echo "::endgroup::"
+
+        mkdir -p steam && cd steam
+  
+        echo "::group::Extract and prepare Win64"
+        mkdir steam-windows
+        (
+            cd steam-windows
+            unzip ../../windows.zip
+            # CI builds can be double-zipped
+            if compgen -G "*.zip" > /dev/null; then
+                unzip *.zip
+                rm *.zip
+            fi
+            # copy install scripts and create sentinel file
+            cp -r ../../source/CI/steam/scripts scripts
+            touch disable_updater
+        )
+        echo "::endgroup::"
+
+        echo "::group::Extract macOS (x86)"
+        mkdir steam-macos
+        # CI builds are zipped
+        if [[ -f ../mac_x86.dmg.zip ]]; then
+            unzip ../mac_x86.dmg.zip
+            # 7-Zip will have an exit code of 2 due to the "unsafe" 'Applications' symlink.
+            # GitHub treats this as a failure so ignore non-zero exit codes here.
+            7zz x *.dmg -otmp || true
+        else
+            7zz x ../mac_x86.dmg -otmp || true
+        fi
+          
+        mv tmp/*/OBS.app steam-macos
+        echo "::endgroup::"
+
+    - name: Setup steamcmd
+      if: steps.should-run.outputs.result == 'true'
+      uses: CyberAndrii/setup-steamcmd@e19cd1516315ce46dbfffa47193f92fe42d1419e
+
+    - name: Generate Steam auth code
+      if: steps.should-run.outputs.result == 'true'
+      id: steam-totp
+      uses: CyberAndrii/steam-totp@0fc9e59dc5bbf4368d23d5a33956f104248da31a
+      with:
+        shared_secret: ${{ secrets.STEAM_SHARED_SECRET }}
+
+    - name: Upload to Steam
+      if: steps.should-run.outputs.result == 'true'
+      run: |
+        cd steam
+        echo "::group::Prepare Steam build script"
+        # The description in Steamworks for the build will be "github_<branch>-<tag/short hash>", e.g. "github_nightly-gaa73de952"
+        sed 's/@@DESC@@/${{ steps.build-info.outputs.branch }}-${{ steps.build-info.outputs.desc }}/;s/@@BRANCH@@/${{ steps.build-info.outputs.branch }}/' ../source/CI/steam/obs_build.vdf > build.vdf
+        echo "Generated file:"
+        cat build.vdf
+        echo "::endgroup::"
+        echo "::group::Upload to Steam"
+        steamcmd +login '${{ secrets.STEAM_USER }}' '${{ secrets.STEAM_PASSWORD }}' '${{ steps.steam-totp.outputs.code }}' +run_app_build "$(pwd)/build.vdf" +quit
+        echo "::endgroup::"
+
+    - name: Upload Steam build logs
+      if: steps.should-run.outputs.result == 'true'
+      uses: actions/upload-artifact@v2
+      with:
+        name: steam-build-logs
+        path: ${{ github.workspace }}/steam/build/*.log

+ 36 - 0
CI/steam/obs_build.vdf

@@ -0,0 +1,36 @@
+"AppBuild"
+{
+	"AppID" "1905180"
+	"Desc" "github_@@DESC@@"
+
+	"ContentRoot" "./"
+	"BuildOutput" "build/"
+	
+	"SetLive" "@@BRANCH@@"
+
+	"Depots"
+	{
+		"1905181" // Windows
+		{
+			"ContentRoot" "./steam-windows"
+			"InstallScript" "scripts/installscript.vdf"
+			"FileMapping"
+			{
+				"LocalPath" "*"
+				"DepotPath" "."
+				"recursive" "1"
+			}
+		}
+		
+		"1905182" // Mac
+	 	{
+			"ContentRoot" "./steam-macos"
+			"FileMapping"
+			{
+				"LocalPath" "*"
+				"DepotPath" "."
+				"recursive" "1"
+			}
+		}
+	}
+}

+ 85 - 0
CI/steam/scripts/install.bat

@@ -0,0 +1,85 @@
+@echo off
+@cd /d "%~dp0"
+
+goto checkAdmin
+
+
+:checkAdmin
+	net session >nul 2>&1
+	if %errorLevel% == 0 (
+		echo.
+	) else (
+		echo Administrative rights are required. Please re-run this script as Administrator.
+		goto end
+	)
+
+:writeRegistry
+	reg add "HKLM\SOFTWARE\OBS Studio" /f /t REG_SZ /d %1 /reg:32
+	reg add "HKLM\SOFTWARE\OBS Studio" /f /t REG_SZ /d %1 /reg:64
+
+:setupProgramData
+	:: Required for UWP applications
+	mkdir "%PROGRAMDATA%\obs-studio-hook"
+	icacls "%PROGRAMDATA%\obs-studio-hook" /grant "ALL APPLICATION PACKAGES":(OI)(CI)(GR,GE)
+
+:checkDLL
+	echo Checking for 32-bit Virtual Cam registration...
+	reg query "HKLM\SOFTWARE\Classes\CLSID\{A3FCE0F5-3493-419F-958A-ABA1250EC20B}" >nul 2>&1 /reg:32
+	if %errorLevel% == 0 (
+		echo 32-bit Virtual Cam found, skipping install...
+		echo.
+	) else (
+		echo 32-bit Virtual Cam not found, installing...
+		goto install32DLL
+	)
+
+:CheckDLLContinue
+	echo Checking for 64-bit Virtual Cam registration...
+	reg query "HKLM\SOFTWARE\Classes\CLSID\{A3FCE0F5-3493-419F-958A-ABA1250EC20B}" >nul 2>&1 /reg:64
+	if %errorLevel% == 0 (
+		echo 64-bit Virtual Cam found, skipping install...
+		echo.
+	) else (
+		echo 64-bit Virtual Cam not found, installing...
+		goto install64DLL
+	)
+	goto endSuccess
+
+:install32DLL
+	echo Installing 32-bit Virtual Cam...
+	regsvr32.exe /i /s %1\data\obs-plugins\win-dshow\obs-virtualcam-module32.dll
+	reg query "HKLM\SOFTWARE\Classes\CLSID\{A3FCE0F5-3493-419F-958A-ABA1250EC20B}" >nul 2>&1 /reg:32
+	if %errorLevel% == 0 (
+		echo 32-bit Virtual Cam successfully installed
+		echo.
+	) else (
+		echo 32-bit Virtual Cam installation failed
+		echo.
+		goto endFail
+	)
+	goto checkDLLContinue
+
+:install64DLL
+	echo Installing 64-bit Virtual Cam...
+	regsvr32.exe /i /s %1\data\obs-plugins\win-dshow\obs-virtualcam-module64.dll
+	reg query "HKLM\SOFTWARE\Classes\CLSID\{A3FCE0F5-3493-419F-958A-ABA1250EC20B}" >nul 2>&1 /reg:64
+	if %errorLevel% == 0 (
+		echo 64-bit Virtual Cam successfully installed
+		echo.
+		goto endSuccess
+	) else (
+		echo 64-bit Virtual Cam installation failed
+		echo.
+		goto endFail
+	)
+
+:endFail
+	echo Something failed, please report this on the OBS Discord or Forums!
+	goto end
+
+:endSuccess
+	echo Virtual Cam installed!
+	echo.
+
+:end
+	exit

+ 20 - 0
CI/steam/scripts/installscript.vdf

@@ -0,0 +1,20 @@
+"InstallScript"
+{
+    "Run Process"
+    {
+        "install"
+        {
+            "process 1" "scripts\\install.bat"
+            "command 1" "\"%INSTALLDIR%\""
+        }
+    }
+
+    "Run Process On Uninstall"
+    {
+        "uninstall"
+        {
+            "process 1" "scripts\\uninstall.bat"
+            "command 1" "\"%INSTALLDIR%\""
+        }
+    }
+}

+ 33 - 0
CI/steam/scripts/uninstall.bat

@@ -0,0 +1,33 @@
+@echo off
+@cd /d "%~dp0"
+goto checkAdmin
+
+:checkAdmin
+	net session >nul 2>&1
+	if %errorLevel% == 0 (
+		echo.
+	) else (
+		echo Administrative rights are required. Please re-run this script as Administrator.
+		goto end
+	)
+
+:clearRegistry
+	reg delete "HKLM\SOFTWARE\OBS Studio" /f /reg:32
+	reg delete "HKLM\SOFTWARE\OBS Studio" /f /reg:64
+	:: Vulkan layer keys
+	reg delete "HKLM\SOFTWARE\Khronos\Vulkan\ImplicitLayers" /f /v "%PROGRAMDATA%\obs-studio-hook\obs-vulkan64.json" /reg:32
+	reg delete "HKLM\SOFTWARE\Khronos\Vulkan\ImplicitLayers" /f /v "%PROGRAMDATA%\obs-studio-hook\obs-vulkan32.json" /reg:64
+
+:deleteProgramDataFolder
+	RMDIR /S /Q "%PROGRAMDATA%\obs-studio-hook"
+
+:uninstallDLLs
+	regsvr32.exe /u /s %1\data\obs-plugins\win-dshow\obs-virtualcam-module32.dll
+	regsvr32.exe /u /s %1\data\obs-plugins\win-dshow\obs-virtualcam-module64.dll
+
+:endSuccess
+	echo Virtual Cam uninstalled!
+	echo.
+
+:end
+	exit