Skip to content

Commit

Permalink
feat(git-node): add release promotion step (#835)
Browse files Browse the repository at this point in the history
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
  • Loading branch information
aduh95 and codebytere authored Nov 13, 2024
1 parent 819e669 commit dfa9c92
Show file tree
Hide file tree
Showing 4 changed files with 565 additions and 15 deletions.
80 changes: 65 additions & 15 deletions components/git/release.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
import auth from '../../lib/auth.js';
import CLI from '../../lib/cli.js';
import ReleasePreparation from '../../lib/prepare_release.js';
import ReleasePromotion from '../../lib/promote_release.js';
import TeamInfo from '../../lib/team_info.js';
import Request from '../../lib/request.js';
import { runPromise } from '../../lib/run.js';

export const command = 'release [newVersion|options]';
export const command = 'release [prid|options]';
export const describe = 'Manage an in-progress release or start a new one.';

const PREPARE = 'prepare';
const PROMOTE = 'promote';
const RELEASERS = 'releasers';

const releaseOptions = {
filterLabel: {
describe: 'Labels separated by "," to filter security PRs',
type: 'string'
},
'gpg-sign': {
describe: 'GPG-sign commits, will be passed to the git process',
alias: 'S'
},
newVersion: {
describe: 'Version number of the release to be prepared',
type: 'string'
},
prepare: {
describe: 'Prepare a new release of Node.js',
type: 'boolean'
Expand All @@ -21,14 +38,16 @@ const releaseOptions = {
describe: 'Default relase date when --prepare is used. It must be YYYY-MM-DD',
type: 'string'
},
run: {
describe: 'Run steps that involve touching more than the local clone, ' +
'including `git push` commands. Might not work if a passphrase ' +
'required to push to the remote clone.',
type: 'boolean'
},
security: {
describe: 'Demarcate the new security release as a security release',
type: 'boolean'
},
filterLabel: {
describe: 'Labels separated by "," to filter security PRs',
type: 'string'
},
skipBranchDiff: {
describe: 'Skips the initial branch-diff check when preparing releases',
type: 'boolean'
Expand All @@ -49,11 +68,16 @@ let yargsInstance;
export function builder(yargs) {
yargsInstance = yargs;
return yargs
.options(releaseOptions).positional('newVersion', {
describe: 'Version number of the release to be prepared or promoted'
.options(releaseOptions).positional('prid', {
describe: 'PR number or URL of the release proposal to be promoted',
type: 'string'
})
.example('git node release --prepare 1.2.3',
'Prepare a release of Node.js tagged v1.2.3')
.example('git node release --prepare --security',
'Prepare a new security release of Node.js with auto-determined version')
.example('git node release --prepare --newVersion=1.2.3',
'Prepare a new release of Node.js tagged v1.2.3')
.example('git node release --promote 12345',
'Promote a prepared release of Node.js with PR #12345')
.example('git node --prepare --startLTS',
'Prepare the first LTS release');
}
Expand Down Expand Up @@ -88,17 +112,21 @@ function release(state, argv) {
}

async function main(state, argv, cli, dir) {
const prID = /^(?:https:\/\/github\.com\/nodejs\/node\/pull\/)?(\d+)$/.exec(argv.prid);
if (prID) {
argv.prid = Number(prID[1]);
}
if (state === PREPARE) {
const prep = new ReleasePreparation(argv, cli, dir);
const release = new ReleasePreparation(argv, cli, dir);

await prep.prepareLocalBranch();
await release.prepareLocalBranch();

if (prep.warnForWrongBranch()) return;
if (release.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}?`,
`Create release with new version ${release.newVersion}?`,
{ defaultAnswer: true });

if (!create) {
Expand All @@ -107,8 +135,30 @@ async function main(state, argv, cli, dir) {
}
}

return prep.prepare();
return release.prepare();
} else if (state === PROMOTE) {
// TODO(codebytere): implement release promotion.
const credentials = await auth({ github: true });
const request = new Request(credentials);
const release = new ReleasePromotion(argv, request, cli, dir);

cli.startSpinner('Verifying Releaser status');
const info = new TeamInfo(cli, request, 'nodejs', RELEASERS);

const releasers = await info.getMembers();
if (release.username === undefined) {
cli.stopSpinner('Failed to verify Releaser status');
cli.info(
'Username was undefined - do you have your .ncurc set up correctly?');
return;
} else if (releasers.every(r => r.login !== release.username)) {
cli.stopSpinner(`${release.username} is not a Releaser`, 'failed');
if (!argv.dryRun) {
throw new Error('aborted');
}
} else {
cli.stopSpinner(`${release.username} is a Releaser`);
}

return release.promote();
}
}
Loading

0 comments on commit dfa9c92

Please sign in to comment.