Skip to content

ci(audience): Linux PlayMode under xvfb (SDK-317 / SDK-318)#765

Closed
ImmutableJeffrey wants to merge 8 commits into
chore/sdk-317-audience-linux-platform-supportfrom
chore/audience-linux-perf-test-polling
Closed

ci(audience): Linux PlayMode under xvfb (SDK-317 / SDK-318)#765
ImmutableJeffrey wants to merge 8 commits into
chore/sdk-317-audience-linux-platform-supportfrom
chore/audience-linux-perf-test-polling

Conversation

@ImmutableJeffrey
Copy link
Copy Markdown
Collaborator

@ImmutableJeffrey ImmutableJeffrey commented May 9, 2026

Summary

Adds Linux PlayMode CI for the Audience SDK sample app, with the perf trims that bring Unity 6 cell wall time down from initial-failure to ~22-25 min, plus diagnostics and one SDK fix surfaced by the investigation.

CI workflow

  • Adds playmode-linux job running under xvfb inside the unityci/editor:ubuntu-...-linux-il2cpp-3 container. The image ships both Mono and IL2CPP playback engines plus xvfb, so one tag covers both backends.
  • Replaces game-ci/unity-test-runner@v4 with manual docker run because the action hardcodes -batchmode -nographics, so PlayMode tests came back inconclusive and silently passed.
  • Watchdog SIGTERMs Unity 30s after seeing Test run completed so cells exit on suite finish; handles Unity 6's known post-test shutdown hang. 40 min hard cap as fallback.
  • Replaces cartesian + partial-include matrix with explicit per-cell entries; partial includes failed to merge the runner column and spawned zero tests.
  • Captures standalone player log alongside the editor log; surfaces the CI provenance line to the job summary.
  • Defense-in-depth step that fails the cell when zero tests executed (NUnit "inconclusive" doesn't fail the job by default).

Perf trims (Unity 6 Linux)

  • GraphicsApisLinuxOverride build hook forces StandaloneLinux64 to OpenGLCore-only at build time, skipping Vulkan shader variants the runtime never uses.
  • LinuxLogPaneSuppression setup-fixture hides the in-app log ScrollView on Unity 6 Linux, skipping llvmpipe rasterising thousands of UI Toolkit triangles per frame.
  • Adds -force-glcore to skip Unity 6's Vulkan init negotiation.

Diagnostics

  • LogCiProvenance runtime hook stamps [CI] buildGuid=... runId=... cellId=... into Player.log on player startup. Gated to CI runs only.
  • Mirrors OnError and Log.Writer output to Debug.Log so SDK warnings and failure callbacks reach Player.log, not just the in-app pane.
  • PlayerProfilerLogger runtime hook writes a Unity profiler binary log when AUDIENCE_PLAYER_PROFILE_PATH is set.
  • Adds audience_ci_test_marker PlayMode test that emits a CDP marker row so this run's events can be filtered out of analytics.

SDK fix

  • DiskStore.ReadBatch now treats DirectoryNotFoundException as empty queue, matching the existing guards in DeleteAll and ApplyAnonymousDowngrade. Prevents external test cleanup or persistentDataPath wipes from surfacing as OnError.

Sample-app cleanup

  • Trims 30 unused packages and engine modules from examples/audience/Packages/manifest.json.

Linear: SDK-317, SDK-318, SDK-340, SDK-341

ImmutableJeffrey and others added 7 commits May 7, 2026 19:42
…s checkout (SDK-330)

- Replaces the cross-product matrix (unity x target x backend with
  axis-matching include items) on `playmode` with a `set-matrix` helper
  job that emits a fully-specified JSON matrix.
- The cross-product approach silently expanded to zero playmode cells
  on every run since SDK-327, so Windows and macOS PlayMode tests have
  not actually run on PRs (verified on the SDK-327 merge commit and on
  PR #748). Root cause: a unity-keyed include item that has no cell to
  augment after the conditional `exclude` removes Unity 2022 on PR runs
  spawns an orphan combination missing `target`, `backend`, and
  `runner`; `runs-on: ${{ matrix.runner }}` then evaluates to empty and
  GitHub aborts the matrix.
- `set-matrix` runs on ubuntu-latest, defines the full 12-cell playmode
  matrix, 6-cell playmode-linux matrix and 6-cell mobile matrix inline
  as JSON, and uses jq to strip Unity 2022.3.62f2 cells when the
  trigger is pull_request. Schedule and workflow_dispatch get the full
  sets.
- All three matrix-driven jobs now declare `needs: set-matrix` and
  consume `matrix.include: fromJSON(needs.set-matrix.outputs.<key>)`.
  Each cell carries every key the steps need, so no axis-match
  augmentation step can silently drop keys, and the workflow graph
  shows all three jobs hanging off set-matrix in one place.
- `mobile-build` PR runs drop Unity 2022.3.62f2 to match the playmode
  and playmode-linux trim. Schedule and workflow_dispatch keep all 3
  Unity versions. Steps unchanged.
- `playmode-linux` matrix moved from cross-product + conditional
  exclude to the same set-matrix-fed include pattern. Same 6 cells on
  schedule, same 4 cells on PR; behaviour unchanged.
- Hardens the Windows pre-checkout cleanup. The previous Kill-stale step
  only covered Unity-family processes and slept 2 seconds, then handed
  off to actions/checkout@v4 which would die with EBUSY on stuck files
  in examples/audience. New step adds bee_backend and mono to the kill
  list, sleeps 3 seconds, and force-removes the workspace contents in a
  retry loop so checkout's own cleanup is left with nothing to do.

Linear: https://linear.app/imtbl/issue/SDK-330

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures the Google Play install referrer via the vendored
installreferrer-2.2 AAR and ships it as a dedicated install_referrer_received
event (decoupled from game_launch). The async fetch typically completes
after the first Init has fired, so the event lands on the next launch
from the on-disk cache; an idempotency marker ensures it fires exactly
once per install.

Both the build-time AUDIENCE_MOBILE_ATTRIBUTION scripting define and the
runtime AudienceConfig.EnableMobileAttribution flag must be set for the
fetch to run. The Init-time consent gate blocks the network call when
consent is None, regardless of the flag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eferrer

feat(audience-sdk): Android Play Install Referrer support (SDK-310)
Capture the Google Advertising ID and limitAdTracking flag via JNI to
AdvertisingIdClient. Ships on game_launch when AUDIENCE_MOBILE_ATTRIBUTION
is defined, EnableMobileAttribution is on, and the studio has added
play-services-ads-identifier to their gradle dependencies. Async fetch
runs on a dedicated worker thread; first launch ships nothing, launch #2
onwards ships the previously cached value.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(audience-sdk): add Android GAID collection (SDK-309)
…ferrer to Full-only (SDK-331)

idfa, gaid, and installReferrer are cross-app / campaign-source
identifiers in the same privacy class as userId. Previously they shipped
at Anonymous+Full (CanTrack); this sweep re-tiers them to Full-only
(CanIdentify), matching the existing userId gate.

State-class properties (attStatus, gaidLimitAdTracking, skanRegistered)
are non-identifying and remain at Anonymous+Full unchanged.

The install_referrer_received sent-marker is intentionally not written
when consent is Anonymous, so a later upgrade to Full can fire the event
on the next launch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…on-consent

feat(audience-sdk): tighten attribution consent tiers - idfa/gaid/installReferrer to Full-only (SDK-331)
ImmutableJeffrey added a commit that referenced this pull request May 9, 2026
Commit e7718f6 added a comment block above the xvfb-run line that
contained 'xvfb's own screen size'. The apostrophe terminated the outer
bash -c '...' single-quoted heredoc, the rest of the inner script
became outer-shell tokens, and every Linux PlayMode cell on PR #765
exited 1 right after license activation (cell time 90 seconds).

Rewords the comment without the apostrophe. No semantic change to the
docker invocation or the Unity command line.
ImmutableJeffrey added a commit that referenced this pull request May 9, 2026
…SampleApp

Drops 30 of 39 manifest.json entries that the SampleApp does not use.
Verified by grepping the SampleApp source, the SampleApp scene, and
the Audience SDK runtime for any reference to each removed module or
package.

Removed packages:
- com.unity.textmeshpro: no TMP_Text or TMPro references
- com.unity.timeline: no PlayableDirector or TimelineAsset references
- com.unity.ugui: SampleApp uses UI Toolkit, no Canvas references
- com.unity.visualscripting: no ScriptMachine or graph references

Removed engine modules:
- ai, animation, assetbundle, cloth, director, imageconversion,
  particlesystem, physics, physics2d, screencapture, terrain,
  terrainphysics, tilemap, ui, umbra, unityanalytics, vehicles, video,
  vr, wind, xr: no runtime references in SampleApp or audience SDK
- unitywebrequestassetbundle, unitywebrequestaudio,
  unitywebrequesttexture, unitywebrequestwww: SDK uses
  System.Net.Http.HttpClient, not UnityWebRequest variants

Kept (verified used or required):
- com.immutable.audience: the SDK
- com.unity.test-framework: test runner
- com.unity.modules.androidjni: Android plugin compatibility
- com.unity.modules.audio: AudioListener present in SampleApp scene
- com.unity.modules.imgui: test runner overlay
- com.unity.modules.jsonserialize: defensive
- com.unity.modules.uielements: UI Toolkit, primary UI surface
- com.unity.modules.unitywebrequest: defensive (test framework)

Expected impact:
- Smaller IL2CPP and Mono player binaries.
- Faster IL2CPP compile and Bee/Tundra build phases on every cell.
- Faster project init (less to load, fewer InitializeOnLoad hooks).
- Per-frame UI Toolkit cost on llvmpipe is unchanged; that is targeted
  separately by PR #765's log-pane suppression.

Risk: a build link error on a platform that needs a removed module
shows immediately in CI; revert is one-line.
@ImmutableJeffrey ImmutableJeffrey force-pushed the chore/audience-linux-perf-test-polling branch from 153b0f8 to cf5e5d9 Compare May 10, 2026 04:11
@ImmutableJeffrey ImmutableJeffrey changed the title perf(audience): decouple test polling from frame pacing on Linux PlayMode ci(audience): Linux PlayMode under xvfb (SDK-317 / SDK-318) May 10, 2026
@ImmutableJeffrey ImmutableJeffrey changed the base branch from chore/sdk-318-linux-playmode-xvfb to chore/sdk-317-audience-linux-platform-support May 10, 2026 04:11
@ImmutableJeffrey ImmutableJeffrey force-pushed the chore/audience-linux-perf-test-polling branch 9 times, most recently from 35d3c67 to 7678ccf Compare May 10, 2026 14:13
- Reworks playmode-linux to run inside a docker container under xvfb, via
  .github/scripts/audience/playmode-linux.sh. game-ci/unity-test-runner@v4
  hardcodes -nographics, so PlayMode tests came back inconclusive and silently
  passed.
- Watchdog SIGTERMs Unity 30s after "Test run completed" so cells exit on suite
  finish; handles Unity 6's known shutdown hang.
- -force-glcore at runtime skips the Unity 6 Vulkan init and matches the Unity
  2021.3 default path.
- Suppresses in-app log pane on Unity 6 Linux to skip llvmpipe rasterising UI
  Toolkit triangles per frame.
- Stamps CI build info into Player.log on player startup; gated to CI runs only.
- Mirrors SDK output and OnError fires to Debug.Log so failures land in
  Player.log.
- DiskStore.ReadBatch treats missing queue dir as empty (matches existing
  guards).
- Live-fire test SetUp ignores cleanup-time OnError fires so background flush
  cancellations do not fail unrelated tests.
- Trims 30 unused packages from the sample-app manifest.
- Extracts the macOS and Windows playmode runners and the Windows VS Build
  Tools setup to .github/scripts/, mirroring the Linux pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ImmutableJeffrey ImmutableJeffrey force-pushed the chore/audience-linux-perf-test-polling branch from 7678ccf to 0bdc64e Compare May 10, 2026 14:35
ImmutableJeffrey added a commit that referenced this pull request May 10, 2026
…SampleApp

Drops 30 of 39 manifest.json entries that the SampleApp does not use.
Verified by grepping the SampleApp source, the SampleApp scene, and
the Audience SDK runtime for any reference to each removed module or
package.

Removed packages:
- com.unity.textmeshpro: no TMP_Text or TMPro references
- com.unity.timeline: no PlayableDirector or TimelineAsset references
- com.unity.ugui: SampleApp uses UI Toolkit, no Canvas references
- com.unity.visualscripting: no ScriptMachine or graph references

Removed engine modules:
- ai, animation, assetbundle, cloth, director, imageconversion,
  particlesystem, physics, physics2d, screencapture, terrain,
  terrainphysics, tilemap, ui, umbra, unityanalytics, vehicles, video,
  vr, wind, xr: no runtime references in SampleApp or audience SDK
- unitywebrequestassetbundle, unitywebrequestaudio,
  unitywebrequesttexture, unitywebrequestwww: SDK uses
  System.Net.Http.HttpClient, not UnityWebRequest variants

Kept (verified used or required):
- com.immutable.audience: the SDK
- com.unity.test-framework: test runner
- com.unity.modules.androidjni: Android plugin compatibility
- com.unity.modules.audio: AudioListener present in SampleApp scene
- com.unity.modules.imgui: test runner overlay
- com.unity.modules.jsonserialize: defensive
- com.unity.modules.uielements: UI Toolkit, primary UI surface
- com.unity.modules.unitywebrequest: defensive (test framework)

Expected impact:
- Smaller IL2CPP and Mono player binaries.
- Faster IL2CPP compile and Bee/Tundra build phases on every cell.
- Faster project init (less to load, fewer InitializeOnLoad hooks).
- Per-frame UI Toolkit cost on llvmpipe is unchanged; that is targeted
  separately by PR #765's log-pane suppression.

Risk: a build link error on a platform that needs a removed module
shows immediately in CI; revert is one-line.
ImmutableJeffrey added a commit that referenced this pull request May 10, 2026
…SampleApp

Drops 30 of 39 manifest.json entries that the SampleApp does not use.
Verified by grepping the SampleApp source, the SampleApp scene, and
the Audience SDK runtime for any reference to each removed module or
package.

Removed packages:
- com.unity.textmeshpro: no TMP_Text or TMPro references
- com.unity.timeline: no PlayableDirector or TimelineAsset references
- com.unity.ugui: SampleApp uses UI Toolkit, no Canvas references
- com.unity.visualscripting: no ScriptMachine or graph references

Removed engine modules:
- ai, animation, assetbundle, cloth, director, imageconversion,
  particlesystem, physics, physics2d, screencapture, terrain,
  terrainphysics, tilemap, ui, umbra, unityanalytics, vehicles, video,
  vr, wind, xr: no runtime references in SampleApp or audience SDK
- unitywebrequestassetbundle, unitywebrequestaudio,
  unitywebrequesttexture, unitywebrequestwww: SDK uses
  System.Net.Http.HttpClient, not UnityWebRequest variants

Kept (verified used or required):
- com.immutable.audience: the SDK
- com.unity.test-framework: test runner
- com.unity.modules.androidjni: Android plugin compatibility
- com.unity.modules.audio: AudioListener present in SampleApp scene
- com.unity.modules.imgui: test runner overlay
- com.unity.modules.jsonserialize: defensive
- com.unity.modules.uielements: UI Toolkit, primary UI surface
- com.unity.modules.unitywebrequest: defensive (test framework)

Expected impact:
- Smaller IL2CPP and Mono player binaries.
- Faster IL2CPP compile and Bee/Tundra build phases on every cell.
- Faster project init (less to load, fewer InitializeOnLoad hooks).
- Per-frame UI Toolkit cost on llvmpipe is unchanged; that is targeted
  separately by PR #765's log-pane suppression.

Risk: a build link error on a platform that needs a removed module
shows immediately in CI; revert is one-line.
ImmutableJeffrey added a commit that referenced this pull request May 10, 2026
…SampleApp

Drops 30 of 39 manifest.json entries that the SampleApp does not use.
Verified by grepping the SampleApp source, the SampleApp scene, and
the Audience SDK runtime for any reference to each removed module or
package.

Removed packages:
- com.unity.textmeshpro: no TMP_Text or TMPro references
- com.unity.timeline: no PlayableDirector or TimelineAsset references
- com.unity.ugui: SampleApp uses UI Toolkit, no Canvas references
- com.unity.visualscripting: no ScriptMachine or graph references

Removed engine modules:
- ai, animation, assetbundle, cloth, director, imageconversion,
  particlesystem, physics, physics2d, screencapture, terrain,
  terrainphysics, tilemap, ui, umbra, unityanalytics, vehicles, video,
  vr, wind, xr: no runtime references in SampleApp or audience SDK
- unitywebrequestassetbundle, unitywebrequestaudio,
  unitywebrequesttexture, unitywebrequestwww: SDK uses
  System.Net.Http.HttpClient, not UnityWebRequest variants

Kept (verified used or required):
- com.immutable.audience: the SDK
- com.unity.test-framework: test runner
- com.unity.modules.androidjni: Android plugin compatibility
- com.unity.modules.audio: AudioListener present in SampleApp scene
- com.unity.modules.imgui: test runner overlay
- com.unity.modules.jsonserialize: defensive
- com.unity.modules.uielements: UI Toolkit, primary UI surface
- com.unity.modules.unitywebrequest: defensive (test framework)

Expected impact:
- Smaller IL2CPP and Mono player binaries.
- Faster IL2CPP compile and Bee/Tundra build phases on every cell.
- Faster project init (less to load, fewer InitializeOnLoad hooks).
- Per-frame UI Toolkit cost on llvmpipe is unchanged; that is targeted
  separately by PR #765's log-pane suppression.

Risk: a build link error on a platform that needs a removed module
shows immediately in CI; revert is one-line.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants