Skip to content

Merge pull request #608 from immutable/chore/update-version-1.36.9 #948

Merge pull request #608 from immutable/chore/update-version-1.36.9

Merge pull request #608 from immutable/chore/update-version-1.36.9 #948

Workflow file for this run

---
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"