Skip to content

Commit 5bfc606

Browse files
committed
Improve CLI:
- add checks for package.json, RN dependency - add ability to version a RN project from any other folder via the "projectPath" argument - add some status text output, "--quiet" option
1 parent fd06977 commit 5bfc606

File tree

5 files changed

+113
-37
lines changed

5 files changed

+113
-37
lines changed

README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ react-native-version will then update your `android/` and `ios/` code. Depending
4949

5050
```shell
5151
npm install -g react-native-version
52+
# or
53+
yarn global add react-native-version
5254
```
5355

5456
### Example usage
@@ -65,13 +67,14 @@ react-native-version
6567
-h, --help output usage information
6668
-V, --version output the version number
6769
-a, --amend Amend the previous commit. Also updates the latest Git tag to point to the amended commit. This is done automatically when react-native-version is run from the "version" or "postversion" npm script. Use "--never-amend" if you never want to amend.
68-
--skip-tag For use with "--amend" if you don't want to update Git tags
69-
-A, --never-amend Never amend the previous commit
70-
-b, --increment-build Only increment build number
71-
-d, --android [path] Path to your "android/app/build.gradle" file
72-
-i, --ios [path] Path to your "ios/" folder
73-
-r, --reset-build Reset build number back to "1" (iOS only). Unlike Android's "versionCode", iOS doesn't require you to bump the "CFBundleVersion", as long as "CFBundleShortVersionString" changes. To make it consistent across platforms, react-native-version bumps both by default. You can use this option if you prefer to reset the build number after every version change. If you then need to push another build under the same version, you can use "-bt ios".
74-
-t, --target <platforms> Only version specified platforms, eg. "--target android,ios"
70+
--skip-tag For use with "--amend", if you don't want to update Git tags.
71+
-A, --never-amend Never amend the previous commit.
72+
-b, --increment-build Only increment build number.
73+
-d, --android [path] Path to your "android/app/build.gradle" file.
74+
-i, --ios [path] Path to your "ios/" folder.
75+
-q, --quiet Be quiet, only report errors.
76+
-r, --reset-build Reset build number back to "1" (iOS only). Unlike Android's "versionCode", iOS doesn't require you to bump the "CFBundleVersion", as long as "CFBundleShortVersionString" changes. To make it consistent across platforms, react-native-version bumps both by default. You can use this option if you prefer to keep the build number value at "1" after every version change. If you then need to push another build under the same version, you can use "-bt ios" to increment.
77+
-t, --target <platforms> Only version specified platforms, eg. "--target android,ios".
7578
```
7679

7780
You can apply these options to the "version" or "postversion" script too. If for example you want to commit the changes made by RNV yourself, add the "--never-amend" option:
@@ -133,7 +136,7 @@ version({
133136

134137
<a name="version"></a>
135138

136-
#### version(program) ⇒ <code>Promise.&lt;(string\|Error)&gt;</code>
139+
#### version(program, projectPath) ⇒ <code>Promise.&lt;(string\|Error)&gt;</code>
137140
Versions your app
138141

139142
**Kind**: global function
@@ -142,6 +145,7 @@ Versions your app
142145
| Param | Type | Description |
143146
| --- | --- | --- |
144147
| program | <code>Object</code> | commander/CLI-style options, camelCased |
148+
| projectPath | <code>string</code> | Path to your React Native project |
145149

146150
### Types
147151

cli.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@ const defaults = rnv.getDefaults();
99

1010
program
1111
.version(pkg.version)
12+
.description(pkg.description)
13+
.arguments('[projectPath]')
1214
/* eslint-disable max-len */
1315
.option('-a, --amend', 'Amend the previous commit. Also updates the latest Git tag to point to the amended commit. This is done automatically when ' + pkg.name + ' is run from the "version" or "postversion" npm script. Use "--never-amend" if you never want to amend.')
14-
.option('--skip-tag', 'For use with "--amend" if you don\'t want to update Git tags')
15-
.option('-A, --never-amend', 'Never amend the previous commit')
16-
.option('-b, --increment-build', 'Only increment build number')
17-
.option('-d, --android [path]', 'Path to your "android/app/build.gradle" file', defaults.android)
18-
.option('-i, --ios [path]', 'Path to your "ios/" folder', defaults.ios)
19-
.option('-r, --reset-build', 'Reset build number back to "1" (iOS only). Unlike Android\'s "versionCode", iOS doesn\'t require you to bump the "CFBundleVersion", as long as "CFBundleShortVersionString" changes. To make it consistent across platforms, ' + pkg.name + ' bumps both by default. You can use this option if you prefer to reset the build number after every version change. If you then need to push another build under the same version, you can use "-bt ios".')
20-
.option('-t, --target <platforms>', 'Only version specified platforms, eg. "--target android,ios"', list)
16+
.option('--skip-tag', 'For use with "--amend", if you don\'t want to update Git tags.')
17+
.option('-A, --never-amend', 'Never amend the previous commit.')
18+
.option('-b, --increment-build', 'Only increment build number.')
19+
.option('-d, --android [path]', 'Path to your "android/app/build.gradle" file.', defaults.android)
20+
.option('-i, --ios [path]', 'Path to your "ios/" folder.', defaults.ios)
21+
.option('-q, --quiet', 'Be quiet, only report errors.')
22+
.option('-r, --reset-build', 'Reset build number back to "1" (iOS only). Unlike Android\'s "versionCode", iOS doesn\'t require you to bump the "CFBundleVersion", as long as "CFBundleShortVersionString" changes. To make it consistent across platforms, ' + pkg.name + ' bumps both by default. You can use this option if you prefer to keep the build number value at "1" after every version change. If you then need to push another build under the same version, you can use "-bt ios" to increment.')
23+
.option('-t, --target <platforms>', 'Only version specified platforms, eg. "--target android,ios".', list)
2124
/* eslint-enable */
2225
.parse(process.argv);
2326

index.js

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,79 @@ const env = {
2121
* @return {Object} Defaults
2222
*/
2323
function getDefaults() {
24-
const cwd = process.cwd();
25-
2624
return {
27-
android: path.join(cwd, 'android/app/build.gradle'),
28-
cwd: cwd,
29-
ios: path.join(cwd, 'ios')
25+
android: 'android/app/build.gradle',
26+
ios: 'ios'
3027
};
3128
}
3229

3330
/**
3431
* Versions your app
3532
* @param {Object} program commander/CLI-style options, camelCased
33+
* @param {string} projectPath Path to your React Native project
3634
* @return {Promise<string|Error>} A promise which resolves with the last commit hash
3735
*/
38-
function version(program) {
39-
const programOpts = Object.assign({}, getDefaults(), program);
36+
function version(program, projectPath) {
37+
const prog = Object.assign({}, getDefaults(), program || {});
38+
const projPath = path.resolve(process.cwd(), projectPath || prog.args[0] || '');
39+
40+
const programOpts = Object.assign({}, prog, {
41+
android: path.join(projPath, prog.android),
42+
ios: path.join(projPath, prog.ios)
43+
});
4044

4145
const targets = []
4246
.concat(programOpts.target, env.target)
4347
.filter(Boolean);
4448

45-
const appPkg = require(path.join(programOpts.cwd, 'package.json'));
49+
const appPkgJSONPath = path.join(projPath, 'package.json');
50+
const MISSING_RN_DEP = 'MISSING_RN_DEP';
51+
var appPkg;
52+
53+
try {
54+
appPkg = require(appPkgJSONPath);
55+
56+
if (!appPkg.dependencies['react-native']) {
57+
throw new Error(MISSING_RN_DEP);
58+
}
59+
} catch (err) {
60+
if (err.message === MISSING_RN_DEP) {
61+
log({
62+
style: 'red',
63+
text: 'Is this the right folder? React Native isn\'t listed as a dependency in '
64+
+ appPkgJSONPath
65+
});
66+
} else {
67+
log({
68+
style: 'red',
69+
text: err.message
70+
});
71+
72+
log({
73+
style: 'red',
74+
text: 'Is this the right folder? Looks like there isn\'t a package.json here'
75+
});
76+
}
77+
78+
log({
79+
style: 'yellow',
80+
text: 'Pass the project path as an argument, see --help for usage'
81+
});
82+
83+
if (program.outputHelp) {
84+
program.outputHelp();
85+
}
86+
87+
process.exit(1);
88+
}
89+
4690
var android;
4791
var ios;
4892

4993
if (!targets.length || targets.indexOf('android') > -1) {
5094
android = new Promise(function(resolve, reject) {
95+
log({text: 'Versioning Android...'}, programOpts.quiet);
96+
5197
var gradleFile;
5298

5399
try {
@@ -78,12 +124,15 @@ function version(program) {
78124
});
79125

80126
fs.writeFileSync(programOpts.android, gradleFile);
127+
log({text: 'Android updated'}, programOpts.quiet);
81128
resolve();
82129
});
83130
}
84131

85132
if (!targets.length || targets.indexOf('ios') > -1) {
86133
ios = new Promise(function(resolve, reject) {
134+
log({text: 'Versioning iOS...'}, programOpts.quiet);
135+
87136
try {
88137
child.execSync('xcode-select --print-path', {
89138
stdio: ['ignore', 'ignore', 'pipe']
@@ -137,6 +186,7 @@ function version(program) {
137186
child.execSync('agvtool next-version -all', agvtoolOpts);
138187
}
139188

189+
log({text: 'iOS updated'}, programOpts.quiet);
140190
resolve();
141191
});
142192
}
@@ -174,7 +224,7 @@ function version(program) {
174224
}
175225

176226
const gitCmdOpts = {
177-
cwd: programOpts.cwd
227+
cwd: projPath
178228
};
179229

180230
if (
@@ -183,28 +233,44 @@ function version(program) {
183233
&& process.env.npm_lifecycle_event.indexOf('version') > -1
184234
&& !programOpts.neverAmend
185235
) {
236+
log({text: 'Amending...'}, programOpts.quiet);
237+
186238
switch (process.env.npm_lifecycle_event) {
187239
case 'version':
188-
child.spawnSync('git', ['add', program.android, program.ios], gitCmdOpts);
240+
child.spawnSync(
241+
'git', ['add', programOpts.android, programOpts.ios], gitCmdOpts
242+
);
243+
189244
break;
190245

191246
case 'postversion':
192247
default:
193248
child.execSync('git commit -a --amend --no-edit', gitCmdOpts);
194249

195-
if (!program.skipTag) {
250+
if (!programOpts.skipTag) {
251+
log({text: 'Adjusting Git tag...'}, programOpts.quiet);
196252
child.execSync('git tag -f $(git tag | tail -1)', gitCmdOpts);
197253
}
198254
}
199255
}
200256

257+
log({
258+
style: 'green',
259+
text: 'Done'
260+
}, programOpts.quiet);
261+
201262
return child.execSync('git log -1 --pretty=%H', gitCmdOpts).toString();
202263
})
203264
.catch(function(err) {
204265
if (process.env.RNV_ENV === 'ava') {
205266
console.error(err);
206267
}
207268

269+
log({
270+
style: 'red',
271+
text: 'Done, with errors.'
272+
});
273+
208274
process.exit(1);
209275
});
210276
}

test/index.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ test('API: default', async t => {
1818
tempInitAndVersion();
1919

2020
await version({
21-
cwd: t.context.tempDir
22-
});
21+
quiet: true
22+
}, t.context.tempDir);
2323

2424
t.deepEqual(await getCurrTree(t), expectedTree.notAmended);
2525
});
@@ -29,8 +29,8 @@ test('API: amend', async t => {
2929

3030
await version({
3131
amend: true,
32-
cwd: t.context.tempDir
33-
});
32+
quiet: true
33+
}, t.context.tempDir);
3434

3535
t.deepEqual(await getCurrTree(t), expectedTree.amended);
3636

@@ -45,9 +45,9 @@ test('API: amend, skipTag', async t => {
4545

4646
await version({
4747
amend: true,
48-
cwd: t.context.tempDir,
48+
quiet: true,
4949
skipTag: true
50-
});
50+
}, t.context.tempDir);
5151

5252
t.deepEqual(await getCurrTree(t), expectedTree.amended);
5353

@@ -61,9 +61,9 @@ test('API: neverAmend', async t => {
6161
tempInitAndVersion();
6262

6363
await version({
64-
cwd: t.context.tempDir,
65-
neverAmend: true
66-
});
64+
neverAmend: true,
65+
quiet: true
66+
}, t.context.tempDir);
6767

6868
t.deepEqual(await getCurrTree(t), expectedTree.notAmended);
6969
});

util.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ function list(val) {
1212
/**
1313
* Logs a message into the console with style
1414
* @param {Object} msg Object containing the message text and chalk style
15+
* @param {boolean} silent Whether log should be quiet
1516
*/
16-
function log(msg) {
17-
console.log(chalk[msg.style || 'reset'](msg.text));
17+
function log(msg, silent) {
18+
if (!silent) {
19+
console.log('[RNV]', chalk[msg.style || 'reset'](msg.text));
20+
}
1821
}
1922

2023
module.exports = {

0 commit comments

Comments
 (0)