Release 7.0.2-rc9 - #432
Merged
Merged
Conversation
- docs/RPC-Implementation-Plan.md: full spec covering iOS and Android RPC bridge architecture, protocol definition, and phased rollout - plans/01-rpc-phase1-csharp-layer.md: detailed execution plan for the C# layer (AppsFlyerRPCClient, onRPCEvent handler, method routing, unit tests) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces per-platform native bindings with a unified JSON-RPC bridge (AppsFlyerRPC.xcframework on iOS, af-android-plugin-bridge on Android). Core changes: - AppsFlyer.cs: all SDK calls routed through AppsFlyerRPCClient; platform-split #if blocks reordered so UNITY_ANDROID is checked first (safe — mutually exclusive on real devices); setCurrentDeviceLanguage guarded iOS-only; setPhoneNumber Android no-op (bridge requires countryCode, public API does not expose it) - AppsFlyerRPCClient.cs: new IAppsFlyerRPCClient interface + DefaultInstance - AppsFlyerRPCBridge.java: Android RPC bridge implementation - AppsFlyerRPCWrapper.mm + AppsFlyerRPC.xcframework: iOS RPC bridge Tests: - Tests_Suite.cs: Android contract tests (6 new), iOS routing guards updated, platform exclusions validated; 67 tests total (61 iOS+shared, 6 Android) Docs: - Android-RPC-Mapping.md: plugin bridge → SDK API reference for Android - iOS-RPC-Mapping.md: AppsFlyerRPC → AppsFlyerLib method mapping for iOS - docs/RPC-Coverage.md: cross-platform RPC coverage matrix E2E validated locally on emulator/simulator — zero RPC parse errors on both platforms after fixing subscribeForDeepLink method name split. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the static xcframework from Assets/Plugins/iOS and repo root; add pod 'AppsFlyerRPC' 7.0.11 to AppsFlyerDependencies.xml so EDM4U resolves it from CocoaPods alongside AppsFlyerFramework. AppsFlyerRPCWrapper.mm is unchanged — the ObjC API surface is identical. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove af-android-plugin-bridge, af-android-sdk-base, and af-android-sdk-dev local AARs from unitywrapper/libs and test-app/Assets/Plugins/Android. unitywrapper/build.gradle: - implementation 'com.appsflyer:af-android-plugin-bridge:7.0.1' - compileOnly "com.appsflyer:af-android-sdk:$ANDROID_SDK_VERSION" (replaces sdk-base/dev local files) - removed flatDir repository AppsFlyerDependencies.xml: - added com.appsflyer:af-android-plugin-bridge:7.0.1 so EDM4U declares it for Unity consumers alongside af-android-sdk Also includes unit testing examples appended to iOS-RPC-Mapping.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove EmailCryptType and setPhoneNumber: P/Invoke bridge stubs — both APIs were dropped in AppsFlyerFramework 7.0.1; the RPC layer handles these calls. Simplify mainTemplate.gradle to only declare af-android-plugin-bridge:7.0.1 since it provides af-android-sdk transitively (no direct SDK dep needed). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace android_sdk_version/ios_sdk_version inputs with android_plugin_bridge_version and ios_rpc_version throughout the rc-release workflow, bump-version.sh, and ios-pod-install.sh. - rc-release.yml: new inputs for af-android-plugin-bridge and AppsFlyerRPC; verify step checks RPC coords in AppsFlyerDependencies.xml; Slack message shows RPC bridge versions - bump-version.sh: bumps af-android-plugin-bridge in deps XML, build.gradle, and mainTemplate.gradle; bumps AppsFlyerRPC in deps XML and ios-pod-install.sh; retains android_sdk_version for wrapper compileOnly dep - ios-pod-install.sh: reads AppsFlyerRPC version from AppsFlyerDependencies.xml and writes it into the Podfile instead of AppsFlyerFramework Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…wrapper.yml workflow_dispatch does not support a secrets: block; it inherits secrets from the repository/environment directly. Secrets were incorrectly duplicated under workflow_dispatch, causing an IDE validation error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
af-android-plugin-bridge:7.0.1 transitively brings af-android-sdk:7.0.1. The compileOnly dep in gradle.properties must match; 6.17.6 was the old direct-SDK version and is no longer correct. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
af-android-plugin-bridge declares af-android-sdk as api, so sdk classes are available to the wrapper via the bridge alone. Verified by successful assembleRelease without the compileOnly dep. Removes ANDROID_SDK_VERSION from: gradle.properties, unitywrapper/build.gradle, bump-version.sh, publish-android-wrapper.sh, publish-android-wrapper.yml, and rc-release.yml. android_sdk_version is no longer an input anywhere. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update PLUGIN_VERSION in AppsFlyerAndroidWrapper.java and VERSION_NAME in gradle.properties to 7.0.1 ahead of unity-wrapper Sonatype publish. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Method was missing from the wrapper causing NoSuchMethodError at runtime. af-android-plugin-bridge routes it through the RPC bridge to AppsFlyerLib. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Re-version to 7.0.11 to include the setPartnerData fix missing from 7.0.1. Also updates AppsFlyerDependencies.xml to reference unity-wrapper:7.0.11. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PurchaseConnector 7.0.0 pinned AppsFlyerFramework = 7.0.0, conflicting with AppsFlyerRPC 7.0.11 which requires AppsFlyerFramework = 7.0.1. Bumped PurchaseConnector to 7.0.1 (compatible with AppsFlyerFramework 7.0.1) and AppsFlyerFramework to 7.0.1. Also removed af-android-sdk:6.17.6 explicit declaration — it is a transitive dep via af-android-plugin-bridge:7.0.1 (api). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… billing v8 - purchase-connector 2.1.2 → 2.2.0 (billing library v8 support) - billingclient:billing 5.2.0 → 8.0.0 - unity-wrapper artifact version 7.0.11 → 7.0.12 - Remove af-android-sdk:6.17.6 explicit declaration (transitive via bridge) - AppsFlyerFramework 7.0.0 → 7.0.1, PurchaseConnector 7.0.0 → 7.0.1 in iOS pods Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nvoke AppsFlyerRPC 7.0.11 does not handle registerDeeplinkListener, so the deep link delegate was never set and onDeepLinking callbacks never fired. Fall back to instance.subscribeForDeepLink (P/Invoke _subscribeForDeepLink) on iOS which correctly sets AppsFlyerLib.deepLinkDelegate. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…own SDK lifecycle
AppsFlyerAndroid.initSDK called AppsFlyerAndroidWrapper.initSDK (which called
AppsFlyerLib.init with a conversion listener) AND then AppsFlyer.cs fired
ExecuteFire("init") through the RPC bridge, which called AppsFlyerLib.init again
overwriting the conversion listener. Result: onConversionDataFail("Launch exception: null").
Fix: AppsFlyerAndroid.initSDK now only wires the RPC bridge callback routing
(InitAndroidBridge). AppsFlyerLib.init is called exclusively by the RPC bridge.
Similarly, startSDK no longer calls instance.startSDK on Android — the RPC
bridge owns AppsFlyerLib.start. iOS keeps both paths (deprecated _startSDK
is a no-op on the native side).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
startSDK no longer calls instance.startSDK() on Android (removed to fix
double AppsFlyerLib.init). The shared test must verify the RPC path
(ExecuteFire("start")) which fires on all platforms, not the iOS-only
native bridge call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nSessionReady via RPC Both iOS and Android were firing onSessionReady synthetically instead of waiting for the native SDK callback. Collapsed to a single ExecuteFire call on both platforms; removed dead _nativeRegisterSessionReadyListener P/Invoke on iOS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Required by rc-release.yml validation: grep -q "kAppsFlyerPluginVersion = \"$PLUGIN_VERSION\"". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
getConversionData() fires ExecuteFire("registerConversionListener") which is
required for onInstallConversionData to reach Unity. E2E phase_1 was failing
because the listener was never registered.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…revent cache eviction Route onConversionDataSuccess and onConversionDataFail events in onRPCEvent switch so the callback reaches the Unity GameObject. Also increase the pre-stopSDK wait from 1s to 6s: the SDK queues the conversion request immediately after startSDK but ClearCache (triggered by stopSDK(true)) was firing ~300ms before the task could execute, deleting its cached payload and producing "Launch exception: null" → onConversionDataFail on every fresh install. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…conversion data
stopSDK was sending {"stopped": bool} but both Android (JsonRpcRequestParser)
and iOS (AppsFlyerRPC) expect {"shouldStop": bool}. Because optBoolean defaults
to true, stopSDK(false) was a no-op — the SDK stayed stopped permanently,
causing every subsequent conversion-data request to fail with 'isStopTracking'
enabled.
Also wait for onConversionDataSuccess/Fail before calling stopSDK(true) so the
in-flight GCD request is never cancelled by ClearCache on slow CI networks.
Verified: Android 38/38, iOS 38/38 locally.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…3 foreground deep link The RPC bridge's sCallbackObjectName becomes null after RunRPCCoverageApis() runs and the app background/foregrounds, causing all subsequent RPC callbacks (including onDeepLinking) to be silently dropped on Phase 3 re-launch. Android subscribeForDeepLink now calls AppsFlyerAndroidWrapper.subscribeForDeepLink directly (matching the React Native plugin pattern), bypassing the RPC bridge state entirely. iOS keeps the RPC path unchanged. Also include: - adb root call in CI workflow and runner launch to elevate logcat permissions - checks_json recorded before fail_action=abort to prevent missing entries in report Verified 38/38 locally on API 36 emulator. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previous commit accidentally switched iOS to an RPC call without callbackObjectName, breaking Phase 2 and Phase 3 deep link callbacks. iOS was already using instance.subscribeForDeepLink(CallBackObjectName) (direct P/Invoke) which was correct — restore that path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…onNewIntent AppsFlyerUnityActivity.onNewIntent() manually called performDeepLinking() on every foreground deep link, in addition to the SDK's own automatic Unified Deep Linking resolution that runs on the following onResume(). The two concurrent resolution attempts for the same URL raced, and the onDeepLinking(FOUND) callback was intermittently lost (RC E2E phase_3: deeplink_found_fg / deeplink_value_fg). setIntent(intent) alone is enough so the SDK's automatic path sees the new intent. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The native SDK's own Activity-lifecycle foreground/background detection (a 1s-delayed isInForeground flag flip in AndroidLifecycleManagerImpl) gates when unifiedDeepLinking() re-fires after the app returns to the foreground. The SDK's own docs (F-077-session-management.md) state this Activity-lifecycle path is not reliably delivered through Unity's engine, and that onPause() exists specifically as the plugin-bridge workaround for Cocos2dx/Unity — but the Unity plugin never called it. Wire up Unity's own OnApplicationPause(bool) engine callback (which Unity does deliver reliably) to fire the existing RPC "onPause" method, so the SDK's foreground/ background state machine — and therefore deep-link re-resolution on foreground — stays in sync regardless of whether Android's raw Activity callbacks come through. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…inking fires
The native SDK only enqueues the clean-launch deferred deep-link check
(ResolveDdlTask, which delivers onDeepLinking NOT_FOUND) if a DeepLinkListener
is already registered at the exact moment unifiedDeepLinking() runs --
confirmed via the native SDK's F-094-deferred-deep-linking.md ("Activates ...
when unifiedDeepLinking() finds no direct deep link ... and a DeepLinkListener
is registered"). It's a one-shot gate, not a retry.
unifiedDeepLinking() fires synchronously as part of native init() (confirmed
in CI logs: "[DDL] No deep link detected" logs ~200ms after the init RPC
call, with no registerDeepLink-equivalent call having happened yet). The test
app only subscribed via OnDeepLinkReceived += a couple of RPC round-trips
later, in QATestScript's InitAsync, missing the window and permanently
losing the first-launch NOT_FOUND callback (RC E2E phase_1:
on_deep_linking_callback).
Move the native subscribeForDeepLink() call into initSDK() itself, right
after `instance` is assigned and before the "init" RPC call fires, so the
listener is always registered before the native SDK's first
unifiedDeepLinking() pass -- regardless of when/whether the integrating app
wires up OnDeepLinkReceived.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… before The previous commit (0efab22) placed subscribeForDeepLink() before the native "init" RPC call, on the assumption that the native SDK's internal state was independent of init() timing. It wasn't: calling AppsFlyerLib.getInstance().subscribeForDeepLink() before init() has ever run broke SDK startup entirely (RC E2E: sdk_started never logged, app produced only 11 log lines before going silent, phase_1 aborted). The native reference sample (mobile/appsflyer-android-sdk testapp, TestApplication.kt) confirms subscribeForDeepLink() must be called AFTER init(), immediately following it. Keep it there, but move it from QATestScript's later, multi-RPC-hop-removed call site into initSDK() itself, directly after the "init" RPC fires and before any other RPC call -- still ahead of unifiedDeepLinking()'s async dispatch in the vast majority of cases, without the ordering hazard of the previous attempt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… test app instead Both attempts to move subscribeForDeepLink() into AppsFlyer.cs's initSDK() (0efab22, eb4cb6f) caused the Android E2E job to abort entirely -- SDK never finished starting (sdk_started never logged, near-zero app log output) on two independent CI attempts. Reverting AppsFlyer.cs to the last proven-stable state (a8c4d1c, 37/38 passing) rather than keep guessing at native SDK init-timing internals we can't reproduce/debug locally. Fix the original issue (Phase 1 cold-launch onDeepLinking NOT_FOUND lost) in the test app instead, where the blast radius is contained: move `AppsFlyer.OnDeepLinkReceived += OnDeepLinkReceived` (which triggers subscribeForDeepLink()) to run immediately after initSDK() returns, before getConversionData(), shrinking the race window against the native SDK's automatic unifiedDeepLinking() check without touching the shared plugin's init sequencing at all. 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>
…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>
Skip restoring the cached Unity Library when clean_build is true (default) so the Android E2E build always re-imports from scratch, avoiding stale-artifact classes of bugs. Add a post-build step that unzips the APK and greps the dex for AppsFlyerLib and AppsFlyerRpcHandler to catch dropped/misconfigured dependencies before the E2E run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
logCrossPromoteImpression and logAndOpenStore were sending the literal placeholder string "rpc_app_id"/"rpc_store_app" as the promoted app id, which the backend can't resolve, causing real 404s during QA runs. Use the already-loaded _androidAppId/_iosAppId instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…oid ANRs QueryAsync's Execute() call is a synchronous, blocking JNI round trip (isSessionReady, getSdkVersion, getAppsFlyerUID, getAttributionId, and others). Running it on whatever thread called QueryAsync - normally Unity's main game-loop thread - risks an ANR if the native SDK stalls on a slow/hung server round trip. Add AppsFlyerJniWorker: a single, long-lived background thread that attaches to JNI once and stays attached, and route the Android QueryAsync path through it instead. Awaitable.BackgroundThreadAsync() was tried previously and reverted - its transient thread-pool workers aren't guaranteed an attached JNI environment, which caused "Empty response from native" failures under headless Run In Background CI playmode tests. A dedicated permanently-attached thread avoids that failure mode while still moving the blocking call off the main thread. iOS is untouched (already hops via BackgroundThreadAsync/MainThreadAsync for its own, unrelated reason). FireAsync (awaitResponse: false) is untouched. No native bridge/protocol change. Known open risk, not addressed here: AppsFlyerRPCClient has no locking beyond an Interlocked request-id counter, so FireAsync (main thread) and QueryAsync (now this worker thread) can now hit the native bridge concurrently for the first time. Needs an explicit concurrent-call test/ review before this is considered fully done. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Codifies the full clean-rebuild-and-test runbook (uninstall, wipe Unity Library/Temp/Build/Logs and the global Gradle cache, batchmode rebuild, APK/dex/dependency verification, fresh install, logcat request/status map) as a reusable subagent, including the multi-device adb ambiguity and Unity project-lock gotchas hit while running this manually. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reapplies e252c62 (previously reverted in d3a3e3b) on top of the clean_build/APK-verification changes added since: runs-on ubuntu-latest, apt-based jq install, KVM enablement, and the x86_64/api-35/pixel_5 ABI-translation emulator config needed to install the ARM64-only BuildScript.BuildAndroid APK on a GH-hosted image. Known risk, documented inline: this config was reverted once already for intermittent start()/conversion-callback lifecycle flakiness on GH-hosted's x86_64 + ABI-translation emulator. Moving back is a deliberate choice made with that history in view, not an oversight. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…tu-latest" This reverts commit 7e6e3fa.
…nerated .meta cruft EDM4U 1.2.187 is already committed as source under Assets/ExternalDependencyManager; build_unity_package.sh and strict_mode_build_package.sh still imported the obsolete 1.2.183 .unitypackage and unconditionally deleted the (now tracked) ExternalDependency- Manager/PlayServicesResolver folders in their cleanup traps. Drop the import and the matching cleanup lines, and remove the unused vendored 1.2.183 package. Also ignore Android.iml.meta and Plugins/Android/libs(.meta) — Android Studio/Resolver regenerate these on every open/build, and their .meta sidecars weren't covered by the existing *.iml gitignore entry. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…to import it Adds the official external-dependency-manager-1.2.187.unitypackage (verified byte-identical to the committed Assets/ExternalDependencyManager source) to both repo-root and test-app's Editor folders, so the raw distributable artifact is available again for reimport into other projects. Points build_unity_package.sh and strict_mode_build_package.sh's -importPackage back at this file (correct 1.2.187 version, replacing the stale removed 1.2.183 reference), while keeping the earlier fix intact: their cleanup() traps still do not delete Assets/ExternalDependencyManager/PlayServicesResolver, since those are tracked source now, not transient import output. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Strip all remoteSwiftPackage (SPM) blocks from AppsFlyerDependencies.xml when building the strict-mode package and pin AppsFlyerFramework, AppsFlyerRPC, and PurchaseConnector to their CocoaPods /Strict subspecs. Leaving any remoteSwiftPackage declared caused EDM4U to add the regular SPM package alongside the strict CocoaPod, and AppsFlyerRPC's default subspec depends on the non-strict AppsFlyerFramework, which produced a "conflicting names: appsflyerlib.xcframework" pod install failure. Document that strict mode is CocoaPods-only in strictMode.md and Installation.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Dev/android api alignment
Kobikg78
previously approved these changes
Sep 17, 2026
…heck
AppsFlyerDependencies.xml no longer declares af-android-sdk directly
(only af-android-plugin-bridge, which pulls it in transitively), so
read_android_package_version("af-android-sdk") returned empty and
require_version exited 1 in promote-release.yml's "Update installation
links" step.
The docs/Installation.md manual "AppsFlyer Android SDK" download link
is left untouched rather than rewritten to af-android-plugin-bridge,
since that artifact is a thin wrapper that doesn't work standalone for
drag-and-drop installs without its own transitive deps.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Author
|
RC-PROMOTE blocked: expected rc-smoke/github-release to be success on 1484ecf, found missing. |
Author
|
RC-PROMOTE complete. Version surfaces and installation links now point at 7.0.2, and the branch is ready to merge. |
Kobikg78
approved these changes
Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RC release branch for 7.0.2-rc9. Promotion is gated by rc-smoke/github-release.