Skip to content

Commit 6acb2db

Browse files
atljthymikee
andauthored
feat: integrate react-native-brownfield (#271)
* static pod linkage and target settings * add rn brownfield dependency * replace swift impl with rn brownfield example * mode -> configuration * enlist brownfield plugin again * upgrade rn brownfield version * add brownfield template to tsconfig * copy hermes and better logging * expose ReactNativeBundle through the template * changesets * update docs * remove the todo from podfile * cleanup, format, sync fs * Update website/docs/docs/brownfield/ios.mdx * mention podfile changes * support setting USE_FRAMEWORKS with brownfield option in pod install * avoid calling xcode info twice, update swift file * add comment * update, simplify, add images * typo * use relative paths * fix test * fix: make e2e tests run in non-interactive mode --------- Co-authored-by: Michał Pierzchała <[email protected]>
1 parent 778a11f commit 6acb2db

File tree

24 files changed

+363
-283
lines changed

24 files changed

+363
-283
lines changed

.changeset/curvy-crabs-care.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@rnef/plugin-brownfield-ios': patch
3+
---
4+
5+
Implement [react-native-brownfield](https://github.com/callstack/react-native-brownfield) to iOS brownfield template.

.changeset/rare-needles-accept.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@rnef/create-app': patch
3+
---
4+
5+
List the `brownfield-ios` plugin on the plugins list shown while creating an app.

packages/create-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"scripts": {
1313
"publish:npm": "npm publish --access public",
1414
"publish:verdaccio": "npm publish --registry http://localhost:4873 --userconfig ../../.npmrc",
15-
"e2e": "vitest --config vite.e2e.config.js"
15+
"e2e": "CI=true vitest --config vite.e2e.config.js"
1616
},
1717
"bin": {
1818
"create-app": "./dist/src/bin.js"

packages/create-app/src/lib/templates.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,16 @@ export const TEMPLATES: TemplateInfo[] = [
3232
},
3333
];
3434

35-
export const PLUGINS: TemplateInfo[] = [];
35+
export const PLUGINS: TemplateInfo[] = [
36+
{
37+
type: 'npm',
38+
name: 'brownfield-ios',
39+
packageName: '@rnef/plugin-brownfield-ios',
40+
version: 'latest',
41+
directory: 'template',
42+
importName: 'pluginBrownfieldIos',
43+
},
44+
];
3645

3746
export const BUNDLERS: TemplateInfo[] = [
3847
{

packages/create-app/src/lib/utils/prompts.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
color,
33
intro,
4+
isInteractive,
45
note,
56
outro,
67
promptConfirm,
@@ -124,7 +125,7 @@ export function promptPlatforms(
124125
export function promptPlugins(
125126
plugins: TemplateInfo[]
126127
): Promise<TemplateInfo[] | null> {
127-
if (plugins.length === 0) {
128+
if (plugins.length === 0 || !isInteractive()) {
128129
return Promise.resolve(null);
129130
}
130131

packages/platform-android/src/lib/commands/buildAndroid/__tests__/buildAndroid.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { PathLike } from 'node:fs';
22
import fs from 'node:fs';
33
import type { AndroidProjectConfig } from '@react-native-community/cli-types';
44
import * as tools from '@rnef/tools';
5-
import { color, spawn } from '@rnef/tools';
5+
import { spawn } from '@rnef/tools';
66
import type { Mock } from 'vitest';
77
import { test, vi } from 'vitest';
88
import { buildAndroid, type BuildFlags } from '../buildAndroid.js';
@@ -80,9 +80,9 @@ test('buildAndroid runs gradle build with correct configuration for debug and ou
8080
cwd: '/android',
8181
});
8282
expect(spinnerMock.stop).toBeCalledWith(
83-
`Build available at: ${color.cyan(
84-
'/android/app/build/outputs/bundle/debug/app-debug.aab'
85-
)}`
83+
expect.stringContaining(
84+
'android/app/build/outputs/bundle/debug/app-debug.aab'
85+
)
8686
);
8787
});
8888

packages/platform-android/src/lib/commands/buildAndroid/buildAndroid.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from 'node:path';
12
import type { AndroidProjectConfig } from '@react-native-community/cli-types';
23
import type { FingerprintSources } from '@rnef/tools';
34
import {
@@ -43,7 +44,11 @@ export async function buildAndroid(
4344
if (outputFilePath) {
4445
const loader = spinner();
4546
loader.start('');
46-
loader.stop(`Build available at: ${color.cyan(outputFilePath)}`);
47+
loader.stop(
48+
`Build available at: ${color.cyan(
49+
path.relative(process.cwd(), outputFilePath)
50+
)}`
51+
);
4752
}
4853
outro('Success 🎉.');
4954
}

packages/platform-apple-helpers/src/lib/commands/build/createBuild.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,21 @@ export const createBuild = async ({
2727
projectRoot,
2828
reactNativePath,
2929
fingerprintOptions,
30+
brownfield,
3031
}: {
3132
platformName: BuilderCommand['platformName'];
3233
projectConfig: ProjectConfig;
3334
args: BuildFlags;
3435
projectRoot: string;
3536
reactNativePath: string;
3637
fingerprintOptions: FingerprintSources;
38+
brownfield?: boolean;
3739
}) => {
3840
await validateArgs(args);
3941

4042
let xcodeProject: XcodeProjectInfo;
4143
let sourceDir: string;
44+
let scheme: string;
4245
const deviceOrSimulator = args.destination
4346
? // there can be multiple destinations, so we'll pick the first one
4447
args.destination[0].match(/simulator/i)
@@ -58,16 +61,24 @@ export const createBuild = async ({
5861
platformName,
5962
args,
6063
reactNativePath,
64+
brownfield,
6165
});
6266
// The path may not exist when we archive
6367
if (!args.archive) {
6468
const loader = spinner();
6569
loader.start('');
66-
loader.stop(`Build available at: ${color.cyan(appPath)}`);
70+
loader.stop(
71+
`Build available at: ${color.cyan(
72+
path.relative(process.cwd(), appPath)
73+
)}`
74+
);
6775
saveLocalBuildCache(artifactName, appPath);
6876
}
6977
xcodeProject = buildAppResult.xcodeProject;
7078
sourceDir = buildAppResult.sourceDir;
79+
// @ts-expect-error - scheme is not set when binaryPath is provided,
80+
// which is not supported for build command (but is used by run command)
81+
scheme = buildAppResult.scheme;
7182
} catch (error) {
7283
const message = `Failed to create ${args.archive ? 'archive' : 'build'}`;
7384
throw new RnefError(message, { cause: error });
@@ -92,6 +103,8 @@ export const createBuild = async ({
92103
// Save the IPA to the local build cache so it's available for remote-cache command
93104
saveLocalBuildCache(artifactName, ipaPath);
94105
}
106+
107+
return { scheme };
95108
};
96109

97110
async function validateArgs(args: BuildFlags) {

packages/platform-apple-helpers/src/lib/utils/buildApp.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export async function buildApp({
2323
deviceName,
2424
reactNativePath,
2525
binaryPath,
26+
brownfield,
2627
}: {
2728
args: RunFlags | BuildFlags;
2829
projectConfig: ProjectConfig;
@@ -33,6 +34,7 @@ export async function buildApp({
3334
projectRoot: string;
3435
reactNativePath: string;
3536
binaryPath?: string;
37+
brownfield?: boolean;
3638
}) {
3739
if (binaryPath) {
3840
return {
@@ -53,7 +55,8 @@ export async function buildApp({
5355
platformName,
5456
sourceDir,
5557
args.newArch,
56-
reactNativePath
58+
reactNativePath,
59+
brownfield
5760
);
5861
// When the project is not a workspace, we need to get the project config again,
5962
// because running pods install might have generated .xcworkspace project.

packages/platform-apple-helpers/src/lib/utils/pods.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export async function installPodsIfNeeded(
2323
platformName: ApplePlatform,
2424
sourceDir: string,
2525
newArch: boolean,
26-
reactNativePath: string
26+
reactNativePath: string,
27+
brownfield?: boolean
2728
) {
2829
const podsPath = path.join(sourceDir, 'Pods');
2930
const podfilePath = path.join(sourceDir, 'Podfile');
@@ -43,7 +44,13 @@ export async function installPodsIfNeeded(
4344

4445
if (!podsDirExists || hashChanged) {
4546
await runCodegen({ projectRoot, platformName, reactNativePath, sourceDir });
46-
await installPods({ projectRoot, sourceDir, podfilePath, newArch });
47+
await installPods({
48+
projectRoot,
49+
sourceDir,
50+
podfilePath,
51+
newArch,
52+
brownfield,
53+
});
4754
cacheManager.set(
4855
cacheKey,
4956
calculateCurrentHash({ podfilePath, podsPath, nativeDependencies })
@@ -92,6 +99,7 @@ async function runPodInstall(options: {
9299
sourceDir: string;
93100
newArch: boolean;
94101
useBundler: boolean;
102+
brownfield?: boolean;
95103
}) {
96104
if (!options.useBundler) {
97105
await validatePodCommand(options.sourceDir);
@@ -113,6 +121,7 @@ async function runPodInstall(options: {
113121
env: {
114122
RCT_NEW_ARCH_ENABLED: options.newArch ? '1' : '0',
115123
RCT_IGNORE_PODS_DEPRECATION: '1',
124+
...(options.brownfield && { USE_FRAMEWORKS: 'static' }),
116125
...(process.env['USE_THIRD_PARTY_JSC'] && {
117126
USE_THIRD_PARTY_JSC: process.env['USE_THIRD_PARTY_JSC'],
118127
}),
@@ -137,6 +146,7 @@ async function runPodInstall(options: {
137146
sourceDir: options.sourceDir,
138147
newArch: options.newArch,
139148
useBundler: options.useBundler,
149+
brownfield: options.brownfield,
140150
});
141151
} else {
142152
throw new RnefError(
@@ -177,6 +187,7 @@ async function installPods(options: {
177187
projectRoot: string;
178188
podfilePath: string;
179189
newArch: boolean;
190+
brownfield?: boolean;
180191
}) {
181192
if (!fs.existsSync(options.podfilePath)) {
182193
logger.debug(
@@ -195,6 +206,7 @@ async function installPods(options: {
195206
sourceDir: options.sourceDir,
196207
newArch: options.newArch,
197208
useBundler,
209+
brownfield: options.brownfield,
198210
});
199211
}
200212

0 commit comments

Comments
 (0)