From 87f297d880b7257a0ee15886a88a6ee59869a590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kalina?= Date: Mon, 11 May 2026 21:41:23 +0200 Subject: [PATCH 1/2] fix(create-app): preserve existing arg list when patching Podfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `updatePodfile` ran a regex that matched `config = use_native_modules!` plus the whitespace after `!`, but not any existing argument tuple. That works for Community-CLI Podfile templates (call has no argument), but Expo's prebuild template calls it with `config_command` as the argument. The patch then inserted Rock's array right before the existing `(config_command)`, leaving two consecutive call expressions on the same line — invalid Ruby: config = use_native_modules!(['npx', 'rock', 'config', '-p', 'ios'])(config_command) ^ unexpected '(' Every subsequent `pod install` (and `rock run:ios`) failed on Expo projects after `npm create rock`. Fix: extend the regex to also consume any existing parenthesized argument list, so it gets replaced in full. On Community-CLI Podfiles the optional group matches nothing — behaviour is unchanged. On Expo prebuild Podfiles the existing `(config_command)` is now consumed and replaced cleanly. Adds four `updatePodfile` test cases: - Community-CLI template (bare `use_native_modules!`) - Expo prebuild template (`use_native_modules!(config_command)`) - Idempotency on an already-patched Podfile - Missing Podfile is a no-op The `updatePodfile` function is now exported for testability, mirroring the existing `updateAndroidBuildGradle` export. Fixes #702 --- .../__tests__/initInExistingProject.test.ts | 72 ++++++++++++++++++- .../src/lib/utils/initInExistingProject.ts | 12 +++- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/packages/create-app/src/lib/utils/__tests__/initInExistingProject.test.ts b/packages/create-app/src/lib/utils/__tests__/initInExistingProject.test.ts index 8c3660113..d13291d64 100644 --- a/packages/create-app/src/lib/utils/__tests__/initInExistingProject.test.ts +++ b/packages/create-app/src/lib/utils/__tests__/initInExistingProject.test.ts @@ -2,7 +2,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; import { cleanup, getTempDirectory, writeFiles } from '@rock-js/test-helpers'; import * as tools from '@rock-js/tools'; -import { updateAndroidBuildGradle } from '../initInExistingProject.js'; +import { updateAndroidBuildGradle, updatePodfile } from '../initInExistingProject.js'; const directory = getTempDirectory('test_updateAndroidBuildGradle'); @@ -120,3 +120,73 @@ describe('updateAndroidBuildGradle', () => { ); }); }); + +describe('updatePodfile', () => { + it('replaces a bare `use_native_modules!` call (Community-CLI template)', () => { + const content = ` +target 'App' do + config = use_native_modules! + + use_react_native!(:path => config[:reactNativePath]) +end +`; + const expected = ` +target 'App' do + config = use_native_modules!(['npx', 'rock', 'config', '-p', 'ios']) + + use_react_native!(:path => config[:reactNativePath]) +end +`; + writeFiles(directory, { 'ios/Podfile': content }); + updatePodfile(directory, 'ios'); + + expect( + fs.readFileSync(path.join(directory, 'ios/Podfile'), 'utf8'), + ).toStrictEqual(expected); + }); + + it('replaces a `use_native_modules!(config_command)` call (Expo prebuild template, regression test for #702)', () => { + const content = ` +target 'App' do + config_command = ['node', '--no-warnings', '--eval', "require('expo/bin/autolinking')"] + config = use_native_modules!(config_command) + + use_react_native!(:path => config[:reactNativePath]) +end +`; + const expected = ` +target 'App' do + config_command = ['node', '--no-warnings', '--eval', "require('expo/bin/autolinking')"] + config = use_native_modules!(['npx', 'rock', 'config', '-p', 'ios']) + + use_react_native!(:path => config[:reactNativePath]) +end +`; + writeFiles(directory, { 'ios/Podfile': content }); + updatePodfile(directory, 'ios'); + + expect( + fs.readFileSync(path.join(directory, 'ios/Podfile'), 'utf8'), + ).toStrictEqual(expected); + }); + + it('is idempotent — running on an already-patched Podfile is a no-op', () => { + const content = ` +target 'App' do + config = use_native_modules!(['npx', 'rock', 'config', '-p', 'ios']) +end +`; + writeFiles(directory, { 'ios/Podfile': content }); + updatePodfile(directory, 'ios'); + + expect( + fs.readFileSync(path.join(directory, 'ios/Podfile'), 'utf8'), + ).toStrictEqual(content); + }); + + it('does nothing when there is no Podfile', () => { + // No Podfile written; updatePodfile should return without throwing. + expect(() => updatePodfile(directory, 'ios')).not.toThrow(); + }); +}); + diff --git a/packages/create-app/src/lib/utils/initInExistingProject.ts b/packages/create-app/src/lib/utils/initInExistingProject.ts index 572d2771a..93d461af0 100644 --- a/packages/create-app/src/lib/utils/initInExistingProject.ts +++ b/packages/create-app/src/lib/utils/initInExistingProject.ts @@ -271,15 +271,21 @@ Please update the "Bundle React Native code and images" build phase manually wit ); } -function updatePodfile(projectRoot: string, sourceDir: string) { +export function updatePodfile(projectRoot: string, sourceDir: string) { const filePath = path.join(projectRoot, sourceDir, 'Podfile'); if (!fs.existsSync(filePath)) { return; } const content = fs.readFileSync(filePath, 'utf8'); + // Replace `config = use_native_modules!` together with any existing + // argument list. The Community-CLI Podfile template calls it with no + // arguments (`use_native_modules!`), but the Expo prebuild template + // passes its own autolinking command in (`use_native_modules!(config_command)`). + // Without consuming that argument the previous regex left it dangling + // on the line and produced invalid Ruby — see issue #702. const replaced = content.replace( - /(config\s*=\s*use_native_modules!)(\s*)/g, - "$1(['npx', 'rock', 'config', '-p', 'ios'])$2", + /(config\s*=\s*use_native_modules!)(\s*\([^)]*\))?/g, + "$1(['npx', 'rock', 'config', '-p', 'ios'])", ); if ( !content.includes(`(['npx', 'rock', 'config', '-p', 'ios'])`) && From 67164611a229bbd1b0f84b6c3866d87afcb8cfcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kalina?= Date: Wed, 13 May 2026 11:42:38 +0200 Subject: [PATCH 2/2] chore: add changeset --- .changeset/podfile-patch-preserve-args.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/podfile-patch-preserve-args.md diff --git a/.changeset/podfile-patch-preserve-args.md b/.changeset/podfile-patch-preserve-args.md new file mode 100644 index 000000000..3c7e330eb --- /dev/null +++ b/.changeset/podfile-patch-preserve-args.md @@ -0,0 +1,5 @@ +--- +'create-rock': patch +--- + +fix(create-app): preserve existing arg list when patching Podfile