Repository navigation
chore(react-native-plugin)!: resolve posthog-ios through Swift Package Manager - #5449
Conversation
…e Manager posthog-ios 4.0 ships on Swift Package Manager only, so the podspec always adds posthog-ios with React Native's spm_dependency helper instead of depending on the PostHog pod from CocoaPods trunk. That helper needs react-native / react-native-macos 0.75, so the peer floor moves from 0.71. Also stop setting screenshotModeBackgroundCapture, which posthog-ios 4.0 removes, and turn the posthog.useSpm CI lane into a dynamic-frameworks lane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
PostHog Review · Standard · reviewed 6aafa73: 1 Should fix.
See this review and its findings in PostHog Review. Comment @posthog review --deep for a Deep review. A Deep review takes longer and looks deeper than a Standard review.
Coherence0 spec problems · 0 failing chokepoints · 2 spec gaps · 0 guard failures 44 components, 7 bullets (5 invariants, 2 requirements), 0 problems Chokepoints: none declared. Spec gaps: 2 entrances with outside or unknown trust and no traced control, and 10 more held by the adoption baseline
Close one with |
… isn't supported React Native's spm_dependency only searches the main Pods project for the plugin's target, so pod install crashed with that option on.
Node SDK compliance v2Commit: f392811 Capture v0 — acceptance✅ 28 passed / ❌ 3 non-passing / Drill-down: run artifacts → ❌ server_snapshot_payload_false — failed_assertionExpected native data result Code: Failed step: acceptance/public/evaluate-flags.feature:868 the public snapshot outcomes should have these semantics: ❌ server_snapshot_payload_zero — failed_assertionExpected native data result Code: Failed step: acceptance/public/evaluate-flags.feature:868 the public snapshot outcomes should have these semantics: ❌ server_snapshot_payload_null — failed_assertionExpected native data result Code: Failed step: acceptance/public/evaluate-flags.feature:868 the public snapshot outcomes should have these semantics: Harness exit: 1; report validation exit: 1. Capture v1 — acceptance✅ 28 passed / ❌ 3 non-passing / Drill-down: run artifacts → ❌ server_snapshot_payload_false — failed_assertionExpected native data result Code: Failed step: acceptance/public/evaluate-flags.feature:868 the public snapshot outcomes should have these semantics: ❌ server_snapshot_payload_zero — failed_assertionExpected native data result Code: Failed step: acceptance/public/evaluate-flags.feature:868 the public snapshot outcomes should have these semantics: ❌ server_snapshot_payload_null — failed_assertionExpected native data result Code: Failed step: acceptance/public/evaluate-flags.feature:868 the public snapshot outcomes should have these semantics: Harness exit: 1; report validation exit: 1. Capture v0 — migration✅ 55 passed / ❌ 1 non-passing / Drill-down: run artifacts → ❌ migration/yaml-parity-v1/remote-flags-v1.feature::Omitted GeoIP settings default to enabled in flag requests — failed_assertionFlags field differs Code: Failed step: migration/yaml-parity-v1/remote-flags-v1.feature:134 the first flags request field "geoip_disable" should equal JSON false Operation: Field: Expected: false Actual value: true Harness exit: 1; report validation exit: 1. Capture v1 — migration✅ 120 passed / ❌ 1 non-passing / Drill-down: run artifacts → ❌ migration/yaml-parity-v1/remote-flags-v1.feature::Omitted GeoIP settings default to enabled in flag requests — failed_assertionFlags field differs Code: Failed step: migration/yaml-parity-v1/remote-flags-v1.feature:134 the first flags request field "geoip_disable" should equal JSON false Operation: Field: Expected: false Actual value: true Harness exit: 1; report validation exit: 1. |
dustinbyrne
left a comment
There was a problem hiding this comment.
The multi-project diagnostic addresses the earlier concern. Disabled target deduplication still reaches a missing-target failure; there is also an optional Podfile re-entry improvement inline.
AI-assisted review.
…sn't supported With target deduplication off, CocoaPods names the plugin's target posthog-react-native-plugin-Pods-<App>, and React Native's spm_dependency looks it up by its exact pod name, so pod install crashed on a nil target. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…spec Autolinking evaluates the podspec while the Podfile is still loading, so Pod::Config#podfile loaded the Podfile again from the plugin directory, re-running use_native_modules! and its CLI config command. Read the already-loaded Podfile instead; pod install re-evaluates the :path podspec afterwards, so the install! option checks still run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Covers PostHog/posthog-js#5449: posthog-ios always comes from SwiftPM, and screenshotModeBackgroundCapture is ignored on iOS.
dustinbyrne
left a comment
There was a problem hiding this comment.
Both previous findings are addressed. One multi-application case with different iOS deployment targets still reaches the SPM missing-target failure; details inline.
AI-assisted review.
…tforms or linkage aren't supported CocoaPods then splits the plugin into scoped targets (posthog-react-native-plugin-iOS15.1, -framework/-library), and React Native's spm_dependency crashed on a nil target looking up the exact pod name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dustinbyrne
left a comment
There was a problem hiding this comment.
The concrete-target diagnostics are verified. My earlier rooted example was incorrect: App16 does not inherit the plugin. One abstract-parent variant still escapes the guard; details inline.
AI-assisted review.
…oped pods An abstract parent with a platform gets its own plugin variant, so a different linkage there splits the target too.
dustinbyrne
left a comment
There was a problem hiding this comment.
Verified the abstract-target diagnostic and aligned-target controls. The earlier findings are addressed.
AI-assisted review.
…e Manager (#5449) * chore(react-native-plugin)!: resolve posthog-ios through Swift Package Manager posthog-ios 4.0 ships on Swift Package Manager only, so the podspec always adds posthog-ios with React Native's spm_dependency helper instead of depending on the PostHog pod from CocoaPods trunk. That helper needs react-native / react-native-macos 0.75, so the peer floor moves from 0.71. Also stop setting screenshotModeBackgroundCapture, which posthog-ios 4.0 removes, and turn the posthog.useSpm CI lane into a dynamic-frameworks lane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(react-native-plugin): explain that generate_multiple_pod_projects isn't supported React Native's spm_dependency only searches the main Pods project for the plugin's target, so pod install crashed with that option on. * fix(react-native-plugin): explain that deduplicate_targets => false isn't supported With target deduplication off, CocoaPods names the plugin's target posthog-react-native-plugin-Pods-<App>, and React Native's spm_dependency looks it up by its exact pod name, so pod install crashed on a nil target. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(react-native-plugin): don't reload the app's Podfile from the podspec Autolinking evaluates the podspec while the Podfile is still loading, so Pod::Config#podfile loaded the Podfile again from the plugin directory, re-running use_native_modules! and its CLI config command. Read the already-loaded Podfile instead; pod install re-evaluates the :path podspec afterwards, so the install! option checks still run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(react-native-plugin): explain that app targets with different platforms or linkage aren't supported CocoaPods then splits the plugin into scoped targets (posthog-react-native-plugin-iOS15.1, -framework/-library), and React Native's spm_dependency crashed on a nil target looking up the exact pod name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(react-native-plugin): count abstract targets when checking for scoped pods An abstract parent with a platform gets its own plugin variant, so a different linkage there splits the target too. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Problem
posthog-ios 4.0 ships on Swift Package Manager only (PostHog/posthog-ios#972). The plugin's podspec gets posthog-ios from CocoaPods trunk by default (
s.dependency 'PostHog'), and only uses SwiftPM when the app setsposthog.useSpm. Trunk will never have 4.x, so with the 4.0 pin (#5237) the defaultpod installfails. Stacked on #5194 (plugin 3.0).Changes
spm_dependency. It no longer depends on thePostHogpod or readsposthog.useSpm.posthog_ios_versionstays the one source for the version.react-nativepeer>=0.71→>=0.75. The podspec raises a clear error whenspm_dependencyis missing.spm_dependencyfirst ships in react-native 0.75.0 and react-native-macos 0.75 (checked in the npm tarballs: absent in 0.74.7 / macOS 0.74.5). The 0.71 changeset from #5194 is edited to 0.75.sessionReplayConfig.screenshotModeBackgroundCaptureon iOS.posthog.useSpmlane becomes a dynamic-frameworks lane.Dynamic frameworks aren't required. The old podspec comment said the SwiftPM path needs
use_frameworks! :linkage => :dynamic. With current React Native and Xcode 26 that isn't true: static libraries, static frameworks and dynamic frameworks all build and run (see below).pod installstill prints React Native's generic "static linking might cause linker errors" warning for static linkage. Expo apps don't needexpo-build-propertieschanges.Merge order
screenshotModeBackgroundCaptureremoval turns off that experimental option on 3.88.2, which is fine because 3.0 doesn't ship without chore(react-native-plugin)!: require posthog-ios 4.0 #5237.check-spm-manifest.mjsstill matches. Its "the plugin's Swift needs no changes for 4.0" note was written before fix: Remove debug code from survey-utils #937 merged. This PR has the fix.For the maintainer
use_frameworks! :linkage => :dynamicnote from chore: re-enable bundle checker now master and branches both use pnpm #972's wrapper section.posthog.useSpmis no longer needed.posthog-react-native-session-replaypackage get posthog-ios 3.x from trunk next to 4.x from SwiftPM. I didn't test that combination.Release info Sub-libraries affected
Libraries affected
Checklist
If releasing new changes
pnpm changesetto generate a changeset file. Addedrn-plugin-v3-spm.mdandrn-plugin-v3-screenshot-background-capture.md, and edited the RN floor changeset (renamed torn-plugin-v3-react-native-075.md).🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Claude Code (Opus 5.5), run as a subagent from Anna's session. Tools: git, gh, pnpm, CocoaPods, xcodebuild, simctl.
Local builds used Xcode 26.4.1, with #5194 + #5237 + #5236 merged and posthog-ios pointed at #972's branch (
chore/v4-spm-only@d079f97) through a temporaryspm_dependencybranch requirement. That override isn't committed.examples/example-rn-native-plugin(RN 0.79.6), iOS simulator: static libraries (default),USE_FRAMEWORKS=static,USE_FRAMEWORKS=dynamicpod install+ Debug build pass for all three; Release passes for static. Each launches, and a temporarysetup()call resolves with replaybufferinginscreenshotcapture mode. CrashReporter and libwebp are linked, so default traits are on.pod install+ Debug build pass.examples/example-expo-57(Expo 57, RN 0.86.2, static libraries, precompiled modules) with packed local tarballsexpo prebuild+pod install+ simulator Debug build pass. Not launched.spm_dependency(pod ipc spec)pnpm lint,pnpm typecheck,pnpm test:unit;actionlinton the workflowNot verified: React Native's full-SwiftPM path (
examples/example-rn-spm) against 4.0 with #5237's traits (this PR doesn't touchPackage.swift); Release builds other than static; devices; RN 0.75–0.78. Local tooling needed workarounds that don't come from the plugin (Ruby 4 + json 3 broke Expo'spod install, and the CommandLineTools SDK broke native compiles).🤖 Generated with Claude Code