Merge pull request #608 from immutable/chore/update-version-1.36.9 #948
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: UI Tests 🧪 | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| targetPlatform: | |
| description: "Select the platform to build and test" | |
| required: true | |
| default: "All" | |
| type: choice | |
| options: | |
| - All | |
| - StandaloneOSX # Builds Unity 2021 macOS only | |
| - StandaloneOSX-Unity6 # Builds Unity 6 macOS only | |
| - StandaloneWindows64 # Builds Unity 2021 Windows only | |
| - StandaloneWindows64-Unity6 # Builds Unity 6 Windows only | |
| # - Android | |
| # - iOS | |
| push: | |
| branches: [main] | |
| pull_request: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| name: Build ${{ matrix.targetPlatform }} for AltTester 🛠️ | |
| runs-on: ubuntu-latest-8-cores | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - targetPlatform: StandaloneOSX | |
| buildMethod: MacBuilder.BuildForAltTester | |
| buildPath: sample/Builds/MacOS | |
| projectPath: sample | |
| unityVersion: 2021.3.26f1 | |
| - targetPlatform: StandaloneWindows64 | |
| buildMethod: WindowsBuilder.BuildForAltTester | |
| buildPath: sample/Builds/Windows64 | |
| projectPath: sample | |
| unityVersion: 2021.3.26f1 | |
| # - targetPlatform: Android | |
| # buildMethod: MobileBuilder.BuildForAltTester | |
| # buildPath: sample/Builds/Android | |
| # projectPath: sample | |
| # unityVersion: 2021.3.26f1 | |
| steps: | |
| - uses: actions/checkout@v3 | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform | |
| with: | |
| lfs: true | |
| - uses: actions/cache@v3 | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform | |
| with: | |
| path: Library | |
| key: Library-${{ matrix.targetPlatform }}-${{ hashFiles(format('{0}/Assets/**', matrix.projectPath), format('{0}/Packages/**', matrix.projectPath), format('{0}/ProjectSettings/**', matrix.projectPath)) }} | |
| restore-keys: | | |
| Library-${{ matrix.targetPlatform }} | |
| Library- | |
| - name: Build project | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform | |
| uses: game-ci/unity-builder@v4 | |
| env: | |
| UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} | |
| UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} | |
| UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} | |
| with: | |
| targetPlatform: ${{ contains(matrix.targetPlatform, 'Unity6') && 'StandaloneOSX' || matrix.targetPlatform }} | |
| projectPath: ${{ matrix.projectPath }} | |
| unityVersion: ${{ matrix.unityVersion }} | |
| buildMethod: ${{ matrix.buildMethod }} | |
| customParameters: -logFile logFile.log -quit -batchmode | |
| artifactsPath: ${{ matrix.buildPath }} | |
| - name: Ensure build path exists | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform | |
| run: mkdir -p ${{ matrix.buildPath }} | |
| - name: Upload artifact | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Build-${{ matrix.targetPlatform }} | |
| path: ${{ matrix.buildPath }} | |
| build-and-test-unity6-macos: # Unity 6 requires a full build cycle to compile AltTester packages properly. This doesn't work well in Game CI, so we have to build it manually. | |
| name: Build & Test Unity 6 macOS 🛠️🧪 | |
| runs-on: [self-hosted, macOS] | |
| concurrency: | |
| group: ui-tests-email-inbox-macos-unity6 | |
| cancel-in-progress: false # Let tests complete rather than cancelling | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == 'StandaloneOSX-Unity6' | |
| steps: | |
| - name: Cleanup old builds | |
| run: | | |
| # Remove previous build to save space | |
| rm -rf sample-unity6/Tests/* 2>/dev/null || true | |
| - uses: actions/checkout@v3 | |
| with: | |
| lfs: true | |
| - name: Setup symlinks for Unity 6 macOS | |
| run: ./setup-symlinks.sh | |
| - name: Force clean package resolution | |
| run: | | |
| echo "Removing Library folder to force clean package resolution..." | |
| rm -rf sample-unity6/Library | |
| echo "✅ Library folder removed" | |
| - name: First build (resolves packages) | |
| run: | | |
| echo "Running first build to trigger package resolution..." | |
| export TMPDIR="/Users/svc_buildsdk/tmp" | |
| mkdir -p "$TMPDIR" | |
| mkdir -p sample-unity6/Tests | |
| /Applications/Unity/Hub/Editor/6000.0.58f2/Unity.app/Contents/MacOS/Unity -projectPath "${{ github.workspace }}/sample-unity6" -executeMethod "MacBuilderUnity6.BuildForAltTester" -logFile "${{ github.workspace }}/sample-unity6/first-build-log.txt" -quit -batchmode --buildPath "${{ github.workspace }}/sample-unity6/Tests/Sample Unity 6 macOS" || true | |
| echo "First build completed (may have failed, that's ok). Checking for AltTester..." | |
| if ls -la "${{ github.workspace }}/sample-unity6/Library/PackageCache/" | grep alttester; then | |
| echo "✅ AltTester found in PackageCache after first build" | |
| else | |
| echo "⚠️ AltTester not found yet, but will be ready for second build" | |
| fi | |
| - name: Build Unity 6 macOS with command line (second build with packages ready) | |
| run: | | |
| echo "Building Unity 6 macOS using command line..." | |
| export TMPDIR="/Users/svc_buildsdk/tmp" | |
| mkdir -p "$TMPDIR" | |
| mkdir -p sample-unity6/Tests | |
| /Applications/Unity/Hub/Editor/6000.0.58f2/Unity.app/Contents/MacOS/Unity -projectPath "${{ github.workspace }}/sample-unity6" -executeMethod "MacBuilderUnity6.BuildForAltTester" -logFile "${{ github.workspace }}/sample-unity6/build-log.log" -quit -batchmode --buildPath "${{ github.workspace }}/sample-unity6/Tests/Sample Unity 6 macOS" | |
| echo "Build completed. Checking for build output..." | |
| ls -la sample-unity6/Tests/ | |
| - name: Create temporary keychain | |
| run: | | |
| security list-keychains | |
| security delete-keychain temporary || true | |
| security list-keychains | |
| security create-keychain -p "" temporary | |
| security default-keychain -s temporary | |
| security unlock-keychain -p "" temporary | |
| security set-keychain-settings -lut 600 temporary | |
| - name: Make macOS artifact executable | |
| run: chmod -R +x 'sample-unity6/Tests/Sample Unity 6 macOS.app/Contents/MacOS' | |
| - uses: actions/setup-python@v4 | |
| with: | |
| python-version: "3.13" | |
| - name: Install dependencies | |
| run: pip install -r sample-unity6/Tests/requirements-desktop.txt | |
| - name: Run UI tests | |
| env: | |
| UNITY_APP_PATH: Sample Unity 6 macOS.app | |
| UNITY_APP_NAME: Sample Unity 6 macOS | |
| MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }} | |
| BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} | |
| BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} | |
| working-directory: sample-unity6/Tests | |
| run: pytest -xs test/test_mac.py::MacTest | |
| - name: Remove temporary keychain | |
| if: always() | |
| run: | | |
| security list-keychains | |
| security delete-keychain temporary | |
| security default-keychain -s ~/Library/Keychains/login.keychain-db | |
| security list-keychains -d user -s ~/Library/Keychains/login.keychain-db | |
| security list-keychains | |
| - name: Upload first build log | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Unity6-First-Build-Log | |
| path: sample-unity6/first-build-log.txt | |
| - name: Upload build log | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Unity6-macOS-Build-Log | |
| path: sample-unity6/build-log.log | |
| build-and-test-unity6-windows: # Unity 6 requires a full build cycle to compile AltTester packages properly. This doesn't work well in Game CI, so we have to build it manually. | |
| name: Build & Test Unity 6 Windows 🛠️🧪 | |
| runs-on: [self-hosted, windows] | |
| concurrency: | |
| group: ui-tests-email-inbox-windows-unity6 | |
| cancel-in-progress: false # Let tests complete rather than cancelling | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == 'StandaloneWindows64-Unity6' | |
| steps: | |
| - name: Cleanup old builds | |
| run: | | |
| # Remove previous build to save space | |
| if (Test-Path "sample-unity6/Tests") { Remove-Item -Recurse -Force "sample-unity6/Tests" -ErrorAction SilentlyContinue } | |
| - uses: actions/checkout@v3 | |
| with: | |
| lfs: true | |
| - name: Cache Unity Library folder | |
| uses: actions/cache@v3 | |
| with: | |
| path: sample-unity6/Library | |
| key: Library-Unity6-Windows-${{ hashFiles('sample-unity6/Assets/**', 'sample-unity6/Packages/**', 'sample-unity6/ProjectSettings/**') }} | |
| restore-keys: | | |
| Library-Unity6-Windows- | |
| - name: Setup symlinks for Unity 6 Windows | |
| run: .\setup-symlinks.ps1 | |
| - name: Verify symlinks were created | |
| run: | | |
| if (-not (Test-Path "sample-unity6/Assets/Editor/WindowsBuilderUnity6.cs")) { | |
| Write-Output "❌ Build script not found - symlink setup failed" | |
| exit 1 | |
| } | |
| Write-Output "✅ Symlinks verified" | |
| # Don't delete Library folder - let Unity reuse cached package data if available | |
| # Deleting it forces a complete reimport which takes too long | |
| - name: Ensure Tests directory exists | |
| run: | | |
| if (-not (Test-Path "sample-unity6/Tests")) { | |
| New-Item -ItemType Directory -Path "sample-unity6/Tests" -Force | Out-Null | |
| } | |
| - name: First build (resolves packages) | |
| run: | | |
| Write-Output "Running first build to trigger package resolution..." | |
| $unityPath = "C:\Program Files\Unity\Hub\Editor\6000.0.58f2\Editor\Unity.exe" | |
| $projectPath = "${{ github.workspace }}\sample-unity6" | |
| $logFile = "${{ github.workspace }}\sample-unity6\first-build-log.txt" | |
| $buildPath = "${{ github.workspace }}\sample-unity6\Tests\Sample Unity 6 Windows.exe" | |
| $arguments = @( | |
| "-projectPath", "`"$projectPath`"", | |
| "-executeMethod", "WindowsBuilderUnity6.BuildForAltTester", | |
| "-logFile", "`"$logFile`"", | |
| "-quit", "-batchmode", "-nographics", | |
| "--buildPath", "`"$buildPath`"" | |
| ) | |
| # Run and ignore exit code (may fail on first attempt) | |
| $process = Start-Process -FilePath $unityPath ` | |
| -ArgumentList $arguments ` | |
| -Wait -PassThru -NoNewWindow | |
| Write-Output "First build completed (exit code: $($process.ExitCode), may have failed, that's ok). Checking for AltTester..." | |
| if (Test-Path "${{ github.workspace }}\sample-unity6\Library\PackageCache") { | |
| $altTesterFound = Get-ChildItem "${{ github.workspace }}\sample-unity6\Library\PackageCache" -Filter "*alttester*" -ErrorAction SilentlyContinue | |
| if ($altTesterFound) { | |
| Write-Output "✅ AltTester found in PackageCache after first build" | |
| } else { | |
| Write-Output "⚠️ AltTester not found yet, but will be ready for second build" | |
| } | |
| } | |
| - name: Build Unity 6 Windows executable | |
| timeout-minutes: 20 | |
| run: | | |
| Write-Output "Building Unity 6 Windows executable..." | |
| Write-Output "Started at: $(Get-Date -Format 'HH:mm:ss')" | |
| # Run Unity build | |
| $unityPath = "C:\Program Files\Unity\Hub\Editor\6000.0.58f2\Editor\Unity.exe" | |
| $projectPath = "${{ github.workspace }}\sample-unity6" | |
| $logFile = "${{ github.workspace }}\sample-unity6\build-log.log" | |
| $buildPath = "${{ github.workspace }}\sample-unity6\Tests\Sample Unity 6 Windows.exe" | |
| # Build argument list with proper quoting for paths with spaces | |
| $arguments = @( | |
| "-projectPath", "`"$projectPath`"", | |
| "-executeMethod", "WindowsBuilderUnity6.BuildForAltTester", | |
| "-logFile", "`"$logFile`"", | |
| "-quit", "-batchmode", "-nographics", | |
| "--buildPath", "`"$buildPath`"" | |
| ) | |
| $process = Start-Process -FilePath $unityPath ` | |
| -ArgumentList $arguments ` | |
| -Wait -PassThru -NoNewWindow | |
| $buildExitCode = $process.ExitCode | |
| Write-Output "Finished at: $(Get-Date -Format 'HH:mm:ss') (exit code: $buildExitCode)" | |
| # Verify build output | |
| Start-Sleep -Seconds 2 | |
| if (Test-Path $buildPath) { | |
| $fileSize = (Get-Item $buildPath).Length / 1MB | |
| Write-Output "✅ Build succeeded! ($([math]::Round($fileSize, 2)) MB)" | |
| } else { | |
| Write-Output "❌ Build failed! Executable not found" | |
| Write-Output "" | |
| Write-Output "Build log:" | |
| if (Test-Path $logFile) { | |
| Get-Content $logFile | |
| } else { | |
| Write-Output "⚠️ Log file not found at: $logFile" | |
| } | |
| exit 1 | |
| } | |
| - uses: actions/setup-python@v4 | |
| with: | |
| python-version: "3.13" | |
| - name: Verify test files are accessible | |
| run: | | |
| if (-not (Test-Path "sample-unity6/Tests/requirements-desktop.txt") -and -not (Test-Path "sample/Tests/requirements-desktop.txt")) { | |
| Write-Output "❌ Test requirements file not found" | |
| exit 1 | |
| } | |
| - name: Install dependencies | |
| run: | | |
| if (Test-Path "sample-unity6/Tests/requirements-desktop.txt") { | |
| pip install -r sample-unity6/Tests/requirements-desktop.txt | |
| } else { | |
| pip install -r sample/Tests/requirements-desktop.txt | |
| } | |
| - name: Run UI tests | |
| env: | |
| UNITY_APP_PATH: Sample Unity 6 Windows.exe | |
| UNITY_APP_NAME: Sample Unity 6 Windows | |
| MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }} | |
| BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} | |
| BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} | |
| working-directory: sample-unity6/Tests | |
| run: python -m pytest -xs test/test_windows.py::WindowsTest | |
| - name: Upload build log | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Unity6-Windows-Build-Log | |
| path: sample-unity6/build-log.log | |
| test: | |
| name: Run ${{ matrix.targetPlatform }} UI tests 🧪 | |
| needs: build | |
| strategy: | |
| matrix: | |
| include: | |
| - targetPlatform: StandaloneOSX | |
| runs-on: [self-hosted, macOS] | |
| test_script: pytest -xs test/test_mac.py::MacTest | |
| projectPath: sample | |
| unityAppName: SampleApp | |
| unityAppExtension: .app | |
| concurrency_group: macos | |
| - targetPlatform: StandaloneWindows64 | |
| runs-on: [self-hosted, windows] | |
| test_script: python -m pytest -xs test/test_windows.py::WindowsTest | |
| projectPath: sample | |
| unityAppName: Immutable Sample | |
| unityAppExtension: .exe | |
| concurrency_group: windows | |
| # - targetPlatform: Android | |
| # runs-on: [ self-hosted, macOS ] | |
| # test_script: browserstack-sdk pytest -s ./test/test_android.py --browserstack.config "browserstack.android.yml" | |
| concurrency: | |
| group: ui-tests-email-inbox-${{ matrix.concurrency_group }} | |
| cancel-in-progress: false # Let tests complete rather than canceling | |
| runs-on: ${{ matrix.runs-on }} | |
| steps: | |
| - uses: actions/checkout@v3 | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform | |
| with: | |
| lfs: true | |
| - name: Create temporary keychain | |
| if: contains(matrix.targetPlatform, 'StandaloneOSX') && (github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform) | |
| run: | | |
| security list-keychains | |
| security delete-keychain temporary || true | |
| security list-keychains | |
| security create-keychain -p "" temporary | |
| security default-keychain -s temporary | |
| security unlock-keychain -p "" temporary | |
| security set-keychain-settings -lut 600 temporary | |
| - uses: actions/download-artifact@v4 | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform | |
| with: | |
| name: Build-${{ matrix.targetPlatform }} | |
| path: ${{ matrix.projectPath }}/Tests | |
| - name: Make macOS artifact executable | |
| if: | | |
| contains(matrix.targetPlatform, 'StandaloneOSX') && | |
| (github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform) | |
| run: chmod -R +x '${{ matrix.projectPath }}/Tests/${{ matrix.unityAppName }}.app/Contents/MacOS' | |
| - uses: actions/setup-python@v4 | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform | |
| with: | |
| python-version: "3.13" | |
| - name: Install dependencies (Windows) | |
| if: matrix.targetPlatform == 'StandaloneWindows64' && (github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == 'StandaloneWindows64') | |
| run: pip install -r "${{ matrix.projectPath }}/Tests/requirements-desktop.txt" | |
| - name: Install dependencies (Mac) | |
| if: contains(matrix.targetPlatform, 'StandaloneOSX') && (github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform) | |
| run: pip install -r "${{ matrix.projectPath }}/Tests/requirements-desktop.txt" | |
| - name: Run UI tests | |
| if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform | |
| env: | |
| UNITY_APP_PATH: ${{ matrix.unityAppName }}${{ matrix.unityAppExtension }} | |
| UNITY_APP_NAME: ${{ matrix.unityAppName }} | |
| MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }} | |
| BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} | |
| BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} | |
| working-directory: ${{ matrix.projectPath }}/Tests | |
| run: ${{ matrix.test_script }} | |
| - name: Remove temporary keychain | |
| if: contains(matrix.targetPlatform, 'StandaloneOSX') && (github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == matrix.targetPlatform) | |
| run: | | |
| security list-keychains | |
| security delete-keychain temporary | |
| security default-keychain -s ~/Library/Keychains/login.keychain-db | |
| security list-keychains -d user -s ~/Library/Keychains/login.keychain-db | |
| security list-keychains | |
| # build-ios: #test-ios: | |
| # name: Run iOS build #UI tests 🧪 | |
| # needs: | |
| # - build | |
| # - test | |
| # runs-on: [ self-hosted, macOS ] | |
| # if: github.event_name != 'workflow_dispatch' || github.event.inputs.targetPlatform == 'All' || github.event.inputs.targetPlatform == 'iOS' | |
| # steps: | |
| # - uses: actions/checkout@v3 | |
| # with: | |
| # lfs: true | |
| # - name: Build iOS app | |
| # working-directory: sample | |
| # run: | | |
| # export TMPDIR=/Users/svc_buildsdk/tmp | |
| # mkdir -p $TMPDIR | |
| # ./build_ios.sh | |
| # - uses: actions/setup-python@v4 | |
| # with: | |
| # python-version: "3.13" | |
| # - name: Install dependencies | |
| # run: pip install -r "sample/Tests/requirements-mobile.txt" | |
| # - name: Run UI tests | |
| # env: | |
| # MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }} | |
| # BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} | |
| # BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} | |
| # working-directory: sample/Tests/test/ios | |
| # run: browserstack-sdk pytest -xs ./test_ios.py --browserstack.config "browserstack.ios.yml" |