Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/scripts/audience/ensure-msvc-windows.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Ensures Visual Studio Build Tools (VC.Tools + Win10 SDK) are present on the runner.
# Workflow caller: .github/workflows/test-audience-sample-app.yml (Windows IL2CPP cells).

$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"

# Match Unity's detection logic: vswhere requires VC.Tools (any version), registry
# probe for any Win10 SDK at v10.0/InstallationFolder. Pinning a specific SDK
# version in -requires is too strict; VCTools ships with whatever Win10 SDK is
# current, and Unity accepts any.
function Test-Toolchain {
$vc = if (Test-Path $vswhere) {
& $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath 2>$null
} else { '' }
$sdk = (Get-ItemProperty 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0' -ErrorAction SilentlyContinue).InstallationFolder
return @{ VcTools = $vc; Win10Sdk = $sdk }
}

$state = Test-Toolchain
if ($state.VcTools -and $state.Win10Sdk) {
Write-Output "VC.Tools at: $($state.VcTools)"
Write-Output "Win10 SDK at: $($state.Win10Sdk)"
exit 0
}
Write-Output "Toolchain incomplete. VC.Tools='$($state.VcTools)' Win10Sdk='$($state.Win10Sdk)'"

Write-Output "::group::Install VS 2022 Build Tools (VCTools + Win10 SDK)"
$installer = "$env:RUNNER_TEMP\vs_BuildTools.exe"
Invoke-WebRequest -Uri 'https://aka.ms/vs/17/release/vs_BuildTools.exe' -OutFile $installer

$installArgs = @(
'--quiet','--wait','--norestart','--nocache',
'--add','Microsoft.VisualStudio.Workload.VCTools',
'--add','Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
'--add','Microsoft.VisualStudio.Component.Windows10SDK.20348',
'--includeRecommended'
)
$p = Start-Process -FilePath $installer -ArgumentList $installArgs -Wait -PassThru -NoNewWindow
# 3010 = success, reboot pending (tools are usable without reboot).
if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) {
Write-Output "::error::VS Build Tools installer exited $($p.ExitCode)"
exit $p.ExitCode
}
Write-Output "::endgroup::"

$state = Test-Toolchain
if (-not ($state.VcTools -and $state.Win10Sdk)) {
Write-Output "::group::diagnostic"
Write-Output "VC.Tools path (vswhere): '$($state.VcTools)'"
Write-Output "Win10 SDK (registry v10.0/InstallationFolder): '$($state.Win10Sdk)'"
Write-Output "--- all VS installations ---"
if (Test-Path $vswhere) { & $vswhere -all -products * -format json }
Write-Output "--- HKLM Win10 SDK roots ---"
Get-ChildItem 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows' -ErrorAction SilentlyContinue | Format-List
Write-Output "::endgroup::"
Write-Output "::error::Install reported success but VC.Tools or Win10 SDK still not detected. Runner service account likely lacks admin to install system-wide. Install VS Build Tools manually on IMX_SDKBUILD: vs_BuildTools.exe --quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"
exit 1
}
Write-Output "Verified VC.Tools at: $($state.VcTools)"
Write-Output "Verified Win10 SDK at: $($state.Win10Sdk)"
56 changes: 56 additions & 0 deletions .github/scripts/audience/install-unity-macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash
# Installs the Unity editor and (for IL2CPP cells) the mac-il2cpp module.
# Idempotent. Sets UNITY_PATH in GITHUB_ENV so the playmode step picks it up.
# Workflow caller: .github/workflows/test-audience-sample-app.yml (playmode job).
#
# Inputs (env): UNITY_VERSION, UNITY_CHANGESET, BACKEND.

set -uo pipefail

HUB="/Applications/Unity Hub.app/Contents/MacOS/Unity Hub"

echo "::group::install editor"
"$HUB" -- --headless install \
--version "$UNITY_VERSION" --changeset "$UNITY_CHANGESET" --architecture arm64 \
|| echo "(install non-zero, OK if 'Editor already installed in this location')"
echo "::endgroup::"

if [ "$BACKEND" = "IL2CPP" ]; then
echo "::group::install mac-il2cpp module"
"$HUB" -- --headless install-modules \
--version "$UNITY_VERSION" --changeset "$UNITY_CHANGESET" --architecture arm64 \
--module mac-il2cpp \
|| echo "(install-modules non-zero, OK if 'No modules found to install')"
echo "::endgroup::"
fi

EDITOR_APP=""
for cand in \
"/Applications/Unity/Hub/Editor/$UNITY_VERSION-arm64/Unity.app" \
"/Applications/Unity/Hub/Editor/$UNITY_VERSION/Unity.app"; do
if [ -x "$cand/Contents/MacOS/Unity" ]; then EDITOR_APP="$cand"; break; fi
done

IL2CPP_DIR=""
if [ "$BACKEND" = "IL2CPP" ] && [ -n "$EDITOR_APP" ]; then
for d in \
"$EDITOR_APP/Contents/PlaybackEngines/MacStandaloneSupport/Variations/macos_arm64_player_nondevelopment_il2cpp" \
"$EDITOR_APP/Contents/PlaybackEngines/MacStandaloneSupport/Variations/macos_x64_player_nondevelopment_il2cpp"; do
if [ -d "$d" ]; then IL2CPP_DIR="$d"; break; fi
done
fi

MISSING=""
[ -z "$EDITOR_APP" ] && MISSING="editor"
[ "$BACKEND" = "IL2CPP" ] && [ -z "$IL2CPP_DIR" ] && MISSING="${MISSING:+$MISSING+}mac-il2cpp"
if [ -n "$MISSING" ]; then
echo "::error::Unity $UNITY_VERSION missing: $MISSING"
ls -la /Applications/Unity/Hub/Editor/ 2>&1 || true
"$HUB" -- --headless editors --installed 2>&1 || true
exit 1
fi

UNITY_PATH="$EDITOR_APP/Contents/MacOS/Unity"
echo "Found Unity: $UNITY_PATH"
[ -n "$IL2CPP_DIR" ] && echo "Found IL2CPP: $IL2CPP_DIR"
echo "UNITY_PATH=$UNITY_PATH" >> "$GITHUB_ENV"
39 changes: 39 additions & 0 deletions .github/scripts/audience/install-unity-windows.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Installs the Unity editor and (for IL2CPP cells) the windows-il2cpp module.
# Idempotent. Sets UNITY_PATH in GITHUB_ENV so the playmode step picks it up.
# Workflow caller: .github/workflows/test-audience-sample-app.yml (playmode job).
#
# Inputs (env): UNITY_VERSION, UNITY_CHANGESET, BACKEND.

$ErrorActionPreference = 'Continue'
$hub = "C:\Program Files\Unity Hub\Unity Hub.exe"

Write-Output "::group::install editor"
& $hub -- --headless install --version $env:UNITY_VERSION --changeset $env:UNITY_CHANGESET --architecture x86_64 2>&1 | Write-Output
if ($LASTEXITCODE -ne 0) { Write-Output "(install non-zero, OK if 'Editor already installed in this location')" }
$global:LASTEXITCODE = 0
Write-Output "::endgroup::"

if ($env:BACKEND -eq 'IL2CPP') {
Write-Output "::group::install windows-il2cpp module"
& $hub -- --headless install-modules --version $env:UNITY_VERSION --changeset $env:UNITY_CHANGESET --architecture x86_64 --module windows-il2cpp 2>&1 | Write-Output
if ($LASTEXITCODE -ne 0) { Write-Output "(install-modules non-zero, OK if 'No modules found to install')" }
$global:LASTEXITCODE = 0
Write-Output "::endgroup::"
}

$editor = "C:\Program Files\Unity\Hub\Editor\$env:UNITY_VERSION\Editor\Unity.exe"
$il2cpp = "C:\Program Files\Unity\Hub\Editor\$env:UNITY_VERSION\Editor\Data\PlaybackEngines\windowsstandalonesupport\Variations\win64_player_nondevelopment_il2cpp"
$missing = @()
if (-not (Test-Path $editor)) { $missing += 'editor' }
if ($env:BACKEND -eq 'IL2CPP' -and -not (Test-Path $il2cpp)) { $missing += 'windows-il2cpp' }
if ($missing.Count -gt 0) {
Write-Output "::error::Unity $env:UNITY_VERSION missing: $($missing -join '+')"
Get-ChildItem "C:\Program Files\Unity\Hub\Editor\" -ErrorAction SilentlyContinue | Format-Table
& $hub -- --headless editors --installed
exit 1
}

Write-Output "Found Unity: $editor"
if ($env:BACKEND -eq 'IL2CPP') { Write-Output "Found IL2CPP: $il2cpp" }

"UNITY_PATH=$editor" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
20 changes: 20 additions & 0 deletions .github/scripts/audience/matrix-shared.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"unity_versions": [
{ "version": "2021.3.45f2", "changeset": "88f88f591b2e" },
{ "version": "6000.4.0f1", "changeset": "8cf496087c8f" },
{ "version": "2022.3.62f2", "changeset": "7670c08855a9" }
],
"scripting_backends": ["IL2CPP", "Mono2x"],
"desktop_targets": [
{ "target": "StandaloneWindows64", "runner": ["self-hosted", "Windows", "X64"], "install_unity_script": ".github/scripts/audience/install-unity-windows.ps1", "run_playmode_script": ".github/scripts/audience/playmode-windows.ps1" },
{ "target": "StandaloneOSX", "runner": ["self-hosted", "macOS", "ARM64"], "install_unity_script": ".github/scripts/audience/install-unity-macos.sh", "run_playmode_script": ".github/scripts/audience/playmode-macos.sh" },
{ "target": "StandaloneLinux64", "runner": "ubuntu-latest-8-cores", "install_unity_script": "", "run_playmode_script": ".github/scripts/audience/playmode-linux.sh" }
],
"mobile_targets": [
{ "target": "Android", "build_player_method": "AndroidBuilder.Build" },
{ "target": "iOS", "build_player_method": "IosBuilder.Build" }
],
"pr_exclude": [
{ "unity": { "version": "2022.3.62f2", "changeset": "7670c08855a9" } }
]
}
118 changes: 118 additions & 0 deletions .github/scripts/audience/playmode-linux-container.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/bin/bash
# Audience SDK PlayMode test runner for Linux: in-container body.
# Runs inside the unityci/editor:ubuntu-X-linux-il2cpp-3 container.
# Caller: .github/scripts/audience/playmode-linux.sh (host-side docker wrapper).

set -uo pipefail

LOG=/github/workspace/artifacts/unity.log
ACTIVATION_LOG=/github/workspace/artifacts/activation.log
RESULTS=/github/workspace/artifacts/test-results.xml
PROJECT=/github/workspace/examples/audience

test_rc=1

activate_license() {
unity-editor -batchmode -nographics -quit \
-username "$UNITY_EMAIL" \
-password "$UNITY_PASSWORD" \
-serial "$UNITY_SERIAL" \
-logFile - 2>&1 | tee "$ACTIVATION_LOG" || true
Comment thread
ImmutableJeffrey marked this conversation as resolved.

if grep -qE "License activation has failed|\[Licensing::Client\] Error: Code [0-9]+" "$ACTIVATION_LOG"; then
echo "::error::Unity license activation failed."
exit 1
fi
if ! grep -qE "Successfully activated the entitlement license" "$ACTIVATION_LOG"; then
echo "::error::Unity license activation: no success marker in log."
exit 1
fi
}

run_tests_with_watchdog() {
# xvfb-run gives Unity a virtual X display. UI Toolkit needs GLX + render;
# llvmpipe in the image provides software OpenGL so no GPU is needed.
# -force-glcore skips the Unity 6 Vulkan init and matches the Unity 2021.3 default path.
xvfb-run -a --server-args="-ac +extension GLX +render -noreset" -- \
unity-editor \
-batchmode \
-force-glcore \
-screen-fullscreen 0 \
-screen-width 320 \
-screen-height 240 \
-projectPath "$PROJECT" \
-runTests \
-testPlatform StandaloneLinux64 \
-testResults "$RESULTS" \
-logFile "$LOG" &
local unity_pid=$!

# Mirror Unity log to job stdout while the editor is alive.
tail --pid=$unity_pid -F "$LOG" 2>/dev/null &

# Watchdog (vs fixed timeout) because per-version run length varies wildly:
# Unity 2021.3 cells finish in ~2 min, Unity 6 in ~22 min, and Unity 6 has a
# known post-test shutdown hang. SIGTERM 30 s after "Test run completed" so
# each cell exits as soon as its suite finishes. 40 min hard cap as fallback.
local deadline=$((SECONDS + 2400))
local flush_deadline=0
local kill_reason=""
while kill -0 "$unity_pid" 2>/dev/null; do
if [ "$SECONDS" -ge "$deadline" ]; then
kill_reason="hard-cap-40m"
break
fi
if [ "$flush_deadline" -eq 0 ] && grep -q "Test run completed" "$LOG" 2>/dev/null; then
flush_deadline=$((SECONDS + 30))
echo "[watchdog] saw \"Test run completed\" at ${SECONDS}s; SIGTERM after 30s flush window"
fi
if [ "$flush_deadline" -gt 0 ] && [ "$SECONDS" -ge "$flush_deadline" ]; then
kill_reason="flush-window-elapsed"
break
fi
sleep 5
done

if [ -n "$kill_reason" ]; then
echo "[watchdog] sending SIGTERM to Unity (reason: $kill_reason)"
kill -TERM "$unity_pid" 2>/dev/null || true
# 15 s grace, then SIGKILL.
for _ in 1 2 3; do
kill -0 "$unity_pid" 2>/dev/null || break
sleep 5
done
if kill -0 "$unity_pid" 2>/dev/null; then
echo "[watchdog] SIGTERM not honored, sending SIGKILL"
kill -KILL "$unity_pid" 2>/dev/null || true
fi
fi

wait "$unity_pid" 2>/dev/null
test_rc=$?
if [ "$kill_reason" = "hard-cap-40m" ]; then
echo "::warning::Unity hit the 40 min hard cap without logging \"Test run completed\". Inspect Player.log."
fi
}

capture_player_log() {
# Player runs in a separate process from the editor; copy its Player.log so
# HTTP traces and OnError fires are captured. Glob across companies / products.
find /root/.config/unity3d -name "Player.log" 2>/dev/null | while IFS= read -r f; do
co=$(basename "$(dirname "$(dirname "$f")")")
pr=$(basename "$(dirname "$f")")
cp "$f" "/github/workspace/artifacts/Player-${co}-${pr}.log" 2>/dev/null || true
done
}

return_license() {
# Always return the seat to keep the activation pool from exhausting on reruns.
unity-editor -batchmode -nographics -quit -returnlicense -logFile - 2>&1 || true
}

activate_license
run_tests_with_watchdog
capture_player_log
return_license

# Unity exits 2 on test failure or inconclusive; propagate so the step fails.
exit "$test_rc"
27 changes: 27 additions & 0 deletions .github/scripts/audience/playmode-linux.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
# Audience SDK PlayMode test runner for Linux: host-side docker wrapper.
# Runs unityci/editor with the env and volume mounts the inner
# playmode-linux-container.sh expects. Lives outside the container so the
# workflow can launch all 3 desktop platforms from one matrix-shared.json entry.
#
# Manual docker run because game-ci/unity-test-runner@v4 hardcodes
# -nographics. Without a virtual display every PlayMode test comes back
# inconclusive, and the action's USE_EXIT_CODE=false suppresses Unity
# exit 2, so cells went silently green.
#
# Workflow caller: .github/workflows/test-audience-sample-app.yml (playmode job).
# Inputs (env): UNITY_VERSION, UNITY_EMAIL, UNITY_PASSWORD, UNITY_SERIAL,
# AUDIENCE_TEST_PUBLISHABLE_KEY, AUDIENCE_SCRIPTING_BACKEND.

set -uo pipefail
mkdir -p artifacts

docker run --rm \
--workdir /github/workspace \
--env UNITY_EMAIL --env UNITY_PASSWORD --env UNITY_SERIAL \
--env AUDIENCE_TEST_PUBLISHABLE_KEY --env AUDIENCE_SCRIPTING_BACKEND \
--env AUDIENCE_TEST_RUN_ID --env AUDIENCE_TEST_CELL_ID --env AUDIENCE_TEST_JOB_ID \
--volume "$PWD":/github/workspace:z \
--cpus=8 --memory=30487m \
"unityci/editor:ubuntu-${UNITY_VERSION}-linux-il2cpp-3" \
bash /github/workspace/.github/scripts/audience/playmode-linux-container.sh
45 changes: 45 additions & 0 deletions .github/scripts/audience/playmode-macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash
# Runs the audience PlayMode tests on macOS. Captures Player.log into artifacts/.
# Surfaces Unity compile errors as ::error:: annotations.
# Workflow caller: .github/workflows/test-audience-sample-app.yml (playmode job).
#
# Inputs (env): UNITY_PATH (set by install-unity-macos.sh), TARGET.

set -uo pipefail

LOG=artifacts/unity.log
RESULTS="$(pwd)/artifacts/test-results.xml"

mkdir -p artifacts

# Tee Unity stdout to artifacts/unity.log so the annotation step has a file
# to scan; pipefail propagates Unity's exit code through tee.
"$UNITY_PATH" \
-batchmode -nographics \
-projectPath examples/audience \
-runTests \
-testPlatform "$TARGET" \
-testResults "$RESULTS" \
-logFile - 2>&1 | tee "$LOG"
test_rc=${PIPESTATUS[0]}

# Player runs as a separate process; copy its Player.log so HTTP traces and
# OnError fires are captured. Glob across companies and products.
src="$HOME/Library/Logs"
if [ -d "$src" ]; then
find "$src" -name "Player.log" 2>/dev/null | while IFS= read -r f; do
cp "$f" "artifacts/Player-$(basename "$(dirname "$f")").log" 2>/dev/null || true
done
fi

# Promote Unity compile errors to ::error:: annotations. Sanitize '::' so log
# lines containing workflow commands cannot terminate the annotation early.
if [ -f "$LOG" ]; then
grep -E '(error CS[0-9]+:|Compilation failed:)' "$LOG" | sort -u | while IFS= read -r line; do
trimmed="${line#"${line%%[![:space:]]*}"}"
sanitized="${trimmed//::/%3A%3A}"
echo "::error::$sanitized"
done || true
fi

exit "$test_rc"
Loading
Loading