Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Automatically calculate version based on commits
  • Loading branch information
codebytere committed Mar 11, 2020
commit 7e8f11a71ba63e0c34f584ced2ce21bd5899828a
50 changes: 30 additions & 20 deletions components/git/release.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,10 @@ function builder(yargs) {
}

function handler(argv) {
if (argv.newVersion) {
const newVersion = semver.clean(argv.newVersion);
if (semver.valid(newVersion)) {
if (argv.prepare) {
return release(PREPARE, argv);
} else if (argv.promote) {
return release(PROMOTE, argv);
}
}
if (argv.prepare) {
return release(PREPARE, argv);
} else if (argv.promote) {
return release(PROMOTE, argv);
}

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

if (prep.warnForWrongBranch()) return;

// If the new version was automatically calculated, confirm it.
if (!argv.newVersion) {
const create = await cli.prompt(
`Create release with new version ${prep.newVersion}?`,
{ defaultAnswer: true });

if (!create) {
cli.error('Aborting release preparation process');
return;
}
}

// Check the branch diff to determine if the releaser
// wants to backport any more commits before proceeding.
cli.startSpinner('Fetching branch-diff');
const raw = prep.getBranchDiff({ onlyNotableChanges: false });
const diff = raw.split('*');
cli.stopSpinner('Got branch diff');

const staging = `v${semver.major(argv.newVersion)}.x-staging`;
const proceed = await cli.prompt(
`There are ${diff.length - 1} commits that may be ` +
`backported to ${staging} - do you still want to proceed?`,
{ defaultAnswer: false });

if (!proceed) {
const seeDiff = await cli.prompt(
'Do you want to see the branch diff?');
if (seeDiff) cli.log(raw);
return;
const outstandingCommits = diff.length - 1;
if (outstandingCommits !== 0) {
const staging = `v${semver.major(prep.newVersion)}.x-staging`;
const proceed = await cli.prompt(
`There are ${outstandingCommits} commits that may be ` +
`backported to ${staging} - do you still want to proceed?`,
{ defaultAnswer: false });

if (!proceed) {
const seeDiff = await cli.prompt(
'Do you want to see the branch diff?');
if (seeDiff) cli.log(raw);
return;
}
}

return prep.prepare();
Expand Down
106 changes: 84 additions & 22 deletions lib/prepare_release.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,24 @@ class ReleasePreparation {
constructor(argv, cli, dir) {
this.cli = cli;
this.dir = dir;
this.newVersion = semver.clean(argv.newVersion);
this.isSecurityRelease = argv.security;
this.isLTS = false;
this.ltsCodename = '';
this.date = '';
this.config = getMergedConfig(this.dir);

// Allow passing optional new version.
if (argv.newVersion) {
const newVersion = semver.clean(argv.newVersion);
if (!semver.valid(newVersion)) {
cli.warn(`${newVersion} is not a valid semantic version.`);
return;
}
this.newVersion = newVersion;
} else {
this.newVersion = this.calculateNewVersion();
}

const { upstream, owner, repo, newVersion } = this;

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

// Check whether to update NODE_MODULE_VERSION (default false).
const shouldUpdateNodeModuleVersion = await cli.prompt(
'Update NODE_MODULE_VERSION?', { defaultAnswer: false });
if (shouldUpdateNodeModuleVersion) {
const variant = await cli.prompt(
'Specify variant (ex. \'v8_7.9\') for new NODE_MODULE_VERSION:',
{ questionType: 'input', noSeparator: true });
const versions = await cli.prompt(
'Specify versions (ex. \'14.0.0-pre\') for new NODE_MODULE_VERSION:',
{ questionType: 'input', noSeparator: true });
this.updateNodeModuleVersion('node', variant, versions);
// Check whether to update NODE_MODULE_VERSION.
const isSemverMajor = versionComponents.minor === 0;
if (isSemverMajor) {
const shouldUpdateNodeModuleVersion = await cli.prompt(
'Update NODE_MODULE_VERSION?', { defaultAnswer: false });
if (shouldUpdateNodeModuleVersion) {
const variant = await cli.prompt(
'Specify variant (ex. \'v8_7.9\') for new NODE_MODULE_VERSION:',
{ questionType: 'input', noSeparator: true });
const versions = await cli.prompt(
'Specify versions (ex. \'14.0.0-pre\') for new NODE_MODULE_VERSION:',
{ questionType: 'input', noSeparator: true });
this.updateNodeModuleVersion('node', variant, versions);
}
}

// Update any REPLACEME tags in the docs.
Expand Down Expand Up @@ -154,6 +168,32 @@ class ReleasePreparation {
return this.config.username;
}

calculateNewVersion() {
let newVersion;

const lastTagVersion = semver.clean(this.getLastRef());
const lastTag = {
major: semver.major(lastTagVersion),
minor: semver.minor(lastTagVersion),
patch: semver.patch(lastTagVersion)
};

const raw = this.getBranchDiff({
onlyNotableChanges: false,
comparisonBranch: `v${lastTagVersion}`
});

if (raw.includes('SEMVER-MAJOR')) {
newVersion = `${lastTag.major + 1}.0.0`;
} else if (raw.includes('SEMVER-MINOR')) {
newVersion = `${lastTag.major}.${lastTag.minor + 1}.0`;
} else {
newVersion = `${lastTag.major}.${lastTag.minor}.${lastTag.patch + 1}`;
}

return newVersion;
}

getCurrentBranch() {
return runSync('git', ['rev-parse', '--abbrev-ref', 'HEAD']).trim();
}
Expand Down Expand Up @@ -253,14 +293,21 @@ class ReleasePreparation {
` ${releaseInfo}, @${username}\n`;

for (let idx = 0; idx < arr.length; idx++) {
if (arr[idx].includes(`<a id="${lastRef.substring(1)}"></a>`)) {
const topHeader =
`<a href="#${lastRef.substring(1)}">${lastRef.substring(1)}</a><br/>`;
if (arr[idx].includes(topHeader)) {
const newHeader =
`<a href="#${newVersion}">${newVersion}</a><br/>`;
arr.splice(idx, 1, newHeader);
} else if (arr[idx].includes(`<a id="${lastRef.substring(1)}"></a>`)) {
const toAppend = [];
toAppend.push(`<a id="${newVersion}"></a>`);
toAppend.push(releaseHeader);
toAppend.push('### Notable Changes\n');
toAppend.push(notableChanges);
toAppend.push('### Commits\n');
toAppend.push(allCommits);
toAppend.push('');

arr.splice(idx, 0, ...toAppend);
break;
Expand Down Expand Up @@ -345,23 +392,33 @@ class ReleasePreparation {

cli.log(`${messageTitle}\n\n${messageBody.join('')}`);
const useMessage = await cli.prompt(
'Continue with this commit message?');
'Continue with this commit message?', { defaultAnswer: false });
return useMessage;
}

getBranchDiff(opts) {
const {
versionComponents,
stagingBranch,
versionComponents = {},
upstream,
newVersion,
isLTS
} = this;

let majorVersion;
let stagingBranch;
if (Object.keys(versionComponents).length !== 0) {
majorVersion = versionComponents.major;
stagingBranch = this.stagingBranch;
} else {
stagingBranch = this.getCurrentBranch();
const stagingBranchSemver = semver.coerce(stagingBranch);
majorVersion = stagingBranchSemver.major;
}

let branchDiffOptions;
if (opts.onlyNotableChanges) {
const proposalBranch = `v${newVersion}-proposal`;
const releaseBranch = `v${versionComponents.major}.x`;
const releaseBranch = `v${majorVersion}.x`;

const notableLabels = [
'notable-change',
Expand All @@ -377,21 +434,26 @@ class ReleasePreparation {
} else {
const excludeLabels = [
'semver-major',
`dont-land-on-v${versionComponents.major}.x`,
`backport-requested-v${versionComponents.major}.x`,
`backported-to-v${versionComponents.major}.x`,
`backport-blocked-v${versionComponents.major}.x`
`dont-land-on-v${majorVersion}.x`,
`backport-requested-v${majorVersion}.x`,
`backported-to-v${majorVersion}.x`,
`backport-blocked-v${majorVersion}.x`
];

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

let comparisonBranch = 'master';
if (opts.comparisonBranch) {
comparisonBranch = opts.comparisonBranch;
}

branchDiffOptions = [
stagingBranch,
// TODO(codebytere): use Current branch instead of master for LTS
'master',
comparisonBranch,
`--exclude-label=${excludeLabels.join(',')}`,
'--filter-release',
'--format=simple'
Expand Down