Skip to content

Commit 1bf4e79

Browse files
feat: Add pinningDisabled option in Expo
1 parent 6feb744 commit 1bf4e79

8 files changed

Lines changed: 106 additions & 53 deletions

File tree

.github/workflows/pull-request.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ jobs:
128128
- name: Set up Xcode
129129
uses: maxim-lobanov/setup-xcode@v1.7.0
130130
with:
131-
xcode-version: latest-stable
131+
# Avoid `latest-stable` (Xcode 17+ / Swift 6 defaults) breaking RoktUXHelper
132+
# source builds until Rokt pins are updated upstream.
133+
xcode-version: '^16.0.0'
132134

133135
- name: Set Xcode Toolchain
134136
run: echo "TOOLCHAINS=com.apple.dt.toolchain.XcodeDefault" >> $GITHUB_ENV

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Expo config plugin: optional `pinningDisabled` for `MPNetworkOptions` / `NetworkOptions` at SDK startup
13+
14+
### Fixed
15+
16+
- iOS sample CI: pin `Rokt-Widget` `~> 5.2.2` and constrain GitHub Actions to Xcode 16.x so `RoktUXHelper` compiles (avoids `BaseStyles` / missing `image` with bleeding-edge Xcode)
17+
1018
## [3.1.2] - 2026-05-28
1119

1220
### Fixed

ExpoTestApp/README.md

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -268,17 +268,18 @@ dependencies {
268268

269269
## Plugin Configuration Options
270270

271-
| Option | Type | Description |
272-
| ------------------------- | -------- | --------------------------------------------------------- |
273-
| `iosApiKey` | string | mParticle iOS API key |
274-
| `iosApiSecret` | string | mParticle iOS API secret |
275-
| `androidApiKey` | string | mParticle Android API key |
276-
| `androidApiSecret` | string | mParticle Android API secret |
277-
| `logLevel` | string | Log level: `none`, `error`, `warning`, `debug`, `verbose` |
278-
| `environment` | string | Environment: `development`, `production`, `autoDetect` |
279-
| `useEmptyIdentifyRequest` | boolean | Initialize with empty identify request (default: true) |
280-
| `dataPlanId` | string | Data plan ID for validation |
281-
| `dataPlanVersion` | number | Data plan version |
282-
| `iosKits` | string[] | iOS kit pod names (e.g., `["mParticle-Rokt"]`) |
283-
| `customBaseUrl` | string | Custom base URL for global CNAME setup on iOS and Android |
284-
| `androidKits` | string[] | Android kit dependencies (e.g., `["android-rokt-kit"]`) |
271+
| Option | Type | Description |
272+
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
273+
| `iosApiKey` | string | mParticle iOS API key |
274+
| `iosApiSecret` | string | mParticle iOS API secret |
275+
| `androidApiKey` | string | mParticle Android API key |
276+
| `androidApiSecret` | string | mParticle Android API secret |
277+
| `logLevel` | string | Log level: `none`, `error`, `warning`, `debug`, `verbose` |
278+
| `environment` | string | Environment: `development`, `production`, `autoDetect` |
279+
| `useEmptyIdentifyRequest` | boolean | Initialize with empty identify request (default: true) |
280+
| `dataPlanId` | string | Data plan ID for validation |
281+
| `dataPlanVersion` | number | Data plan version |
282+
| `iosKits` | string[] | iOS kit pod names (e.g., `["mParticle-Rokt"]`) |
283+
| `customBaseUrl` | string | Custom base URL for global CNAME setup on iOS and Android |
284+
| `pinningDisabled` | boolean | Disable SSL pinning (iOS: `MPNetworkOptions.pinningDisabled`; Android: `setPinningDisabledInDevelopment`) |
285+
| `androidKits` | string[] | Android kit dependencies (e.g., `["android-rokt-kit"]`) |

README.md

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,21 @@ npx expo run:android
7171

7272
### Plugin Configuration Options
7373

74-
| Option | Type | Required | Description |
75-
| ------------------------- | -------- | -------- | ------------------------------------------------------------------- |
76-
| `iosApiKey` | string | Yes | iOS API key from mParticle dashboard |
77-
| `iosApiSecret` | string | Yes | iOS API secret from mParticle dashboard |
78-
| `androidApiKey` | string | Yes | Android API key from mParticle dashboard |
79-
| `androidApiSecret` | string | Yes | Android API secret from mParticle dashboard |
80-
| `logLevel` | string | No | Log level: `'none'`, `'error'`, `'warning'`, `'debug'`, `'verbose'` |
81-
| `environment` | string | No | Environment: `'development'`, `'production'`, `'autoDetect'` |
82-
| `dataPlanId` | string | No | Data plan ID for validation |
83-
| `dataPlanVersion` | number | No | Data plan version |
84-
| `iosKits` | string[] | No | iOS kit pod names (e.g., `['mParticle-Rokt']`) |
85-
| `customBaseUrl` | string | No | Custom base URL for global CNAME setup on iOS and Android |
86-
| `androidKits` | string[] | No | Android kit artifact names (e.g., `['android-rokt-kit']`) |
87-
| `useEmptyIdentifyRequest` | boolean | No | Use empty user identify request at init (default: `true`) |
74+
| Option | Type | Required | Description |
75+
| ------------------------- | -------- | -------- | --------------------------------------------------------------------------------------------- |
76+
| `iosApiKey` | string | Yes | iOS API key from mParticle dashboard |
77+
| `iosApiSecret` | string | Yes | iOS API secret from mParticle dashboard |
78+
| `androidApiKey` | string | Yes | Android API key from mParticle dashboard |
79+
| `androidApiSecret` | string | Yes | Android API secret from mParticle dashboard |
80+
| `logLevel` | string | No | Log level: `'none'`, `'error'`, `'warning'`, `'debug'`, `'verbose'` |
81+
| `environment` | string | No | Environment: `'development'`, `'production'`, `'autoDetect'` |
82+
| `dataPlanId` | string | No | Data plan ID for validation |
83+
| `dataPlanVersion` | number | No | Data plan version |
84+
| `iosKits` | string[] | No | iOS kit pod names (e.g., `['mParticle-Rokt']`) |
85+
| `customBaseUrl` | string | No | Custom base URL for global CNAME setup on iOS and Android |
86+
| `pinningDisabled` | boolean | No | Disable SSL pinning (`MPNetworkOptions` on iOS; `setPinningDisabledInDevelopment` on Android) |
87+
| `androidKits` | string[] | No | Android kit artifact names (e.g., `['android-rokt-kit']`) |
88+
| `useEmptyIdentifyRequest` | boolean | No | Use empty user identify request at init (default: `true`) |
8889

8990
### Example with Kits
9091

@@ -123,14 +124,14 @@ For global CNAME setup, add the optional shared `customBaseUrl` setting:
123124
**iOS:**
124125

125126
- Adds mParticle SDK initialization to `AppDelegate` (supports both Swift and Objective-C)
126-
- Sets `MPNetworkOptions.customBaseURL` before startup when `customBaseUrl` is configured
127+
- Sets `MPNetworkOptions` (`customBaseURL` and/or `pinningDisabled`) before startup when those plugin options are configured
127128
- Configures `pre_install` hook in Podfile for dynamic framework linking
128129
- Adds specified kit pod dependencies
129130

130131
**Android:**
131132

132133
- Adds mParticle SDK initialization to `MainApplication` (supports both Kotlin and Java)
133-
- Sets `NetworkOptions.setCustomBaseURL` before startup when `customBaseUrl` is configured
134+
- Sets `NetworkOptions` (`setCustomBaseURL` and/or `setPinningDisabledInDevelopment`) before startup when those plugin options are configured
134135
- Adds specified kit Maven dependencies to `build.gradle`
135136

136137
### Version Support

plugin/src/withMParticle.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ export interface MParticlePluginProps {
6363
*/
6464
customBaseUrl?: string;
6565

66+
/**
67+
* When true, disables SSL certificate pinning for mParticle network traffic.
68+
*
69+
* - **iOS:** Sets `MPNetworkOptions.pinningDisabled` before startup.
70+
* - **Android:** Sets `NetworkOptions.Builder.setPinningDisabledInDevelopment(true)`
71+
* (mParticle's Android API for proxy/debug builds; see Android SDK docs).
72+
*/
73+
pinningDisabled?: boolean;
74+
6675
/**
6776
* Android kit artifact names to include (version auto-detected from core SDK)
6877
* @example ['android-rokt-kit', 'android-amplitude-kit']

plugin/src/withMParticleAndroid.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import { getCustomBaseUrl } from './customBaseUrl';
1010
// Tag used for mergeContents to identify code blocks added by this plugin
1111
const MPARTICLE_TAG = 'react-native-mparticle';
1212

13+
function shouldEmitNetworkOptions(props: MParticlePluginProps): boolean {
14+
return Boolean(getCustomBaseUrl(props) || props.pinningDisabled === true);
15+
}
16+
1317
/**
1418
* Get the mParticle log level string for Android
1519
*/
@@ -64,6 +68,7 @@ function generateKotlinInitCode(props: MParticlePluginProps): string {
6468
dataPlanVersion,
6569
} = props;
6670
const customBaseUrl = getCustomBaseUrl(props);
71+
const pinningDisabled = props.pinningDisabled === true;
6772

6873
const lines: string[] = [
6974
'// mParticle SDK initialization',
@@ -86,12 +91,17 @@ function generateKotlinInitCode(props: MParticlePluginProps): string {
8691
lines.push(` .dataplan("${dataPlanId}"${versionParam})`);
8792
}
8893

89-
if (customBaseUrl) {
94+
if (shouldEmitNetworkOptions(props)) {
9095
lines.push(' .networkOptions(');
9196
lines.push(' NetworkOptions.builder()');
92-
lines.push(
93-
` .setCustomBaseURL(${JSON.stringify(customBaseUrl)})`
94-
);
97+
if (customBaseUrl) {
98+
lines.push(
99+
` .setCustomBaseURL(${JSON.stringify(customBaseUrl)})`
100+
);
101+
}
102+
if (pinningDisabled) {
103+
lines.push(' .setPinningDisabledInDevelopment(true)');
104+
}
95105
lines.push(' .build()');
96106
lines.push(' )');
97107
}
@@ -120,6 +130,7 @@ function generateJavaInitCode(props: MParticlePluginProps): string {
120130
dataPlanVersion,
121131
} = props;
122132
const customBaseUrl = getCustomBaseUrl(props);
133+
const pinningDisabled = props.pinningDisabled === true;
123134

124135
const lines: string[] = [
125136
'// mParticle SDK initialization',
@@ -142,12 +153,17 @@ function generateJavaInitCode(props: MParticlePluginProps): string {
142153
lines.push(` .dataplan("${dataPlanId}"${versionParam})`);
143154
}
144155

145-
if (customBaseUrl) {
156+
if (shouldEmitNetworkOptions(props)) {
146157
lines.push(' .networkOptions(');
147158
lines.push(' NetworkOptions.builder()');
148-
lines.push(
149-
` .setCustomBaseURL(${JSON.stringify(customBaseUrl)})`
150-
);
159+
if (customBaseUrl) {
160+
lines.push(
161+
` .setCustomBaseURL(${JSON.stringify(customBaseUrl)})`
162+
);
163+
}
164+
if (pinningDisabled) {
165+
lines.push(' .setPinningDisabledInDevelopment(true)');
166+
}
151167
lines.push(' .build()');
152168
lines.push(' )');
153169
}
@@ -173,7 +189,7 @@ function getKotlinImports(props: MParticlePluginProps): string {
173189
'import com.mparticle.identity.IdentityApiRequest',
174190
];
175191

176-
if (getCustomBaseUrl(props)) {
192+
if (shouldEmitNetworkOptions(props)) {
177193
imports.push('import com.mparticle.networking.NetworkOptions');
178194
}
179195

@@ -190,7 +206,7 @@ function getJavaImports(props: MParticlePluginProps): string {
190206
'import com.mparticle.identity.IdentityApiRequest;',
191207
];
192208

193-
if (getCustomBaseUrl(props)) {
209+
if (shouldEmitNetworkOptions(props)) {
194210
imports.push('import com.mparticle.networking.NetworkOptions;');
195211
}
196212

plugin/src/withMParticleIOS.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,19 @@ function generateSwiftInitCode(props: MParticlePluginProps): string {
136136
}
137137

138138
const customBaseUrl = getCustomBaseUrl(props);
139-
if (customBaseUrl) {
139+
const pinningDisabled = props.pinningDisabled === true;
140+
if (customBaseUrl || pinningDisabled) {
140141
lines.push('let networkOptions = MPNetworkOptions()');
141-
lines.push(
142-
`networkOptions.customBaseURL = URL(string: ${JSON.stringify(
143-
customBaseUrl
144-
)})`
145-
);
142+
if (customBaseUrl) {
143+
lines.push(
144+
`networkOptions.customBaseURL = URL(string: ${JSON.stringify(
145+
customBaseUrl
146+
)})`
147+
);
148+
}
149+
if (pinningDisabled) {
150+
lines.push('networkOptions.pinningDisabled = true');
151+
}
146152
lines.push('mParticleOptions.networkOptions = networkOptions');
147153
}
148154

@@ -196,15 +202,21 @@ function generateObjcInitCode(props: MParticlePluginProps): string {
196202
}
197203

198204
const customBaseUrl = getCustomBaseUrl(props);
199-
if (customBaseUrl) {
205+
const pinningDisabled = props.pinningDisabled === true;
206+
if (customBaseUrl || pinningDisabled) {
200207
lines.push(
201208
'MPNetworkOptions *networkOptions = [[MPNetworkOptions alloc] init];'
202209
);
203-
lines.push(
204-
`networkOptions.customBaseURL = [NSURL URLWithString:@${JSON.stringify(
205-
customBaseUrl
206-
)}];`
207-
);
210+
if (customBaseUrl) {
211+
lines.push(
212+
`networkOptions.customBaseURL = [NSURL URLWithString:@${JSON.stringify(
213+
customBaseUrl
214+
)}];`
215+
);
216+
}
217+
if (pinningDisabled) {
218+
lines.push('networkOptions.pinningDisabled = YES;');
219+
}
208220
lines.push('mParticleOptions.networkOptions = networkOptions;');
209221
}
210222

sample/ios/Podfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ target 'MParticleSample' do
3434
:app_path => "#{Pod::Config.instance.installation_root}/.."
3535
)
3636
pod 'mParticle-Rokt', '~> 9.2'
37+
# Transitive `~> 5.2` can resolve to an older 5.2.x whose bundled RoktUXHelper
38+
# fails Swift compile on newer Xcode (e.g. BaseStyles.swift / `image` parameter).
39+
# Pin the Rokt line explicitly for reproducible sample + CI builds.
40+
pod 'Rokt-Widget', '~> 5.2.2'
3741

3842
target 'MParticleSampleTests' do
3943
inherit! :complete

0 commit comments

Comments
 (0)