fix: merge main into workstation/swift-migration and apply pending test fixes - #915
Conversation
feat(network): accept native GoDaddy R1 certificate chains Add GoDaddy TLS Root CA - R1 to the default certificate set while retaining all existing trust anchors. Verify the embedded certificate against GoDaddy's published SHA-256 fingerprint to prevent accidental pin changes. #agentic
chore: (release) 9.4.1 Updates version to 9.4.1 across the mParticle ecosystem.
release-ecosystem-from-main.yml is registered in Actions as disabled_manually but its file is not on main at all - only on unmerged branches - so describing it as a workflow file in the tree that never runs was wrong. The real trap is that the workflow list and the tree disagree in both directions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Observed on this branch: the build-kits Pod Lint jobs fail as a batch on a CocoaPods CDN error, and a cancelled job is a timeout-minutes expiry or a superseded push under pull-request.yml's cancel-in-progress concurrency group - not a test result. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5 to 6. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](actions/setup-java@v5...v6) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* ci: stop simulator cloning and bound network/test hangs Two unrelated hangs were holding up CI. Both were unbounded, so they consumed a job's full budget instead of failing. native-tests: the iOS x mParticle-Apple-SDK-Swift cell repeatedly hit its 15-minute timeout. A single test, MPDeviceTests.testDictionaryDescription, took 156-459s across recent runs while every other test finished in under 1.6s; job duration tracked that test exactly. The same test takes 0.069s on tvOS in the same run, so the cause is simulator state, not the assertions. MPDevice reads UIDevice.current for name and identifierForVendor, which are XPC calls into simulator daemons, and mParticle-Apple-SDK-Swift.xcscheme is the only scheme in the repo with parallelizable="YES" - so xcodebuild clones and boots extra iOS simulators on a runner that just erased one, starving the daemons that test then blocks on. Disable parallel testing for the run. The suite is ~2s of tests; locally this is 2x faster end to end (33s vs 74s) because it no longer boots 8 simulator clones. Also wait for a real boot via simctl bootstatus - the action's wait_for_boot only waits for state=Booted, not for first-boot work to finish - and add a per-test timeout so a hung test fails in 2 minutes with an explicit diagnostic instead of silently eating the job timeout. The slowest genuine test on CI is ~30s, leaving 4x headroom. build-kits: Build rokt-sdk-plus-ios stalled 30 minutes inside a git fetch of stripe-ios (2.7 GB, reached transitively via rokt-payment-extension-ios), leaving orphaned git and git-remote-http processes. The job has no timeout-minutes, so only an unrelated concurrency cancel stopped it; otherwise it would have held a macOS runner for the 6-hour default. Make git abort a transfer stalled below 1 KB/s for 3 minutes, retry the resolve three times (matching the existing pod-lint-kits pattern), and add job timeouts so no hang here can run unbounded again. Healthy resolves take 2-5 minutes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ci: bound each SPM resolve attempt with a kill-and-retry watchdog The first version of this fix relied on git's own low-speed abort to break a stalled fetch. It does not fire: on run 33010942238 the stripe-ios fetch sat for 24.5 minutes with http.lowSpeedLimit/lowSpeedTime set, produced no error, and never returned - so the retry loop never got a turn and the step burned its whole 25-minute budget before failing. Bound each attempt explicitly instead. A watchdog kills the resolve and its surviving git children once an attempt passes ATTEMPT_TIMEOUT_SECONDS (480s, against a healthy 2-5 minute resolve), so a stalled attempt is retried rather than consuming the step. Drop to 2 attempts and a 20-minute step timeout, since an attempt can no longer run unbounded. Keep the git low-speed config: it is not sufficient on its own but still aborts genuinely slow transfers where it does apply. Verified against the extracted step body with a stubbed resolver: a healthy resolve exits 0 in 1s with no kills; a permanent hang is killed twice and fails bounded; a hang followed by a healthy retry is killed once and exits 0. Defaulted the timeout in-place so an unset variable cannot make the watchdog fire immediately. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ci: run the resolve watchdog cleanup in the parent so it actually executes Bugbot caught that the watchdog's cleanup was dead code. The watchdog TERMed the resolve subshell and then slept 5s before escalating, but TERMing the resolve unblocks the parent's wait immediately, and the parent then kills the watchdog mid-sleep - so the kill -KILL and the pkill of leftover xcodebuild and git-remote-http children never ran. The retry could therefore start while the previous stalled fetch was still alive and race it over SwiftPM's cache locks, which is the exact failure the watchdog was added to prevent. The watchdog now only records that it fired (via a marker file) and sends TERM. Escalation and child cleanup run in the parent after wait returns, where they cannot be pre-empted, followed by a short grace period before the retry. Verified by extracting the step body, stubbing the resolver and replacing the pkill calls with probes: on the old code the cleanup probes fired 0 times out of 4 expected; they now fire 4/4 on a permanent hang and 2/2 when one attempt hangs and the retry succeeds. Cleanup still does not run on a non-timeout failure (0 probes), so a fast failure does not trigger a spurious pkill, and the healthy path is unchanged at exit 0 with no kills. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…inistic (#870) testSwitchWorkspaceKitsWithStop waited on two nested 10-second dispatch_after blocks, so it always burned at least 20 seconds of wall clock and depended on fixed timing rather than on the SDK actually being ready. Wait on the SDK's own readiness signals instead - MParticle.initialized after startWithOptions:, and the replacement shared instance after switchWorkspaceWithOptions: - by spinning the main run loop until the condition holds. The assertions are unchanged, so the test still checks the same behaviour; it now takes 0.11s instead of 20.2s. testActiveKitsRegistryThreadSafety tracked failure in a plain __block BOOL written from four concurrent blocks, which is itself an unsynchronized data race, and called XCTFail from those background queues. Guard the shared state with an NSLock, record only the first exception, and report it from the dispatch_group_notify block on the main queue. This commit does not change the flakiness of testActiveKitsRegistryThreadSafety itself: that crash is a real race in MPKitContainer (flushSerializedKits enumerates and mutates kitsRegistry without kitsSemaphore, reached via the early return in configureKits: before the lock is taken). Reproduced at 2 crashes in 10 runs of that test alone. Fixing it changes core SDK locking, so it is deliberately left for a separate, explicitly-reviewed change. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
docs: trim AGENTS.md to the non-derivable core
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.1.2 to 3.1.5. - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](isaacs/minimatch@v3.1.2...v3.1.5) --- updated-dependencies: - dependency-name: minimatch dependency-version: 3.1.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.18.1. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](lodash/lodash@4.17.21...4.18.1) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.18.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
….29.4 in /RNExample (#767) chore: bump @babel/plugin-transform-modules-systemjs in /RNExample Bumps [@babel/plugin-transform-modules-systemjs](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-modules-systemjs) from 7.25.9 to 7.29.4. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.4/packages/babel-plugin-transform-modules-systemjs) --- updated-dependencies: - dependency-name: "@babel/plugin-transform-modules-systemjs" dependency-version: 7.29.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [shell-quote](https://github.com/ljharb/shell-quote) from 1.8.1 to 1.10.0. - [Changelog](https://github.com/ljharb/shell-quote/blob/main/CHANGELOG.md) - [Commits](ljharb/shell-quote@v1.8.1...v1.10.0) --- updated-dependencies: - dependency-name: shell-quote dependency-version: 1.10.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
🐦 Swift Migration ProgressProduction implementation code at
Objective-C retained by design: Core SDK 5,801 · SDK kit infrastructure 2,063 · Standalone kits 0. This PR's code movement
How this is measured
Generated with |
PR SummaryLow Risk Overview CI: Tests: Workspace-switch cases in Repo hygiene: Reviewed by Cursor Bugbot for commit 6322ca6. Bugbot is set up for automated code reviews on this repo. Configure here. |
📦 SDK Size Impact ReportMeasures how much the SDK adds to an app's size (with-SDK minus without-SDK).
➡️ SDK size impact change is minimal. Raw measurementsTarget branch (workstation/swift-migration): {"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":2520,"with_sdk_executable_size_bytes":76312,"sdk_impact_kb":2436,"sdk_executable_impact_bytes":848,"xcframework_size_kb":7000}This PR: {"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":2520,"with_sdk_executable_size_bytes":76312,"sdk_impact_kb":2436,"sdk_executable_impact_bytes":848,"xcframework_size_kb":7000} |
Brings this branch's native-tests / build-kits CI up to date with main's #867 (stop simulator cloning that starved the daemons one Swift-scheme test blocks on; bound the SPM resolve with a per-attempt watchdog instead of trusting git's own low-speed abort, which does not reliably fire) and #870 (the workspace-switch tests moved off nested 10-second dispatch_after chains onto MPWaitForCondition, which polls the SDK's own readiness state instead of guessing at a fixed delay). Auto-merged cleanly everywhere except UnitTests/ObjCTests/MParticleTests.m, where both branches had independently rewritten the same five workspace-switch test bodies - main by removing dispatch_after for MPWaitForCondition, this branch by adding migration-specific assertions (resetRegistry, kitContainer_PRIVATE, registeredKits.anyObject) on top of the old dispatch_after version. Git's line-based merge "succeeded" there without a conflict marker, but silently interleaved hunks from both rewrites - 10 dispatch_after calls survived alongside 3 MPWaitForCondition calls, split unevenly across the five methods. Replaced that whole block with a hand-reconciled version carrying both: MPWaitForCondition throughout, this branch's own assertions preserved. The one real conflict marker, on the MParticle() class-extension additions, was two property declarations that both belonged. testActiveKitsRegistryThreadSafety merged without incident - this branch's independent registry work (MPKitContainer.swift's registryLock/registry are both static, unlike main's per-instance kitsSemaphore that #916 fixes) never touched the same lines as main's #870 change to that test, which only reworked how the test itself tracks failures across its four dispatch_group blocks. Verified: no duplicate method names introduced, build-for-testing succeeds, and MParticleTests + MPKitContainerTests run 147/147 clean, including all five workspace-switch tests (0.1-0.4s each, versus 20-30s before) and the thread-safety stress test.
MPRoktTests.m diverged too far from main's version for the preceding merge to carry this over as part of it - main's tearDown reorders the same two lines, but the files no longer share enough context for a line-based merge to find that hunk. Applying it directly here instead: releasing self.rokt while OCMPartialMock(self.rokt) is still installed is the wrong order regardless of which branch's file structure it's in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5b6c5ad to
6322ca6
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6322ca6. Configure here.
906036f
into
workstation/swift-migration

Draft. This is now a real
git merge mainintoworkstation/swift-migration, not a hand-authored commit reproducing main's changes. Previous revision of this PR did the latter; this replaces it.Why a merge instead of a port
workstation/swift-migrationdiverged frommainbefore #867 and #870 landed, so this branch never got the CI hang fixes or the workspace-switch test fixes. The first version of this PR re-implemented that content as a fresh commit. That works for a one-time sync, but it leaves no shared history — a future real merge ofmaininto this branch would see none of it as already-applied, and would either duplicate the work or conflict against it for no reason.This version merges
main's actual tip into this branch instead, so#867,#870, and everything elsemainhas picked up since (CODEOWNERS additions, anAGENTS.mdtrim, dependency bumps) land with their real commit history intact.What merged cleanly, and what didn't - and a correction on attribution
Everything auto-merged except
UnitTests/ObjCTests/MParticleTests.m, where both branches had independently rewritten the same five workspace-switch test bodies. Correction to an earlier version of this description: only one of those five,testSwitchWorkspaceKitsWithStop, was actually converted fromdispatch_aftertoMPWaitForConditionbymain's #870. The other four are converted in commit35fe1c82on the still-open #878/#916 stack, not onmain. I said "main removesdispatch_afterforMPWaitForCondition" for the whole block; that overstated it for four of the five methods, and I want the record accurate rather than let it stand.Git's line-based merge did not raise a conflict marker on this file, but it silently interleaved hunks from the different rewrites each side had made: 10
dispatch_aftercalls survived alongside 3MPWaitForConditioncalls, split unevenly across the five methods. A clean merge report is not proof the result is correct - I checked, and this one wasn't. Rather than reconcile only the one method main had actually converted and leave the other four on old-style fixed delays, I carried over the same conversion from #878/#916 for all five, since this branch needs the same fix and the merge conflict was the natural point to apply it. Assertions are this branch's own (resetRegistry,kitContainer_PRIVATE,registeredKits.anyObject) throughout - only the wait mechanism changed. The one actual conflict marker, in theMParticle ()class-extension additions, was just two property declarations that both belonged (kitContainer_PRIVATEfrom this branch,initializedfrom main).testActiveKitsRegistryThreadSafetyinMPKitContainerTests.mmerged without any of this trouble - main's #870 change there only reworked how the test tracks failures internally (anNSLock-guarded exception instead of an unsynchronized__block BOOL), in lines this branch hadn't independently touched.MPRoktTests.mdiverged too far structurally for the merge to locate matching context at all - main's changes there (async timeout raises, teardown drain, areject-site fix, the mock teardown ordering) simply didn't apply. The teardown-ordering piece is re-applied directly in the second commit here, since it's correct regardless of file structure; the rest doesn't apply to this branch's version of the file and isn't part of this PR.A known weak wait, tracked upstream rather than fixed here
Cursor flagged that
testSwitchWorkspaceOptionsandtestSwitchWorkspaceSideloadedKitswait on signals that fire before startup actually finishes (instance.options != nilis set synchronously near the top ofstartWithOptions:, well before the asyncidentifycall andconfigureWithOptions:thatinitializedwaits for). Confirmed by readingmParticle.mdirectly - it's a real gap, not a false positive.Both tests came from #878/#916 (see the correction above), which has the identical wait and the identical gap. Fixing it here would diverge from that PR rather than match it, and the next real merge would just reintroduce the weaker version. Left as a follow-up on #878 - once fixed there, it reaches this branch on the next sync.
Deliberately still not ported
The
kitsRegistrylock fix does not apply here. The migration moved the registry intoMPKitContainer.swift, whereregistryLockandregistryare bothstaticand every accessor takes the lock already - this branch's registry locking is sounder than main's pre-fix version. Main's separatewrapperInstancerace fix (#916) is the same story: it's fixing anonatomicproperty race inMPKitContainerExecutionAdapter.m's Objective-C teardown path, and this branch's Swift-side locking doesn't have the same shape of problem. Neither is in scope here.Validation
build-for-testingsucceeds.MParticleTests+MPKitContainerTests: 147/147 passing, including all five workspace-switch tests (0.1-0.4s each, versus 20-30s of fixed delay before) and the thread-safety stress test.trunk checkclean.🤖 Generated with Claude Code