Skip to content

fix: merge main into workstation/swift-migration and apply pending test fixes - #915

Merged
nickolas-dimitrakas merged 18 commits into
workstation/swift-migrationfrom
fix/port-ci-and-concurrency-fixes-to-swift-migration
Sep 2, 2026
Merged

nickolas-dimitrakas merged 18 commits into
workstation/swift-migrationfrom
fix/port-ci-and-concurrency-fixes-to-swift-migration

Conversation

@nickolas-dimitrakas

@nickolas-dimitrakas nickolas-dimitrakas commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Draft. This is now a real git merge main into workstation/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-migration diverged from main before #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 of main into 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 else main has picked up since (CODEOWNERS additions, an AGENTS.md trim, 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 from dispatch_after to MPWaitForCondition by main's #870. The other four are converted in commit 35fe1c82 on the still-open #878/#916 stack, not on main. I said "main removes dispatch_after for MPWaitForCondition" 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_after calls survived alongside 3 MPWaitForCondition calls, 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 the MParticle () class-extension additions, was just two property declarations that both belonged (kitContainer_PRIVATE from this branch, initialized from main).

testActiveKitsRegistryThreadSafety in MPKitContainerTests.m merged without any of this trouble - main's #870 change there only reworked how the test tracks failures internally (an NSLock-guarded exception instead of an unsynchronized __block BOOL), in lines this branch hadn't independently touched.

MPRoktTests.m diverged too far structurally for the merge to locate matching context at all - main's changes there (async timeout raises, teardown drain, a reject-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 testSwitchWorkspaceOptions and testSwitchWorkspaceSideloadedKits wait on signals that fire before startup actually finishes (instance.options != nil is set synchronously near the top of startWithOptions:, well before the async identify call and configureWithOptions: that initialized waits for). Confirmed by reading mParticle.m directly - 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 kitsRegistry lock fix does not apply here. The migration moved the registry into MPKitContainer.swift, where registryLock and registry are both static and every accessor takes the lock already - this branch's registry locking is sounder than main's pre-fix version. Main's separate wrapperInstance race fix (#916) is the same story: it's fixing a nonatomic property race in MPKitContainerExecutionAdapter.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

  • No duplicate method names introduced by the merge (checked directly, since that's the failure mode a bad Objective-C merge would produce).
  • build-for-testing succeeds.
  • 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 check clean.
  • Local runs, Xcode 26.3 / iOS 26 simulator. CI not yet re-run against this revision.

🤖 Generated with Claude Code

thomson-t and others added 16 commits August 28, 2026 16:44
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>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

🐦 Swift Migration Progress

Production implementation code at 6322ca6d47fa compared with edc6f6c82bcd.

Area Goal Progress Base This PR Swift SLOC Objective-C remaining Change
Core SDK Short term — in scope ████▌░░░░░ 44.61% 44.61% 6,630 8,232 ➖ 0.00 pp
Core SDK Long term — all Objective-C ███▎░░░░░░ 32.09% 32.09% 6,630 14,033 ➖ 0.00 pp
SDK kit infrastructure Short term — in scope ██████░░░░ 60.28% 60.28% 1,645 1,084 ➖ 0.00 pp
SDK kit infrastructure Long term — all Objective-C ███▍░░░░░░ 34.33% 34.33% 1,645 3,147 ➖ 0.00 pp
Standalone kits Short term — in scope ▏░░░░░░░░░ 1.06% 1.06% 152 14,218 ➖ 0.00 pp
Standalone kits Long term — all Objective-C ▏░░░░░░░░░ 1.06% 1.06% 152 14,218 ➖ 0.00 pp

Objective-C retained by design: Core SDK 5,801 · SDK kit infrastructure 2,063 · Standalone kits 0.

This PR's code movement

Area Swift lines added Objective-C lines removed
Core SDK 0 0
SDK kit infrastructure 0 0
Standalone kits 0 0
How this is measured
  • Current composition uses production source lines of code (SLOC) from cloc; comments and blank lines are excluded.
  • Short term — in scope excludes the Objective-C the migration will not delete, so 100% is the end of this project: every in-scope implementation gone.
  • Long term — all Objective-C keeps the full denominator. Reaching 100% there means the public API itself becomes Swift, which is a breaking change reserved for a future major release.
  • The gap between the two rows is the retained public/kit contract, runtime-identity, and boundary-glue surface listed in Tools/swift-migration-retained-objc.txt.
  • Retained wrappers keep their Objective-C interface but still shed logic to Swift. That thinning moves the long-term row and the retained figure, not the short-term row.
  • Both revisions are measured with the manifest from the head revision, so a manifest edit does not by itself move the reported change. A retained file this pull request renamed or deleted still counts as retained at the base.
  • Pull request movement uses physical additions/deletions from git diff base...head --numstat; it counts retained files too and is intentionally separate from SLOC totals.
  • Core excludes SDK kit infrastructure and vendored libraries. Standalone kits include only files below Kits/**/Sources.
  • Tests, examples, headers, build outputs, vendored libraries, and the MParticle/Sources Swift overlay are excluded.
  • Objective-C++ (.mm) is included in the Objective-C figures and removed counts.

Generated with cloc 2.10. This report is informational and does not gate migration direction.

@nickolas-dimitrakas nickolas-dimitrakas self-assigned this Sep 1, 2026
@nickolas-dimitrakas
nickolas-dimitrakas marked this pull request as ready for review September 1, 2026 21:36
@nickolas-dimitrakas
nickolas-dimitrakas requested a review from a team as a code owner September 1, 2026 21:36
@cursor

cursor Bot commented Sep 1, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Changes are CI, documentation, lockfile, and test harness only; no production SDK behavior is modified.

Overview
Ports CI reliability fixes and ObjC unit-test timing/thread-safety improvements onto the swift-migration branch, plus slimmer agent docs and per-kit CODEOWNERS.

CI: native-tests waits for simulator boot (simctl bootstatus), turns off parallel test clones, and enables per-test timeouts. build-kits adds job/step timeouts and replaces bare SPM resolve with git low-speed settings, an 8-minute watchdog, child-process cleanup, and two retry attempts. Java setup moves to actions/setup-java@v6 in cross-platform and integration workflows.

Tests: Workspace-switch cases in MParticleTests drop nested dispatch_after delays in favor of MPWaitForCondition (main-run-loop polling until initialized, kit registry state, or a new shared instance). MPRoktTests stops the partial mock before releasing the kit under test. The testActiveKitsRegistryThreadSafety stress path records failures under an NSLock and asserts on the main queue instead of calling XCTest APIs from worker threads.

Repo hygiene: AGENTS.md is rewritten as a short, repo-specific agent guide (commands, traps, PR/CI gotchas). Each kit under Kits/ gets a .github/CODEOWNERS (Rokt SDK+ → @ROKT/sdk-engineering). RNExample/package-lock.json picks up routine transitive npm bumps.

Reviewed by Cursor Bugbot for commit 6322ca6. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

📦 SDK Size Impact Report

Measures how much the SDK adds to an app's size (with-SDK minus without-SDK).

Metric Target Branch This PR Change
App Bundle Impact 2.38 MB 2.38 MB +N/A
Executable Impact 848 bytes 848 bytes +N/A
XCFramework Size 6.84 MB 6.84 MB +N/A

➡️ SDK size impact change is minimal.

Raw measurements

Target 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}

nickolas-dimitrakas and others added 2 commits September 2, 2026 09:57
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>
@nickolas-dimitrakas
nickolas-dimitrakas force-pushed the fix/port-ci-and-concurrency-fixes-to-swift-migration branch from 5b6c5ad to 6322ca6 Compare September 2, 2026 13:59

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread UnitTests/ObjCTests/MParticleTests.m
@nickolas-dimitrakas nickolas-dimitrakas changed the title fix: port CI hang fixes and workspace-switch condition waits to swift-migration fix: merge main into workstation/swift-migration and apply pending test fixes Sep 2, 2026
@nickolas-dimitrakas
nickolas-dimitrakas merged commit 906036f into workstation/swift-migration Sep 2, 2026
156 of 157 checks passed
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.

5 participants