From b9a365a7fb6faa8888b615b2834d4738d0d23605 Mon Sep 17 00:00:00 2001 From: Alexander Pantiukhov Date: Mon, 12 Oct 2026 14:02:49 +0200 Subject: [PATCH 1/2] fix(react-native): Skip CocoaPods steps for Swift Package Manager projects `react-native spm add --deintegrate` keeps a Podfile that `pod install` cannot parse. The wizard found this Podfile, added `use_modular_headers!` to it, and offered to run `pod install`, which failed. The wizard now finds the SwiftPM autolinking package in the Xcode project and skips these steps. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 4 +++ src/react-native/react-native-wizard.ts | 41 ++++++++++++++++++------- src/react-native/xcode.ts | 11 +++++++ test/react-native/xcode.test.ts | 36 ++++++++++++++++++++++ 4 files changed, 81 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bad815887..e47ad5bf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased + +- fix(react-native): Do not change the Podfile or run `pod install` when the iOS project uses Swift Package Manager ([#XXXX](https://github.com/getsentry/sentry-wizard/pull/XXXX)) + ## 9.1.0 - feat(sourcemaps): Import the Vite, webpack, Rollup and esbuild plugins from the installed SDK (`@sentry/node`, `@sentry/nestjs`, `@sentry/aws-serverless`) on v11, or install `@sentry/bundler-plugins` as a dev dependency and import from `@sentry/bundler-plugins/` ([#1382](https://github.com/getsentry/sentry-wizard/pull/1382)) diff --git a/src/react-native/react-native-wizard.ts b/src/react-native/react-native-wizard.ts index e8bb8e9cc..6fd1142ce 100644 --- a/src/react-native/react-native-wizard.ts +++ b/src/react-native/react-native-wizard.ts @@ -54,6 +54,7 @@ import { findDebugFilesUploadPhase, getValidExistingBuildPhases, patchBundlePhase, + usesSwiftPMAutolinking, writeXcodeProject, } from './xcode'; @@ -349,20 +350,38 @@ async function patchXcodeFiles(config: RNCliSetupConfigContent) { gitignore: false, }); - // The RNSentry pod is a Swift pod and requires `use_modular_headers!` in the - // Podfile to integrate as a static library. Patch it before `pod install` so - // the install succeeds now and any later manual `pod install` keeps working. - if (usesCocoaPod('ios')) { - traceStep('add-modular-headers', () => addModularHeaders('ios')); - } - - if (platform() === 'darwin' && (await confirmPodInstall())) { - await traceStep('pod-install', () => podInstall('ios')); - } - const xcodeProjectPath = traceStep('find-xcode-project', () => getFirstMatchedPath(XCODE_PROJECT), ); + + // `react-native spm add --deintegrate` keeps a Podfile that `pod install` + // cannot parse. + const usesSwiftPM = + !!xcodeProjectPath && usesSwiftPMAutolinking(xcodeProjectPath); + Sentry.setTag( + 'ios-dependency-manager', + usesSwiftPM ? 'swiftpm' : 'cocoapods', + ); + + if (usesSwiftPM) { + clack.log.info( + `The iOS project uses Swift Package Manager. The wizard does not change the ${chalk.cyan( + 'Podfile', + )} and does not run ${chalk.cyan('pod install')}.`, + ); + } else { + // The RNSentry pod is a Swift pod and requires `use_modular_headers!` in the + // Podfile to integrate as a static library. Patch it before `pod install` so + // the install succeeds now and any later manual `pod install` keeps working. + if (usesCocoaPod('ios')) { + traceStep('add-modular-headers', () => addModularHeaders('ios')); + } + + if (platform() === 'darwin' && (await confirmPodInstall())) { + await traceStep('pod-install', () => podInstall('ios')); + } + } + Sentry.setTag( 'xcode-project-status', xcodeProjectPath ? 'found' : 'not-found', diff --git a/src/react-native/xcode.ts b/src/react-native/xcode.ts index 598d663b1..a4b7f8b3c 100644 --- a/src/react-native/xcode.ts +++ b/src/react-native/xcode.ts @@ -196,6 +196,17 @@ export function findDebugFilesUploadPhase( }); } +// React Native SwiftPM autolinking adds a local package at this path. +export function usesSwiftPMAutolinking(xcodeProjectPath: string): boolean { + try { + return /relativePath = "?build\/generated\/autolinking"?;/.test( + fs.readFileSync(xcodeProjectPath, 'utf-8'), + ); + } catch { + return false; + } +} + export function writeXcodeProject( xcodeProjectPath: string, xcodeProject: Project, diff --git a/test/react-native/xcode.test.ts b/test/react-native/xcode.test.ts index 407683953..77a1a0b09 100644 --- a/test/react-native/xcode.test.ts +++ b/test/react-native/xcode.test.ts @@ -6,7 +6,11 @@ import { findBundlePhase, findDebugFilesUploadPhase, ErrorPatchSnippet, + usesSwiftPMAutolinking, } from '../../src/react-native/xcode'; +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; import chalk from 'chalk'; import { makeCodeSnippet } from '../../src/utils/clack'; // @ts-expect-error - clack is ESM and TS complains about that. It works though @@ -435,4 +439,36 @@ sentry-cli upload-dsym path/to/dsym --include-sources expect(findDebugFilesUploadPhase(input)).toBeUndefined(); }); }); + + describe('usesSwiftPMAutolinking', () => { + const writeProject = (content: string) => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-xcode-project')); + const projectPath = path.join(dir, 'project.pbxproj'); + fs.writeFileSync(projectPath, content); + return projectPath; + }; + + it('returns true for a project with the autolinking package', () => { + const projectPath = + writeProject(`/* Begin XCLocalSwiftPackageReference section */ + C2FECF1430FDAAE3BF355839 /* XCLocalSwiftPackageReference "build/generated/autolinking" */ = {isa = XCLocalSwiftPackageReference; relativePath = build/generated/autolinking;}; +/* End XCLocalSwiftPackageReference section */`); + + expect(usesSwiftPMAutolinking(projectPath)).toBe(true); + }); + + it('returns false for a CocoaPods project', () => { + const projectPath = writeProject( + `shellScript = "\"\${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks.sh\"\n";`, + ); + + expect(usesSwiftPMAutolinking(projectPath)).toBe(false); + }); + + it('returns false if the project file does not exist', () => { + expect( + usesSwiftPMAutolinking(path.join(os.tmpdir(), 'missing.pbxproj')), + ).toBe(false); + }); + }); }); From 2f8dde5d1195d69f3dc4e6fa5fb07e0ed6e1bb42 Mon Sep 17 00:00:00 2001 From: Alexander Pantiukhov Date: Wed, 11 Nov 2026 13:55:42 +0100 Subject: [PATCH 2/2] docs(changelog): Link the SwiftPM entry to its pull request Replace the #XXXX placeholder with the number of the pull request that adds the entry. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e47ad5bf3..4c8ff215e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- fix(react-native): Do not change the Podfile or run `pod install` when the iOS project uses Swift Package Manager ([#XXXX](https://github.com/getsentry/sentry-wizard/pull/XXXX)) +- fix(react-native): Do not change the Podfile or run `pod install` when the iOS project uses Swift Package Manager ([#1386](https://github.com/getsentry/sentry-wizard/pull/1386)) ## 9.1.0