Skip to content
This repository was archived by the owner on Jun 19, 2026. It is now read-only.

Commit b2bd035

Browse files
chore: source posthog-ios via SPM as opt-in (#81)
Add an opt-in Swift Package Manager resolution path for posthog-ios so consumers can sidestep CocoaPods ahead of trunk freezing on 2026-12-02 and posthog-ios dropping its podspec. Unblocks PostHog/posthog-ios#472 from the React Native side. Set "posthog.useSpm": "true" in your app's ios/Podfile.properties.json (and use_frameworks! :linkage => :dynamic) to engage the SPM path. Default behavior is unchanged: without the property, posthog-ios continues to resolve through CocoaPods trunk via `s.dependency 'PostHog', '~> 3.58.1'`. Example app upgraded to RN 0.79.6 and pnpm switched to node-linker=hoisted so both CI cells (build-ios-static-lib and build-ios-spm) build cleanly on Xcode 26.
1 parent 97ed936 commit b2bd035

41 files changed

Lines changed: 1152 additions & 778 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'posthog-react-native-session-replay': minor
3+
---
4+
5+
Add an opt-in Swift Package Manager resolution path for `posthog-ios`. Set `"posthog.useSpm": "true"` in your app's `ios/Podfile.properties.json` and (on RN >= 0.75) `pod install` will resolve `posthog-ios` from `https://github.com/PostHog/posthog-ios.git` via the RN `spm_dependency` helper instead of CocoaPods trunk.
6+
7+
Default behavior is unchanged: without the property, `posthog-ios` resolves through CocoaPods. This makes the SPM path available ahead of [PostHog/posthog-ios#472](https://github.com/PostHog/posthog-ios/issues/472) and the CocoaPods trunk read-only date (2026-12-02) without forcing consumers to migrate yet.
8+
9+
The SPM path uses `upToNextMinorVersion: 3.58.1` to match the existing CocoaPods `~> 3.58.1` constraint and requires `use_frameworks! :linkage => :dynamic` in the consumer's `Podfile` ([known RN limitation](https://github.com/facebook/react-native/pull/44627#issuecomment-2123119711)).

.github/workflows/ci.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ concurrency:
1414
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
1515
cancel-in-progress: true
1616

17+
permissions:
18+
contents: read
19+
1720
jobs:
1821
lint:
1922
runs-on: ubuntu-latest
@@ -146,3 +149,40 @@ jobs:
146149
run: |
147150
cd example/ios
148151
set -o pipefail && xcrun xcodebuild -workspace PosthogReactNativeSessionReplayExample.xcworkspace -configuration Debug -scheme posthog-react-native-session-replay -destination generic/platform=ios | xcpretty
152+
153+
build-ios-spm:
154+
# Exercises the opt-in path: `posthog.useSpm` in Podfile.properties.json
155+
# routes posthog-ios through the React Native spm_dependency helper.
156+
# The SPM path requires dynamic frameworks. macos-26 uses the latest
157+
# Xcode shipped with the runner image.
158+
runs-on: macos-26
159+
steps:
160+
- name: Checkout
161+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
162+
163+
- name: Print Xcode version
164+
run: xcodebuild -version
165+
166+
- name: Setup
167+
uses: ./.github/actions/setup
168+
169+
- name: Opt example into SPM resolution
170+
run: |
171+
cat > example/ios/Podfile.properties.json <<'JSON'
172+
{
173+
"posthog.useSpm": "true"
174+
}
175+
JSON
176+
177+
- name: Install cocoapods
178+
run: |
179+
cd example/ios
180+
pod install
181+
env:
182+
NO_FLIPPER: 1
183+
USE_FRAMEWORKS: dynamic
184+
185+
- name: Build example for iOS Simulator
186+
run: |
187+
cd example/ios
188+
xcodebuild -workspace PosthogReactNativeSessionReplayExample.xcworkspace -configuration Debug -scheme posthog-react-native-session-replay -sdk iphonesimulator -destination 'generic/platform=iOS Simulator'

.github/workflows/codeql.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ jobs:
1313
name: Analyze (${{ matrix.language }})
1414
runs-on: ${{ matrix.runner }}
1515
permissions:
16+
actions: read # required by the CodeQL action
17+
contents: read # required for actions/checkout and CodeQL result upload
1618
security-events: write # for uploading CodeQL results
1719
packages: read
1820
strategy:

.npmrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
# Minimum age (in minutes) before a package version can be installed
22
# 10080 minutes = 7 days
33
min-release-age=10080
4+
5+
# Hoisted node_modules layout so React Native's iOS autolinking and
6+
# CocoaPods see a flat dependency tree without pnpm's .pnpm/ symlink
7+
# layer. The symlinked layout causes Xcode "Multiple commands produce"
8+
# errors when multiple Pods copy headers from the shared react-native
9+
# node_modules path.
10+
node-linker=hoisted

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,17 @@ Session Replay for React Native (Android and iOS)
77
```sh
88
npm install posthog-react-native-session-replay
99
```
10+
11+
## iOS dependency resolution
12+
13+
By default, `posthog-ios` is resolved through CocoaPods trunk via `pod install`.
14+
15+
[CocoaPods trunk goes read-only on 2026-12-02](https://blog.cocoapods.org/CocoaPods-Specs-Repo/) and `posthog-ios` is moving to Swift Package Manager (see [PostHog/posthog-ios#472](https://github.com/PostHog/posthog-ios/issues/472)). To opt this package into the SPM resolution path early, add the following to your app's `ios/Podfile.properties.json`:
16+
17+
```json
18+
{
19+
"posthog.useSpm": "true"
20+
}
21+
```
22+
23+
When that property is set and React Native >= 0.75 is in use, `pod install` resolves `posthog-ios` from `https://github.com/PostHog/posthog-ios.git` via the RN `spm_dependency` helper. The SPM path requires `use_frameworks! :linkage => :dynamic` in your `Podfile` ([known limitation](https://github.com/facebook/react-native/pull/44627#issuecomment-2123119711)).

example/.eslintrc.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
root: true,
3+
extends: '@react-native',
4+
};

example/.gitignore

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# OSX
2+
#
3+
.DS_Store
4+
5+
# Xcode
6+
#
7+
build/
8+
*.pbxuser
9+
!default.pbxuser
10+
*.mode1v3
11+
!default.mode1v3
12+
*.mode2v3
13+
!default.mode2v3
14+
*.perspectivev3
15+
!default.perspectivev3
16+
xcuserdata
17+
*.xccheckout
18+
*.moved-aside
19+
DerivedData
20+
*.hmap
21+
*.ipa
22+
*.xcuserstate
23+
**/.xcode.env.local
24+
25+
# Android/IntelliJ
26+
#
27+
build/
28+
.idea
29+
.gradle
30+
local.properties
31+
*.iml
32+
*.hprof
33+
.cxx/
34+
*.keystore
35+
!debug.keystore
36+
.kotlin/
37+
38+
# node.js
39+
#
40+
node_modules/
41+
npm-debug.log
42+
yarn-error.log
43+
44+
# fastlane
45+
#
46+
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47+
# screenshots whenever they are needed.
48+
# For more information about the recommended setup visit:
49+
# https://docs.fastlane.tools/best-practices/source-control/
50+
51+
**/fastlane/report.xml
52+
**/fastlane/Preview.html
53+
**/fastlane/screenshots
54+
**/fastlane/test_output
55+
56+
# Bundle artifact
57+
*.jsbundle
58+
59+
# Ruby / CocoaPods
60+
**/Pods/
61+
/vendor/bundle/
62+
63+
# Temporary files created by Metro to check the health of the file watcher
64+
.metro-health-check*
65+
66+
# testing
67+
/coverage
68+
69+
# Yarn
70+
.yarn/*
71+
!.yarn/patches
72+
!.yarn/plugins
73+
!.yarn/releases
74+
!.yarn/sdks
75+
!.yarn/versions

example/.prettierrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
arrowParens: 'avoid',
3+
bracketSameLine: true,
4+
bracketSpacing: false,
5+
singleQuote: true,
6+
trailingComma: 'all',
7+
};

example/Gemfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,11 @@ ruby ">= 2.6.10"
66
# Exclude problematic versions of cocoapods and activesupport that causes build failures.
77
gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
88
gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
9+
gem 'xcodeproj', '< 1.26.0'
10+
gem 'concurrent-ruby', '< 1.3.4'
11+
12+
# Ruby 3.4.0 has removed some libraries from the standard library.
13+
gem 'bigdecimal'
14+
gem 'logger'
15+
gem 'benchmark'
16+
gem 'mutex_m'

example/README.md

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,56 +2,76 @@ This is a new [**React Native**](https://reactnative.dev) project, bootstrapped
22

33
# Getting Started
44

5-
> **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
5+
> **Note**: Make sure you have completed the [Set Up Your Environment](https://reactnative.dev/docs/set-up-your-environment) guide before proceeding.
66
7-
## Step 1: Start the Metro Server
7+
## Step 1: Start Metro
88

9-
First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.
9+
First, you will need to run **Metro**, the JavaScript build tool for React Native.
1010

11-
To start Metro, run the following command from the _root_ of your React Native project:
11+
To start the Metro dev server, run the following command from the root of your React Native project:
1212

13-
```bash
14-
pnpm start
13+
```sh
14+
# Using npm
15+
npm start
1516

16-
# OR from the monorepo root (recommended)
17-
pnpm example start
17+
# OR using Yarn
18+
yarn start
1819
```
1920

20-
## Step 2: Start your Application
21+
## Step 2: Build and run your app
2122

22-
Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:
23+
With Metro running, open a new terminal window/pane from the root of your React Native project, and use one of the following commands to build and run your Android or iOS app:
2324

24-
### For Android
25+
### Android
2526

26-
```bash
27-
pnpm android
27+
```sh
28+
# Using npm
29+
npm run android
2830

29-
# OR from the monorepo root (recommended)
30-
pnpm example android
31+
# OR using Yarn
32+
yarn android
3133
```
3234

33-
### For iOS
35+
### iOS
3436

35-
```bash
37+
For iOS, remember to install CocoaPods dependencies (this only needs to be run on first clone or after updating native deps).
3638

37-
pnpm ios
39+
The first time you create a new project, run the Ruby bundler to install CocoaPods itself:
3840

39-
# OR from the monorepo root (recommended)
40-
pnpm example ios
41+
```sh
42+
bundle install
4143
```
4244

43-
If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.
45+
Then, and every time you update your native dependencies, run:
4446

45-
This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.
47+
```sh
48+
bundle exec pod install
49+
```
50+
51+
For more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html).
52+
53+
```sh
54+
# Using npm
55+
npm run ios
56+
57+
# OR using Yarn
58+
yarn ios
59+
```
60+
61+
If everything is set up correctly, you should see your new app running in the Android Emulator, iOS Simulator, or your connected device.
62+
63+
This is one way to run your app — you can also build it directly from Android Studio or Xcode.
64+
65+
## Step 3: Modify your app
4666

47-
## Step 3: Modifying your App
67+
Now that you have successfully run the app, let's make changes!
4868

49-
Now that you have successfully run the app, let's modify it.
69+
Open `App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes — this is powered by [Fast Refresh](https://reactnative.dev/docs/fast-refresh).
5070

51-
1. Open `App.tsx` in your text editor of choice and edit some lines.
52-
2. For **Android**: Press the <kbd>R</kbd> key twice or select **"Reload"** from the **Developer Menu** (<kbd>Ctrl</kbd> + <kbd>M</kbd> (on Window and Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (on macOS)) to see your changes!
71+
When you want to forcefully reload, for example to reset the state of your app, you can perform a full reload:
5372

54-
For **iOS**: Hit <kbd>Cmd ⌘</kbd> + <kbd>R</kbd> in your iOS Simulator to reload the app and see your changes!
73+
- **Android**: Press the <kbd>R</kbd> key twice or select **"Reload"** from the **Dev Menu**, accessed via <kbd>Ctrl</kbd> + <kbd>M</kbd> (Windows/Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (macOS).
74+
- **iOS**: Press <kbd>R</kbd> in iOS Simulator.
5575

5676
## Congratulations! :tada:
5777

@@ -60,11 +80,11 @@ You've successfully run and modified your React Native App. :partying_face:
6080
### Now what?
6181

6282
- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
63-
- If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started).
83+
- If you're curious to learn more about React Native, check out the [docs](https://reactnative.dev/docs/getting-started).
6484

6585
# Troubleshooting
6686

67-
If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
87+
If you're having issues getting the above steps to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
6888

6989
# Learn More
7090

0 commit comments

Comments
 (0)