diff --git a/.github/workflows/test-audience-sample-app.yml b/.github/workflows/test-audience-sample-app.yml index d8a0d9fb..bf3e4167 100644 --- a/.github/workflows/test-audience-sample-app.yml +++ b/.github/workflows/test-audience-sample-app.yml @@ -433,6 +433,66 @@ jobs: artifacts/Player-*.log examples/audience/Logs/** + # Linux PlayMode runs on GitHub-hosted Ubuntu via GameCI Docker, not on the + # self-hosted matrix above, to keep self-hosted machines free for Win/macOS. + playmode-linux: + if: github.event.pull_request.head.repo.fork == false || github.event_name == 'workflow_dispatch' + name: ${{ matrix.target }} / ${{ matrix.backend }} / Unity ${{ matrix.unity }} + runs-on: ubuntu-latest-8-cores + strategy: + fail-fast: false + matrix: + include: + - target: StandaloneLinux64 + backend: IL2CPP + unity: 2021.3.45f2 + - target: StandaloneLinux64 + backend: Mono2x + unity: 2021.3.45f2 + + steps: + - uses: actions/checkout@v4 + with: + lfs: true + + - uses: actions/cache@v4 + with: + path: examples/audience/Library + key: Library-${{ matrix.backend }}-${{ matrix.target }}-${{ matrix.unity }}-${{ hashFiles('examples/audience/Assets/**', 'examples/audience/Packages/**', 'examples/audience/ProjectSettings/**', 'src/Packages/Audience/**') }} + restore-keys: | + Library-${{ matrix.backend }}-${{ matrix.target }}-${{ matrix.unity }}- + Library-${{ matrix.backend }}-${{ matrix.target }}- + + - uses: game-ci/unity-test-runner@v4 + id: playmode + env: + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} + AUDIENCE_TEST_PUBLISHABLE_KEY: ${{ secrets.AUDIENCE_TEST_PUBLISHABLE_KEY }} + AUDIENCE_SCRIPTING_BACKEND: ${{ matrix.backend }} + with: + unityVersion: ${{ matrix.unity }} + targetPlatform: ${{ matrix.target }} + projectPath: examples/audience + testMode: playmode + githubToken: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish test report + uses: dorny/test-reporter@v3 + if: always() + with: + name: PlayMode (${{ matrix.backend }} / ${{ matrix.target }}) + path: ${{ steps.playmode.outputs.artifactsPath }}/playmode-results.xml + reporter: dotnet-nunit + fail-on-error: true + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playmode-${{ matrix.backend }}-${{ matrix.target }}-${{ matrix.unity }} + path: ${{ steps.playmode.outputs.artifactsPath }} + # Mobile IL2CPP build validation — runs on GitHub-hosted Ubuntu via GameCI Docker # containers so self-hosted macOS/Windows machines are not occupied. # Scope: IL2CPP compile pipeline only. Runtime tests require a real device and @@ -498,3 +558,111 @@ jobs: path: | examples/audience/Builds/Android/*.apk examples/audience/Logs/** + + # workflow_dispatch only. Cross-checks the GameCI Docker outcome against + # the self-hosted Linux machine when there's reason to suspect divergence. + playmode-linux-selfhosted: + if: github.event_name == 'workflow_dispatch' + name: ${{ matrix.backend }} / Unity ${{ matrix.unity }} (self-hosted Linux) + runs-on: [self-hosted, X64, Linux] + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + include: + - backend: IL2CPP + unity: 2021.3.45f2 + - backend: Mono2x + unity: 2021.3.45f2 + + steps: + - uses: actions/checkout@v4 + with: + lfs: true + + - uses: actions/cache@v4 + with: + path: examples/audience/Library + key: Library-selfhosted-${{ matrix.backend }}-StandaloneLinux64-${{ matrix.unity }}-${{ hashFiles('examples/audience/Assets/**', 'examples/audience/Packages/**', 'examples/audience/ProjectSettings/**', 'src/Packages/Audience/**') }} + restore-keys: | + Library-selfhosted-${{ matrix.backend }}-StandaloneLinux64-${{ matrix.unity }}- + Library-selfhosted-${{ matrix.backend }}-StandaloneLinux64- + + - name: Resolve Unity + shell: bash + run: | + set -uo pipefail + UNITY="$HOME/Unity/Hub/Editor/${{ matrix.unity }}/Editor/Unity" + if [ ! -x "$UNITY" ]; then + echo "::error::Unity ${{ matrix.unity }} not found at $UNITY. Install via Unity Hub on the runner host." + exit 1 + fi + echo "UNITY_PATH=$UNITY" >> "$GITHUB_ENV" + + - name: Activate Unity license + shell: bash + env: + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} + run: | + set -uo pipefail + LOG="$(mktemp)" + "$UNITY_PATH" -batchmode -nographics -quit \ + -username "$UNITY_EMAIL" \ + -password "$UNITY_PASSWORD" \ + -serial "$UNITY_SERIAL" \ + -logFile - 2>&1 | tee "$LOG" || true + + if grep -qE "(License activation has failed|\[Licensing::Client\] Error: Code [0-9]+)" "$LOG"; then + echo "::error::Unity activation failed." + exit 1 + fi + if ! grep -qE "Successfully activated the entitlement license" "$LOG"; then + echo "::error::Unity activation: no success marker found." + exit 1 + fi + + - name: Run PlayMode tests + shell: bash + env: + AUDIENCE_TEST_PUBLISHABLE_KEY: ${{ secrets.AUDIENCE_TEST_PUBLISHABLE_KEY }} + AUDIENCE_SCRIPTING_BACKEND: ${{ matrix.backend }} + run: | + set -euo pipefail + mkdir -p artifacts + "$UNITY_PATH" \ + -batchmode -nographics \ + -projectPath examples/audience \ + -runTests \ + -testPlatform StandaloneLinux64 \ + -testResults "$(pwd)/artifacts/test-results.xml" \ + -logFile - 2>&1 | tee "$(pwd)/artifacts/unity.log" + + - name: Return Unity license + if: always() + shell: bash + run: | + set -uo pipefail + # Releases the seat after every run so manual reruns do not exhaust + # the serial's activation pool. + if [ -n "${UNITY_PATH:-}" ] && [ -x "$UNITY_PATH" ]; then + "$UNITY_PATH" -returnlicense -batchmode -nographics -quit -logFile - 2>&1 || true + fi + + - name: Publish test report + uses: dorny/test-reporter@v3 + if: always() + with: + name: Self-hosted Linux PlayMode (${{ matrix.backend }}) + path: artifacts/test-results.xml + reporter: dotnet-nunit + fail-on-error: true + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: selfhosted-linux-${{ matrix.backend }} + path: | + artifacts/test-results.xml + artifacts/unity.log diff --git a/src/Packages/Audience/Runtime/Unity/com.immutable.audience.unity.asmdef b/src/Packages/Audience/Runtime/Unity/com.immutable.audience.unity.asmdef index 9a03d62a..2ba8c0b9 100644 --- a/src/Packages/Audience/Runtime/Unity/com.immutable.audience.unity.asmdef +++ b/src/Packages/Audience/Runtime/Unity/com.immutable.audience.unity.asmdef @@ -2,7 +2,7 @@ "name": "Immutable.Audience.Unity", "rootNamespace": "Immutable.Audience.Unity", "references": ["Immutable.Audience.Runtime"], - "includePlatforms": ["Android", "Editor", "iOS", "macOSStandalone", "WindowsStandalone64"], + "includePlatforms": ["Android", "Editor", "iOS", "LinuxStandalone64", "macOSStandalone", "WindowsStandalone64"], "excludePlatforms": [], "allowUnsafeCode": false, "overrideReferences": false, diff --git a/src/Packages/Audience/Runtime/com.immutable.audience.asmdef b/src/Packages/Audience/Runtime/com.immutable.audience.asmdef index 0288815d..acc15719 100644 --- a/src/Packages/Audience/Runtime/com.immutable.audience.asmdef +++ b/src/Packages/Audience/Runtime/com.immutable.audience.asmdef @@ -2,7 +2,7 @@ "name": "Immutable.Audience.Runtime", "rootNamespace": "Immutable.Audience", "references": [], - "includePlatforms": ["Android", "Editor", "iOS", "macOSStandalone", "WindowsStandalone64"], + "includePlatforms": ["Android", "Editor", "iOS", "LinuxStandalone64", "macOSStandalone", "WindowsStandalone64"], "excludePlatforms": [], "allowUnsafeCode": false, "overrideReferences": false,