Skip to content

Commit 77b6379

Browse files
hurali97thymikee
andauthored
feat(android): brownfield plugin (#160)
* feat: add brownfield-android plugin to templates * feat: scaffold plugin-brownfield-android * fix: use name without dash * feat: add brownfield android template files * feat: add and update template files * feat: register task for aar generation * feat: expose separate functions for AAR generation * refactor: default to helloworld * feat: add and update files for template * feat: register task for aar local maven publishing * refactor: avoid duplicate consts * chore: bump to latest version * refactor: extract re-used code * chore: generate changeset * test: add test for plugin-brownfield-android * feat: update versions after sync with main * feat: use variant * docs: add brownfield docs for android * chore: add changeset * chore: remove previous changeset * Update packages/platform-android/src/lib/commands/buildAndroid/buildAndroid.ts Co-authored-by: Michał Pierzchała <[email protected]> * Update packages/plugin-brownfield-android/package.json Co-authored-by: Michał Pierzchała <[email protected]> * Apply suggestions from code review Co-authored-by: Michał Pierzchała <[email protected]> * Update BROWNFIELD.md Co-authored-by: Michał Pierzchała <[email protected]> * refactor: remove package-name * refactor: separate Aar options and use function for config * refactor: rename to ReactNativeHostManager * Update packages/platform-android/src/lib/commands/runGradle.ts Co-authored-by: Michał Pierzchała <[email protected]> * refactor: add error cause * update version * move to docs * update titles * remove plugin from defaults * bring back local publish * refactor * feat: use brownfield-gradle-plugin --------- Co-authored-by: Michał Pierzchała <[email protected]>
1 parent 49e7bc0 commit 77b6379

File tree

31 files changed

+1049
-15
lines changed

31 files changed

+1049
-15
lines changed

.changeset/quick-lamps-hear.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@rnef/plugin-brownfield-android': patch
3+
'@rnef/platform-android': patch
4+
'@rnef/create-app': patch
5+
---
6+
7+
add android brownfield plugin
93.2 KB
Loading
11.7 KB
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
11
export * from './lib/platformAndroid.js';
2+
export {
3+
type PackageAarFlags,
4+
packageAar,
5+
options as packageAarOptions,
6+
} from './lib/commands/aar/packageAar.js';
7+
export {
8+
type PublishLocalAarFlags,
9+
publishLocalAar,
10+
options as publishLocalAarOptions,
11+
} from './lib/commands/aar/publishLocalAar.js';
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { outro } from '@rnef/tools';
2+
import { runGradleAar } from '../runGradle.js';
3+
import { toPascalCase } from '../toPascalCase.js';
4+
5+
export interface AarProject {
6+
sourceDir: string;
7+
moduleName: string;
8+
}
9+
10+
export type PackageAarFlags = {
11+
variant: string;
12+
moduleName?: string;
13+
};
14+
15+
export async function packageAar(
16+
aarProject: AarProject,
17+
args: PackageAarFlags
18+
) {
19+
normalizeArgs(args);
20+
21+
const tasks = [`assemble${toPascalCase(args.variant)}`];
22+
23+
await runGradleAar({ tasks, aarProject, args });
24+
outro('Success 🎉.');
25+
}
26+
27+
export async function localPublishAar(
28+
aarProject: AarProject,
29+
args: PackageAarFlags
30+
) {
31+
const tasks = ['publishToMavenLocal'];
32+
33+
await runGradleAar({ tasks, aarProject, args, isPublishTask: true });
34+
outro('Success 🎉.');
35+
}
36+
37+
function normalizeArgs(args: PackageAarFlags) {
38+
if (!args.variant) {
39+
args.variant = 'debug';
40+
}
41+
}
42+
43+
export const options = [
44+
{
45+
name: '--variant <string>',
46+
description:
47+
"Specify your app's build variant, which is constructed from build type and product flavor, e.g. 'debug' or 'freeRelease'.",
48+
},
49+
{
50+
name: '--module-name <string>',
51+
description: 'AAR module name',
52+
},
53+
];
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { outro } from '@rnef/tools';
2+
import { runGradleAar } from '../runGradle.js';
3+
import type { AarProject } from './packageAar.js';
4+
5+
export type PublishLocalAarFlags = {
6+
moduleName: string;
7+
};
8+
9+
export async function publishLocalAar(
10+
aarProject: AarProject,
11+
args: PublishLocalAarFlags
12+
) {
13+
const tasks = ['publishToMavenLocal'];
14+
15+
await runGradleAar({ tasks, aarProject, args, isPublishTask: true });
16+
outro('Success 🎉.');
17+
}
18+
19+
export const options = [
20+
{
21+
name: '--module-name <string>',
22+
description: 'AAR module name',
23+
},
24+
];

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

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,33 @@ import {
66
spinner,
77
type SubprocessError,
88
} from '@rnef/tools';
9+
import type { AarProject, PackageAarFlags } from './aar/packageAar.js';
10+
import type { PublishLocalAarFlags } from './aar/publishLocalAar.js';
911
import type { BuildFlags } from './buildAndroid/buildAndroid.js';
1012
import { getAdbPath, getDevices } from './runAndroid/adb.js';
1113
import type { AndroidProject, Flags } from './runAndroid/runAndroid.js';
1214

15+
type RunGradleAarArgs = {
16+
tasks: string[];
17+
aarProject: AarProject;
18+
args: PackageAarFlags | PublishLocalAarFlags;
19+
isPublishTask?: boolean;
20+
};
21+
1322
export type RunGradleArgs = {
1423
tasks: string[];
1524
androidProject: AndroidProject;
1625
args: BuildFlags | Flags;
1726
};
1827

28+
const getCleanedErrorMessage = (error: SubprocessError) => {
29+
return error.stderr
30+
.split('\n')
31+
.filter((line) => !gradleLinesToRemove.some((l) => line.includes(l)))
32+
.join('\n')
33+
.trim();
34+
};
35+
1936
export async function runGradle({
2037
tasks,
2138
androidProject,
@@ -69,11 +86,9 @@ export async function runGradle({
6986
);
7087
} catch (error) {
7188
loader.stop('Failed to build the app');
72-
const cleanedErrorMessage = (error as SubprocessError).stderr
73-
.split('\n')
74-
.filter((line) => !gradleLinesToRemove.some((l) => line.includes(l)))
75-
.join('\n')
76-
.trim();
89+
const cleanedErrorMessage = getCleanedErrorMessage(
90+
error as SubprocessError
91+
);
7792

7893
if (cleanedErrorMessage) {
7994
logger.error(cleanedErrorMessage);
@@ -87,6 +102,61 @@ export async function runGradle({
87102
}
88103
}
89104

105+
export async function runGradleAar({
106+
tasks,
107+
aarProject,
108+
args,
109+
isPublishTask = false,
110+
}: RunGradleAarArgs) {
111+
if ('binaryPath' in args) {
112+
return;
113+
}
114+
const loader = spinner({ indicator: 'timer' });
115+
const message = isPublishTask
116+
? 'Publishing the AAR'
117+
: // @ts-expect-error args.variant is not set for publish task
118+
`Building the AAR with Gradle in ${args.variant} build variant`;
119+
120+
loader.start(message);
121+
const gradleArgs = getTaskNames(aarProject.moduleName, tasks);
122+
123+
gradleArgs.push('-x', 'lint');
124+
125+
const gradleWrapper = getGradleWrapper();
126+
127+
try {
128+
logger.debug(`Running ${gradleWrapper} ${gradleArgs.join(' ')}.`);
129+
await spawn(gradleWrapper, gradleArgs, {
130+
cwd: aarProject.sourceDir,
131+
stdio: logger.isVerbose() ? 'inherit' : 'pipe',
132+
});
133+
loader.stop(
134+
isPublishTask
135+
? 'Published the AAR to local maven (~/.m2/repository)'
136+
: // @ts-expect-error args.variant is not set for publish task
137+
`Built the AAR in ${args.variant} build variant.`
138+
);
139+
} catch (error) {
140+
loader.stop(`Failed to ${isPublishTask ? 'publish' : 'build'} the AAR`);
141+
const cleanedErrorMessage = getCleanedErrorMessage(
142+
error as SubprocessError
143+
);
144+
145+
if (cleanedErrorMessage) {
146+
logger.error(cleanedErrorMessage);
147+
}
148+
149+
const hints = getErrorHints((error as SubprocessError).stdout ?? '');
150+
throw new RnefError(
151+
hints ||
152+
`Failed to ${
153+
isPublishTask ? 'publish' : 'build'
154+
} the AAR. See the error above for details from Gradle.`,
155+
{ cause: (error as SubprocessError).stderr }
156+
);
157+
}
158+
}
159+
90160
function getErrorHints(output: string) {
91161
const signingMessage = output.includes('validateSigningRelease FAILED')
92162
? `Hint: You can run "${color.bold(
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# plugin-brownfield-android
2+
3+
This library was generated with [Nx](https://nx.dev).
4+
5+
## Building
6+
7+
Run `nx build plugin-brownfield-android` to build the library.
8+
9+
## Running unit tests
10+
11+
Run `nx test plugin-brownfield-ios` to execute the unit tests via [Vitest](https://vitest.dev/).
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import baseConfig from '../../eslint.config.js';
2+
3+
export default baseConfig;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "@rnef/plugin-brownfield-android",
3+
"version": "0.4.1",
4+
"type": "module",
5+
"exports": {
6+
"types": "./dist/src/index.d.ts",
7+
"import": "./dist/src/index.js"
8+
},
9+
"files": [
10+
"dist",
11+
"src",
12+
"template"
13+
],
14+
"scripts": {
15+
"publish:npm": "npm publish --access restricted",
16+
"publish:verdaccio": "npm publish --registry http://localhost:4873 --userconfig ../../.npmrc"
17+
},
18+
"dependencies": {
19+
"@rnef/tools": "^0.4.1",
20+
"@rnef/platform-android": "^0.4.1",
21+
"@react-native-community/cli-config-android": "^16.0.2",
22+
"tslib": "^2.3.0"
23+
},
24+
"devDependencies": {
25+
"@rnef/config": "^0.4.1",
26+
"@react-native-community/cli-types": "^16.0.2"
27+
},
28+
"publishConfig": {
29+
"access": "restricted"
30+
}
31+
}

0 commit comments

Comments
 (0)