Skip to content

Commit 7e8f11a

Browse files
committed
Automatically calculate version based on commits
1 parent f9c8cbb commit 7e8f11a

2 files changed

Lines changed: 114 additions & 42 deletions

File tree

components/git/release.js

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,10 @@ function builder(yargs) {
3535
}
3636

3737
function handler(argv) {
38-
if (argv.newVersion) {
39-
const newVersion = semver.clean(argv.newVersion);
40-
if (semver.valid(newVersion)) {
41-
if (argv.prepare) {
42-
return release(PREPARE, argv);
43-
} else if (argv.promote) {
44-
return release(PROMOTE, argv);
45-
}
46-
}
38+
if (argv.prepare) {
39+
return release(PREPARE, argv);
40+
} else if (argv.promote) {
41+
return release(PROMOTE, argv);
4742
}
4843

4944
// If more than one action is provided or no valid action
@@ -78,24 +73,39 @@ async function main(state, argv, cli, dir) {
7873

7974
if (prep.warnForWrongBranch()) return;
8075

76+
// If the new version was automatically calculated, confirm it.
77+
if (!argv.newVersion) {
78+
const create = await cli.prompt(
79+
`Create release with new version ${prep.newVersion}?`,
80+
{ defaultAnswer: true });
81+
82+
if (!create) {
83+
cli.error('Aborting release preparation process');
84+
return;
85+
}
86+
}
87+
8188
// Check the branch diff to determine if the releaser
8289
// wants to backport any more commits before proceeding.
8390
cli.startSpinner('Fetching branch-diff');
8491
const raw = prep.getBranchDiff({ onlyNotableChanges: false });
8592
const diff = raw.split('*');
8693
cli.stopSpinner('Got branch diff');
8794

88-
const staging = `v${semver.major(argv.newVersion)}.x-staging`;
89-
const proceed = await cli.prompt(
90-
`There are ${diff.length - 1} commits that may be ` +
91-
`backported to ${staging} - do you still want to proceed?`,
92-
{ defaultAnswer: false });
93-
94-
if (!proceed) {
95-
const seeDiff = await cli.prompt(
96-
'Do you want to see the branch diff?');
97-
if (seeDiff) cli.log(raw);
98-
return;
95+
const outstandingCommits = diff.length - 1;
96+
if (outstandingCommits !== 0) {
97+
const staging = `v${semver.major(prep.newVersion)}.x-staging`;
98+
const proceed = await cli.prompt(
99+
`There are ${outstandingCommits} commits that may be ` +
100+
`backported to ${staging} - do you still want to proceed?`,
101+
{ defaultAnswer: false });
102+
103+
if (!proceed) {
104+
const seeDiff = await cli.prompt(
105+
'Do you want to see the branch diff?');
106+
if (seeDiff) cli.log(raw);
107+
return;
108+
}
99109
}
100110

101111
return prep.prepare();

lib/prepare_release.js

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,24 @@ class ReleasePreparation {
1515
constructor(argv, cli, dir) {
1616
this.cli = cli;
1717
this.dir = dir;
18-
this.newVersion = semver.clean(argv.newVersion);
1918
this.isSecurityRelease = argv.security;
2019
this.isLTS = false;
2120
this.ltsCodename = '';
2221
this.date = '';
2322
this.config = getMergedConfig(this.dir);
2423

24+
// Allow passing optional new version.
25+
if (argv.newVersion) {
26+
const newVersion = semver.clean(argv.newVersion);
27+
if (!semver.valid(newVersion)) {
28+
cli.warn(`${newVersion} is not a valid semantic version.`);
29+
return;
30+
}
31+
this.newVersion = newVersion;
32+
} else {
33+
this.newVersion = this.calculateNewVersion();
34+
}
35+
2536
const { upstream, owner, repo, newVersion } = this;
2637

2738
this.versionComponents = {
@@ -54,17 +65,20 @@ class ReleasePreparation {
5465
await this.updateNodeVersion();
5566
cli.stopSpinner(`Updated 'src/node_version.h' for ${newVersion}`);
5667

57-
// Check whether to update NODE_MODULE_VERSION (default false).
58-
const shouldUpdateNodeModuleVersion = await cli.prompt(
59-
'Update NODE_MODULE_VERSION?', { defaultAnswer: false });
60-
if (shouldUpdateNodeModuleVersion) {
61-
const variant = await cli.prompt(
62-
'Specify variant (ex. \'v8_7.9\') for new NODE_MODULE_VERSION:',
63-
{ questionType: 'input', noSeparator: true });
64-
const versions = await cli.prompt(
65-
'Specify versions (ex. \'14.0.0-pre\') for new NODE_MODULE_VERSION:',
66-
{ questionType: 'input', noSeparator: true });
67-
this.updateNodeModuleVersion('node', variant, versions);
68+
// Check whether to update NODE_MODULE_VERSION.
69+
const isSemverMajor = versionComponents.minor === 0;
70+
if (isSemverMajor) {
71+
const shouldUpdateNodeModuleVersion = await cli.prompt(
72+
'Update NODE_MODULE_VERSION?', { defaultAnswer: false });
73+
if (shouldUpdateNodeModuleVersion) {
74+
const variant = await cli.prompt(
75+
'Specify variant (ex. \'v8_7.9\') for new NODE_MODULE_VERSION:',
76+
{ questionType: 'input', noSeparator: true });
77+
const versions = await cli.prompt(
78+
'Specify versions (ex. \'14.0.0-pre\') for new NODE_MODULE_VERSION:',
79+
{ questionType: 'input', noSeparator: true });
80+
this.updateNodeModuleVersion('node', variant, versions);
81+
}
6882
}
6983

7084
// Update any REPLACEME tags in the docs.
@@ -154,6 +168,32 @@ class ReleasePreparation {
154168
return this.config.username;
155169
}
156170

171+
calculateNewVersion() {
172+
let newVersion;
173+
174+
const lastTagVersion = semver.clean(this.getLastRef());
175+
const lastTag = {
176+
major: semver.major(lastTagVersion),
177+
minor: semver.minor(lastTagVersion),
178+
patch: semver.patch(lastTagVersion)
179+
};
180+
181+
const raw = this.getBranchDiff({
182+
onlyNotableChanges: false,
183+
comparisonBranch: `v${lastTagVersion}`
184+
});
185+
186+
if (raw.includes('SEMVER-MAJOR')) {
187+
newVersion = `${lastTag.major + 1}.0.0`;
188+
} else if (raw.includes('SEMVER-MINOR')) {
189+
newVersion = `${lastTag.major}.${lastTag.minor + 1}.0`;
190+
} else {
191+
newVersion = `${lastTag.major}.${lastTag.minor}.${lastTag.patch + 1}`;
192+
}
193+
194+
return newVersion;
195+
}
196+
157197
getCurrentBranch() {
158198
return runSync('git', ['rev-parse', '--abbrev-ref', 'HEAD']).trim();
159199
}
@@ -253,14 +293,21 @@ class ReleasePreparation {
253293
` ${releaseInfo}, @${username}\n`;
254294

255295
for (let idx = 0; idx < arr.length; idx++) {
256-
if (arr[idx].includes(`<a id="${lastRef.substring(1)}"></a>`)) {
296+
const topHeader =
297+
`<a href="#${lastRef.substring(1)}">${lastRef.substring(1)}</a><br/>`;
298+
if (arr[idx].includes(topHeader)) {
299+
const newHeader =
300+
`<a href="#${newVersion}">${newVersion}</a><br/>`;
301+
arr.splice(idx, 1, newHeader);
302+
} else if (arr[idx].includes(`<a id="${lastRef.substring(1)}"></a>`)) {
257303
const toAppend = [];
258304
toAppend.push(`<a id="${newVersion}"></a>`);
259305
toAppend.push(releaseHeader);
260306
toAppend.push('### Notable Changes\n');
261307
toAppend.push(notableChanges);
262308
toAppend.push('### Commits\n');
263309
toAppend.push(allCommits);
310+
toAppend.push('');
264311

265312
arr.splice(idx, 0, ...toAppend);
266313
break;
@@ -345,23 +392,33 @@ class ReleasePreparation {
345392

346393
cli.log(`${messageTitle}\n\n${messageBody.join('')}`);
347394
const useMessage = await cli.prompt(
348-
'Continue with this commit message?');
395+
'Continue with this commit message?', { defaultAnswer: false });
349396
return useMessage;
350397
}
351398

352399
getBranchDiff(opts) {
353400
const {
354-
versionComponents,
355-
stagingBranch,
401+
versionComponents = {},
356402
upstream,
357403
newVersion,
358404
isLTS
359405
} = this;
360406

407+
let majorVersion;
408+
let stagingBranch;
409+
if (Object.keys(versionComponents).length !== 0) {
410+
majorVersion = versionComponents.major;
411+
stagingBranch = this.stagingBranch;
412+
} else {
413+
stagingBranch = this.getCurrentBranch();
414+
const stagingBranchSemver = semver.coerce(stagingBranch);
415+
majorVersion = stagingBranchSemver.major;
416+
}
417+
361418
let branchDiffOptions;
362419
if (opts.onlyNotableChanges) {
363420
const proposalBranch = `v${newVersion}-proposal`;
364-
const releaseBranch = `v${versionComponents.major}.x`;
421+
const releaseBranch = `v${majorVersion}.x`;
365422

366423
const notableLabels = [
367424
'notable-change',
@@ -377,21 +434,26 @@ class ReleasePreparation {
377434
} else {
378435
const excludeLabels = [
379436
'semver-major',
380-
`dont-land-on-v${versionComponents.major}.x`,
381-
`backport-requested-v${versionComponents.major}.x`,
382-
`backported-to-v${versionComponents.major}.x`,
383-
`backport-blocked-v${versionComponents.major}.x`
437+
`dont-land-on-v${majorVersion}.x`,
438+
`backport-requested-v${majorVersion}.x`,
439+
`backported-to-v${majorVersion}.x`,
440+
`backport-blocked-v${majorVersion}.x`
384441
];
385442

386443
const isSemverMinor = versionComponents.patch === 0;
387444
if (isLTS && !isSemverMinor) {
388445
excludeLabels.push('semver-minor');
389446
}
390447

448+
let comparisonBranch = 'master';
449+
if (opts.comparisonBranch) {
450+
comparisonBranch = opts.comparisonBranch;
451+
}
452+
391453
branchDiffOptions = [
392454
stagingBranch,
393455
// TODO(codebytere): use Current branch instead of master for LTS
394-
'master',
456+
comparisonBranch,
395457
`--exclude-label=${excludeLabels.join(',')}`,
396458
'--filter-release',
397459
'--format=simple'

0 commit comments

Comments
 (0)