Skip to content

Dev/android api alignment - #431

Open
af-obodovskyi wants to merge 40 commits into
developmentfrom
dev/android-api-alignment
Open

Dev/android api alignment#431
af-obodovskyi wants to merge 40 commits into
developmentfrom
dev/android-api-alignment

Conversation

@af-obodovskyi

Copy link
Copy Markdown

No description provided.

af-obodovskyi and others added 30 commits September 6, 2026 17:55
The greps that print xcodebuild errors to the console only match
"Undefined symbols" / ld / clang / error: patterns, so a BUILD FAILED
caused by anything else leaves no diagnosable output. Persist the full
/tmp/xcode-build.log as an artifact, mirroring the unity-build-log-ios
fix.
…ore iOS xcodebuild

Root-caused a "'AppsFlyerLib.h' file not found" xcodebuild failure via the
downloaded xcode-build.log: the AppsFlyerLib-Dynamic SPM package (fetched
over the network as part of xcodebuild's implicit package resolution) never
produced a fully-populated framework before the compile step ran, but
xcodebuild build didn't surface this as a resolution error — it silently
proceeded and failed deep in an unrelated-looking compile. The identical
build succeeds locally, confirming this is a CI-only resolution flake, not
a plugin/config defect.

Add an explicit `xcodebuild -resolvePackageDependencies` step with 3 retries
before the compile step, so a network flake fails loudly and recovers on
retry instead of masquerading as a missing-header compile error. Also
upload its log as an artifact for future diagnosability.
Root cause of the "AppsFlyerLib.h file not found" xcodebuild failure:
Unity's bundled (Mono) System.Xml reader throws "An XML comment cannot
contain '--'" when parsing the em dash (—, U+2014) in these two comments,
even though no literal double-hyphen is present. EDM4U's IOSResolver
catches that XmlException and silently discards ALL iOS dependencies
("iOS dependencies in this file will be ignored"), so no Swift Package
references (AppsFlyerLib, AppsFlyerRPC, PurchaseConnector) ever get added
to the exported Xcode project — confirmed via unity-build.log from the
failing CI run, and via the paired xcode-resolve.log showing zero
resolved packages.

This is a real, deterministic parser bug in the CI Unity Editor's XML
reader, not a network flake — the previous xcodebuild -resolvePackageDependencies
retry step (commit 1cd1476) was chasing the wrong hypothesis and had no
effect, since resolution correctly found nothing to resolve.
scripts/bump-version.sh used unanchored sed patterns like
`af-android-plugin-bridge:[^"]*` to bump version specs in
AppsFlyerDependencies.xml. These also matched the same coordinate
mentioned in free-text comment prose, greedily eating everything up
to the next unrelated quote later in the file — including the
closing `-->` of a comment. That's what corrupted the file on the
7.0.2-rc1 release branch (commit 00bdfd2), which then made Unity's
XML reader throw on the next comment's "<!--" and silently drop all
iOS dependencies, causing the "AppsFlyerLib.h file not found"
xcodebuild failure.

Anchors the three vulnerable patterns to spec="..." so they can only
match inside the actual XML attribute value, and removes the two
comments whose prose repeated a version-like substring, so there's
nothing left for a regression to latch onto.
…tting

EDM4U's Google.IOSResolver.SwiftPackageManagerEnabled=True setting lived only
in the gitignored test-app/ProjectSettings/GvhProjectSettings.xml, added in
090ffe8 alongside the genuinely-regenerated AndroidResolverDependencies.xml
under a "regenerated on every build" comment. It isn't regenerated from
scratch - it's a persisted, hand-set setting. Every fresh CI checkout got
EDM4U's own default (Podfile mode) instead, and since rc-e2e-ios.yml has no
pod install step, iOS builds failed to find AppsFlyerLib.h once the earlier
XML corruption bug was fixed.
…upport)

test-app (the project rc-e2e-ios.yml actually builds) was still on EDM4U
1.2.183, which has no SwiftPackageManagerEnabled property and doesn't
recognize <remoteSwiftPackage> at all - it silently ignores those elements
and falls back to the Podfile-style <iosPod> entries instead. rc-e2e-ios.yml
has no `pod install` step, so those pods never get installed, leaving
AppsFlyerLib.h missing regardless of the XML-corruption fix or the
GvhProjectSettings.xml settings fix already applied.

The root Unity project (Assets/ExternalDependencyManager) was already on
1.2.187; test-app's copy just hadn't been upgraded to match. xcode-resolve.log
confirmed this: "resolved source packages:" came back empty even after
SwiftPackageManagerEnabled=True was committed, because the old resolver
DLL doesn't have that property at all.
QATestScript implements IAppsFlyerConversionData (onConversionDataSuccess/
onConversionDataFail) but the plugin no longer dispatches conversion data by
directly invoking that interface on the init() gameObject - native only ever
calls UnitySendMessage(CallBackObjectName, "onRPCEvent", ...), and onRPCEvent
only forwards to onConversionDataSuccessCallback/onConversionDataFailCallback,
which are populated solely by AppsFlyer.registerConversionListener(). Since
QATestScript never called it, the E2E "is_first_launch_true" check always
failed waiting for a callback that had nowhere to route to - unrelated to the
build-pipeline fixes already applied (XML corruption, GvhProjectSettings.xml,
EDM4U 1.2.183->1.2.187).
…plicate

registerConversionListener was already called in QATestScript, just after
init()/the Android lifecycle nudge instead of before it - my previous commit
missed that (grepped for it in other files but not this one) and added a
second, redundant call instead of fixing the placement of the existing one.

Real bug: the local onConversionDataSuccessCallback/onConversionDataFailCallback
delegates are only set once registerConversionListener() runs its synchronous
prefix, but native can fire onInstallConversionData as soon as init()'s
"initialize" RPC call lands. Registering after init() (and after an Android-only
lifecycle nudge) left a window where the event had already fired with no
delegate listening, and it was silently dropped. Moved the one real call to
before AppsFlyer.init(), removed the now-redundant later one.
Screenshot from unity-e2e-ios-20260907_010443 (phase_1_screen.png) shows the
ATT "Allow tracking" system dialog still on screen ~5 minutes after launch -
unanswered, because there's no one in CI to tap it. Per ATTPermissionRequest.mm's
own comment, once that dialog appears the whole app is suspended at the OS
level until it's dismissed. That's why nothing downstream ever happened:
AppsFlyer's install_data/conversions network requests sat cancelled/in-flight
for the full wait window (see phase_1_logs.txt quic-connection entries) and
onInstallConversionData never fired - not a plugin bug, the app was just
frozen behind a modal nobody could answer.

`xcrun simctl privacy` has no "tracking" service to pre-grant, so the request
is now opt-in via .env (REQUEST_ATT=true), defaulting to skipped since none
of the six E2E scenarios (E2E-001..006) exercise the ATT flow.
…ocking deep links

The Obj-C++ -> Swift RPC transport migration (1507c8c) deleted the old
_startSDK's isBridgeReady=YES + AF_BRIDGE_SET notification (previously fired
synchronously as _startSDK's first statement, before startWithCompletionHandler)
without carrying the equivalent into AppsFlyerRPCWrapper.swift. isBridgeReady
gates AppsFlyerAttribution's handleOpenUrl:/continueUserActivity: (see
AppsFlyerAttribution.m) and was left permanently NO, so every iOS deep link
delivered via those paths was silently and permanently dropped, regardless of
timing - a real regression, not a CI/test-app issue, confirmed by phase_2/
phase_3 E2E runs never logging a single onDeepLinking callback.

Restore it by having AppsFlyerRPCWrapper.swift's _afFireJson/_afExecuteJson
detect the "start" RPC method (raw substring match on the request JSON, same
technique already used for response error-detection in this file) and call a
new tiny Obj-C shim, _afMarkBridgeReady() in AppsFlyerAttribution.m, that sets
isBridgeReady and posts AF_BRIDGE_SET exactly as the old wrapper did.
Latest run confirms deep links now arrive (deepLinkValue correctly populated
after the bridge-ready fix), but deeplink_found/deeplink_found_fg still fail:
DeepLinkEventsArgs' status ends up ERROR instead of the expected FOUND.

DeepLinkEventsArgs' constructor only recognizes literal "FOUND"/"NOT_FOUND" and
silently collapses anything else - including a genuinely successful native
result under some other spelling - into DeepLinkStatus.ERROR, discarding the
original string. AFSDKDeepLinkResultStatus (AppsFlyerLib) is a 3-case ObjC
NSUInteger enum (NotFound/Found/Failure) with no built-in string form, and nothing
in the vendored AppsFlyerRPC.framework binary contains literal "FOUND"/
"NOT_FOUND"/"FAILURE" strings - suggesting whatever serializes this enum to
JSON may not be emitting the casing our switch expects, but this can't be
confirmed from a closed-source binary alone.

Add DeepLinkEventsArgs.rawStatus (the untouched original string) and log it
from QATestScript so the next E2E run shows the literal wire value, before
changing the status-mapping logic based on a guess.
The iOS RPC bridge emits lowercase status/error strings (e.g. "found"),
but DeepLinkEventsArgs matched only uppercase literals ("FOUND"),
so valid deep links were misreported as DeepLinkStatus.ERROR.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…emplate.properties

CI Android builds failed with:
  gradleTemplate.properties should contain "unityStreamingAssets=**STREAMING_ASSETS**"
Unity requires this placeholder to mark StreamingAssets files as
uncompressed in the APK; it was missing from the committed template.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
AppsFlyerUnityActivity.java was migrated to extend UnityPlayerGameActivity
and the manifest theme to BaseUnityGameActivityTheme in 5b65e70, but
Player Settings was never flipped from Activity-only (1) to GameActivity
(2) to match — so Unity's Android build never generated the
UnityPlayerGameActivity class or theme resource the migration depends on,
failing the Build Android APK CI step with "cannot find symbol:
UnityPlayerGameActivity" and a missing BaseUnityGameActivityTheme
resource. Reproduced locally with the old value and confirmed the fix
clears both errors and produces a working APK.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
AppsFlyer.cs's BeforeSceneLoad bootstrap calls init() once with an empty
callback name before any scene exists, then AppsFlyer.init() calls it again
with the real one. Every call used to unconditionally rebuild sHandler,
discarding whatever the throwaway first instance had already set up.
QATestScript deliberately calls registerConversionListener/
registerDeepLinkListener before AppsFlyer.init() (to avoid missing early
native events), so those registrations always ran against the first,
disposable handler and were silently orphaned the moment the real init()
call replaced it — meaning onInstallConversionData/onConversionDataSuccess/
onConversionDataFail never reached Unity. Deep-link delivery masked this
because native resolves deep links independent of listener registration.

Verified locally: built the patched wrapper AAR, rebuilt the test APK
against it, and confirmed via a fresh install + full-scenario E2E run that
onConversionDataSuccess now fires and is_first_launch_true passes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…tring

090ffe8 switched DeepLinkEventsArgs to read "deepLink" directly as an
already-nested Dictionary (matching iOS's native RPC framework, which emits
a real nested object), but Android's RPC bridge serializes "deepLink" as a
JSON-encoded string inside the envelope. The type check silently failed on
Android, so deepLinkValue and every other deep-link parameter always came
back empty even though status correctly reported FOUND — deep-link
detection worked, but none of the actual deep-link data reached Unity.

Now handles both shapes: a nested Dictionary (iOS) or a JSON string that
still needs decoding (Android).

Verified locally: rebuilt the test APK and confirmed via the E2E scenario
suite that deeplink_value_bg/deeplink_value_fg now pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
BuildScript.BuildAndroid targets ARM64 only — Unity 6 dropped x86_64
Android build support (AndroidArchitecture no longer has an X86_64 member),
so 8fc9105 removing it was correct. But the E2E job's emulator was still
configured for arch: x86_64 on ubuntu-latest (amd64), so once the earlier
androidApplicationEntry build fix let the pipeline reach the emulator step,
installing the ARM64-only APK failed with INSTALL_FAILED_NO_MATCHING_ABIS.

Can't just flip the emulator to arm64-v8a in place: the Build Android APK
step runs a custom GHCR image (ghcr.io/appsflyersdk/unity-android) that
push-unity-to-ghcr.yml produces via a plain `docker pull` on an amd64
runner with no --platform, so that mirrored image is effectively amd64-only
regardless of upstream unityci/editor's own arch support. Running the whole
job on an arm64 runner would break the build step's container itself.

Splits the job instead: build-android stays on ubuntu-latest/amd64
(unchanged build step) and uploads the APK as an artifact; the new
e2e-android job runs on ubuntu-24.04-arm with arch: arm64-v8a so the
emulator gets hardware-accelerated (KVM) ARM64 emulation matching the APK,
rather than falling back to slow arm64-under-QEMU-on-amd64 emulation or
being unable to install the APK at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…unner starts

The emulator script's default -e meant a failure in adb install (or any
other command before af-scenario-runner.sh started) aborted the whole step
immediately, before anything was ever written to .af-e2e/reports/ — so the
"Upload E2E report" artifact came back empty on exactly the runs that most
needed diagnosis, e.g. the recent INSTALL_FAILED_NO_MATCHING_ABIS failure.

Now captures a full unfiltered device logcat from before adb install through
the end of the run, and adb install's own output/exit code, regardless of
where a failure happens — with explicit exit-code handling so the step
still fails correctly instead of the -e disablement silently swallowing it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…unner

fc48905's arm64 runner + arm64-v8a emulator plan doesn't actually work:
ubuntu-24.04-arm failed enabling KVM ("Failed to open the device 'kvm':
Invalid argument"), confirming GitHub-hosted arm64 Linux runners don't
expose nested virtualization to the guest. The same is true of Apple
Silicon macOS runners (Apple's Virtualization Framework doesn't support
nested virt either) — there's currently no GitHub-hosted runner with
hardware-accelerated ARM64 Android emulation.

Reverts the amd64/arm64 job split back to a single ubuntu-latest job, and
switches the emulator target from google_apis to google_apis_playstore.
Play Store x86_64 system images bundle ARM64-to-x86_64 native-library
translation, so the ARM64-only APK (Unity 6 dropped x86_64 Android build
support, see 7f288a4 and 8fc9105) can install and run on the existing
KVM-accelerated x86_64 emulator without needing ARM64 hardware at all.

Play Store images can never be adb-rooted (regular google_apis images just
don't have it by default), but af-scenario-runner.sh already has a working
non-root fallback for reading QA logs via logcat alone, exercised
successfully in every local verification run this session.

The 65e10ce log-capture fix (full device logcat + adb-install.log written
before any command that could fail) is unaffected and kept as-is.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…r script

reactivecircus/android-emulator-runner executes each line of the `script:`
input as its own separate `sh -c` call rather than one continuous script.
The brace-grouped install block and the cross-line adb-logcat PID handoff
both relied on shared shell state that doesn't exist across lines, so the
bare `{` on its own line errored out immediately (Syntax error: end of file
unexpected) before adb install, log capture, or the scenario runner ever
ran — leaving the uploaded report artifact with nothing but an empty
device-logcat-full.txt. Collapse the install/branch logic into single
self-contained lines and replace PID tracking with pkill for cleanup.
api-level 33's google_apis_playstore x86_64 image still hit
INSTALL_FAILED_NO_MATCHING_ABIS for our ARM64-only test APK. API 35 system
images ship Google's newer ABI-translation support that actually installs
and runs ARM64-only APKs on an x86_64 image; verified locally by installing
and launching the real CI-built APK on a local API 35 google_apis x86_64
emulator.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
QATestScript never logged anything or wrote af_qa_logs.txt in the first
CI run that got past the emulator install stage — the process was alive
and RESUMED at the Android OS level, but Unity's own player loop
(Start/Update/coroutines) never ran a single frame. Reproduced locally:
a headless (-no-window) emulator briefly grants window focus then
permanently loses it, and with Player Settings' Run In Background
disabled, Unity pauses its managed script loop whenever the Activity
lacks window focus - freezing the app before any script code executes,
with no crash or log to show for it.

Enabling Run In Background is the standard fix for exactly this class of
headless-CI-emulator problem.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
QueryAsync/generateInviteLink/QueryValidateAndLogAsync all hopped to a
background thread before calling into AppsFlyerRPCClient.Execute(), a
pattern introduced to work around iOS's _afExecuteJson semaphore
deadlock. Android's Execute() is a plain synchronous JNI call with no
such deadlock risk, and dispatching it from a background thread pool
worker instead risks an unattached/unreliable JNI environment -
matching the "Empty response from native" RPC failures and the
missing start() log seen in CI E2E runs under headless Run In
Background. Scope the background/main-thread hop to iOS only.
The plain google_apis image has no Play Store app, so there's no Play
Install Referrer for native's GCD/onInstallConversionData flow to query
- it silently never fires, failing is_first_launch_true with no error
in the logs (confirmed reproducible across two CI runs, unrelated to
the QueryAsync threading fix). Local ARM64 hardware/emulators never
hit this because they run the APK natively and never needed API 35's
ABI-translation fix that motivated the earlier switch off
google_apis_playstore in the first place (that switch was verified
only for api-level 33's variant, which don't apply here - Google's
system-image repo confirms
system-images;android-35;google_apis_playstore;x86_64 exists).
libswappywrapper.so's SwappyDisplayManager JNI refresh-rate query
segfaults inside the Berberis ARM64-on-x86_64 translator on the
google_apis_playstore API 35 x86_64 CI image, aborting the process
~3s after launch before any AF_QA logs are emitted. Unrelated to the
AppsFlyer plugin; test-app doesn't need frame pacing for a headless
functional E2E run.
…tart flow

Correlates Activity pause/resume (e.g. triggerLifecycleNudge), coroutine
scheduling, and Time.realtimeSinceStartup/frameCount across
HandleSessionReady -> RequestATTThenStart -> RunPostStartApis, to
determine whether CI's post-nudge stall (no logs after "[AF_QA][start]
result: SUCCESS", GCDSDK tasks never queued) is a coroutine that never
gets scheduled, or one that's scheduled but never resumes.
vSyncCount=1 (Android's active quality level) makes Choreographer the
engine's only frame-pacing clock. On CI's headless emulator
(-gpu swiftshader_indirect, -no-window), Choreographer has been observed
disabling itself after an Activity pause/resume (e.g. triggerLifecycleNudge)
and never re-enabling, permanently stalling the player loop - and with it
every coroutine scheduled after that point (RunPostStartApis, and by
extension the native SDK activity that queues GCD conversion-data checks).

Set vSyncCount=0 and Application.targetFrameRate=60 so the engine paces
itself off its own timer instead of depending solely on Choreographer.
…ndroid

google_apis_playstore AVDs keep self-updating Play Store/GMS after boot;
installing and launching the app before that settles races AppsFlyer's
Install-Referrer-based GCD lookup, so onInstallConversionData never fires
and is_first_launch_true fails despite start()/onSessionReady/onDeepLinking
all succeeding.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…firing and forgetting

Narrows the auto-run driver's init sequence (registerDeepLinkListener,
registerConversionListener, init, enableDebug, start) to async Awaitable
methods so each RPC's native round trip completes, in order, before the
next one dispatches. RunPreStartApis/RunPostStartApis/RunRPCCoverageApis
stay coroutine-based and fire-and-forget.
af-obodovskyi and others added 6 commits September 9, 2026 11:27
…f-hosted arm64 Mac)

Build stays on ubuntu-latest via the existing GHCR Docker image; only the
emulator/test job moves to the self-hosted Apple Silicon runner, now
matching local dev conditions (arm64-v8a, google_apis_playstore, API 36,
pixel_9_pro, native HVF acceleration) instead of GH-hosted x86_64 +
ABI translation, which was implicated in the intermittent start()/
conversion-callback flakiness. APK hands off between jobs via artifact
upload/download since jobs don't share a filesystem.
…d job split

- rc-e2e-android.yml: copy the downloaded APK to
  test-app/Build/Android/com.appsflyer.engagement.apk before running the
  scenario runner. af-scenario-runner.sh reads apk_path from the plan JSON
  (shared with local runs and .af-smoke/rc-test-plan.json) rather than
  $APK_PATH, so requires_fresh_install's uninstall+reinstall inside
  run_phase() was failing with "APK not found" on the new self-hosted job,
  blocking phase_1/3/5 and leaving later phases running with no app
  installed at all.
- af-scenario-runner.sh: add -u to the BSD `date -j -f` branch used to
  parse RUN_START. Without it, macOS date silently parses the UTC
  Z-suffixed timestamp as local time, inflating duration_sec by the
  runner's UTC offset (observed as +10800s on a UTC+3 machine).
triggerLifecycleNudge()'s synthetic Activity pause/resume (used to force
AppsFlyerLib's ActivityLifecycleCallbacks to re-evaluate session readiness
on cold launch) recreates the rendering Surface. In headless (-no-window)
mode there's no real compositor backing that Surface: Android's own
APP_CMD_RESUME fired at the native layer, but Unity's managed frame loop
never resumed, so OnApplicationPause(false)/start() never ran, and no
[AF_QA] logs appeared past the nudge.

Confirmed locally: booting the same AVD (Pixel_9_Pro, arm64-v8a,
google_apis_playstore, API 36) without -no-window and re-running phase_1
against the exact APK that froze in CI now passes 11/12 checks, with the
lifecycle-nudge marker observed after 10s instead of never appearing.
Safe to drop here since this job now runs on an interactive self-hosted
Mac session rather than a headless GH-hosted runner.
…ependency

ac993d9 bumped unity-wrapper to 7.0.14 in AppsFlyerDependencies.xml (the
Android Resolver's source of truth) but never touched this generated
file, since it's only regenerated when the resolver actually runs inside
the Editor UI. No one reopened the Editor and committed the regenerated
result afterward, so every CI build since (checkout + batch-mode build,
no Editor UI) has shipped an APK missing the unity-wrapper AAR -
com.appsflyer.unity.AppsFlyerRPCBridge was absent from classes.dex,
throwing ClassNotFoundException and silently dropping every RPC call
(init, registerConversionListener, start, etc.) with no visible error
except a single Debug.LogError on first bridge access.
…r to 7.0.15

af-android-plugin-bridge 7.0.13 fixes registerConversionListener() being
silently dropped when called before init() on Android (handleInit was
passing a hardcoded null conversion listener to AppsFlyerLib.init()
instead of the handler's own registered listener).

unity-wrapper 7.0.14 -> 7.0.15 + ANDROID_PLUGIN_BRIDGE_VERSION 7.0.13 keep
the wrapper's declared dependency in sync; the Maven coordinate is left
commented out in AppsFlyerDependencies.xml until 7.0.15 is actually
published.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reverts the self-hosted Apple Silicon runner in favor of the
x86_64/ABI-translation config (api-level 35, google_apis_playstore,
pixel_5) that was in place before the self-hosted split, restoring
-no-window and KVM setup for the headless Linux runner. Note: this
reintroduces the risk of the intermittent start()/conversion-callback
lifecycle flakiness the self-hosted move had fixed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
unity-wrapper was temporarily pinned to a locally-built .aar to test the
registerConversionListener-before-init fix ahead of the real release.
7.0.15 is now published to Maven/Sonatype, so switch back to resolving
it remotely instead of a local artifact.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
af-obodovskyi and others added 2 commits September 13, 2026 15:42
…ure drift

mainTemplate.gradle still pinned unity-wrapper:7.0.14 and
af-android-plugin-bridge:7.0.12 even though AppsFlyerDependencies.xml (the
resolver's source of truth) had moved on to 7.0.15/7.0.13 across two later
bump commits. This file is only regenerated by the Android Resolver's
Editor UI (per 45df292), never by CI's batch-mode build, so the drift
shipped silently - af-android-plugin-bridge 7.0.13 fixes
registerConversionListener() being dropped when called before init(), and
CI was building against the AAR from before that fix.

Root cause: scripts/bump-version.sh patched af-android-plugin-bridge in
this file but never patched unity-wrapper, so the wrapper coordinate never
moved even as the script kept "succeeding". Fixed the script to patch both,
and added a check to rc-release.yml's version-bump verification step that
fails the pipeline if this file's coordinates ever diverge from
AppsFlyerDependencies.xml again.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…tu-latest"

This reverts commit e252c62.

That revert's own message noted it "reintroduces the risk of the
intermittent start()/conversion-callback lifecycle flakiness the
self-hosted move had fixed" - GH-hosted's x86_64 + ABI-translation emulator
run with -no-window left Unity's frame loop stalled post-resume
(OnApplicationPause(false) never reaching script land after a Surface
recreation), which is indistinguishable from a real dependency-resolution
failure in the E2E report. Restoring the self-hosted Apple Silicon runner
(arm64-v8a, HVF-accelerated, windowed) removes that source of flakiness.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant