Skip to content

Commit f045e77

Browse files
committed
feat: support security prepare
1 parent 267dde0 commit f045e77

File tree

1 file changed

+100
-12
lines changed

1 file changed

+100
-12
lines changed

lib/prepare_release.js

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export default class ReleasePreparation {
5757
};
5858

5959
this.stagingBranch = `v${this.versionComponents.major}.x-staging`;
60+
this.releaseBranch = `v${this.versionComponents.major}.x`;
6061

6162
const upstreamHref = runSync('git', [
6263
'config', '--get',
@@ -67,9 +68,89 @@ export default class ReleasePreparation {
6768
}
6869
}
6970

71+
async prepareSecurity() {
72+
const { cli, newVersion, versionComponents, releaseBranch } = this;
73+
74+
// Create new proposal branch.
75+
cli.startSpinner(`Creating new proposal branch for ${newVersion}`);
76+
await this.createProposalBranch(releaseBranch);
77+
cli.stopSpinner(`Created new proposal branch for ${newVersion}`);
78+
79+
let cherryPicked = await cli.prompt('Were all patches cherry picked?');
80+
while (!cherryPicked) {
81+
cli.warn(
82+
'Cherry-pick all the patches in another terminal before proceeding'
83+
);
84+
cherryPicked = await cli.prompt('Were all patches cherry picked?');
85+
}
86+
87+
// Update version and release info in src/node_version.h.
88+
cli.startSpinner(`Updating 'src/node_version.h' for ${newVersion}`);
89+
await this.updateNodeVersion();
90+
cli.stopSpinner(`Updated 'src/node_version.h' for ${newVersion}`);
91+
92+
// Update any REPLACEME tags in the docs.
93+
cli.startSpinner('Updating REPLACEME items in docs');
94+
await this.updateREPLACEMEs();
95+
cli.stopSpinner('Updated REPLACEME items in docs');
96+
97+
// Fetch date to use in release commit & changelogs.
98+
const todayDate = new Date().toISOString().split('T')[0];
99+
this.date = await cli.prompt('Enter release date in YYYY-MM-DD format:',
100+
{ questionType: 'input', defaultAnswer: todayDate });
101+
102+
cli.startSpinner('Updating CHANGELOG.md');
103+
await this.updateMainChangelog();
104+
cli.stopSpinner('Updated CHANGELOG.md');
105+
106+
cli.startSpinner(`Updating CHANGELOG_V${versionComponents.major}.md`);
107+
await this.updateMajorChangelog();
108+
cli.stopSpinner(`Updated CHANGELOG_V${versionComponents.major}.md`);
109+
110+
await cli.prompt('Finished editing the changelogs?',
111+
{ defaultAnswer: false });
112+
113+
// Create release commit.
114+
const shouldCreateReleaseCommit = await cli.prompt(
115+
'Create release commit?');
116+
if (!shouldCreateReleaseCommit) {
117+
cli.warn(`Aborting \`git node release\` for version ${newVersion}`);
118+
return;
119+
}
120+
121+
// Proceed with release only after the releaser has amended
122+
// it to their liking.
123+
const createDefaultCommit = await this.createReleaseCommit();
124+
if (!createDefaultCommit) {
125+
const lastCommitSha = runSync('git', ['rev-parse', '--short', 'HEAD']);
126+
cli.warn(`Please manually edit commit ${lastCommitSha} by running ` +
127+
'`git commit --amend` before proceeding.');
128+
129+
await cli.prompt(
130+
'Finished editing the release commit?',
131+
{ defaultAnswer: false });
132+
}
133+
134+
cli.separator();
135+
cli.ok(`Release preparation for ${newVersion} complete.\n`);
136+
cli.info(
137+
'To finish the release proposal, run: \n' +
138+
` $ git push -u ${this.upstream} v${newVersion}-proposal\n` +
139+
'Finally, proceed to Jenkins and begin the following CI jobs:\n' +
140+
' * https://ci.nodejs.org/job/node-test-pull-request/\n' +
141+
' * https://ci.nodejs.org/job/citgm-smoker/');
142+
cli.info(
143+
'If this release has deps/v8 changes, you\'ll also need to run:\n' +
144+
' * https://ci.nodejs.org/job/node-test-commit-v8-linux/'
145+
);
146+
}
147+
70148
async prepare() {
71-
const { cli, newVersion, versionComponents } = this;
149+
const { cli, newVersion, versionComponents, isSecurityRelease } = this;
72150

151+
if (isSecurityRelease) {
152+
return this.prepareSecurity();
153+
}
73154
// Check the branch diff to determine if the releaser
74155
// wants to backport any more commits before proceeding.
75156
cli.startSpinner('Fetching branch-diff');
@@ -431,15 +512,15 @@ export default class ReleasePreparation {
431512
await fs.writeFile(majorChangelogPath, arr.join('\n'));
432513
}
433514

434-
async createProposalBranch() {
435-
const { upstream, newVersion, stagingBranch } = this;
515+
async createProposalBranch(base = this.stagingBranch) {
516+
const { upstream, newVersion } = this;
436517
const proposalBranch = `v${newVersion}-proposal`;
437518

438519
await runAsync('git', [
439520
'checkout',
440521
'-b',
441522
proposalBranch,
442-
`${upstream}/${stagingBranch}`
523+
`${upstream}/${base}`
443524
]);
444525
}
445526

@@ -618,28 +699,35 @@ export default class ReleasePreparation {
618699
}
619700

620701
warnForWrongBranch() {
621-
const { cli, stagingBranch, versionComponents } = this;
702+
const {
703+
cli,
704+
stagingBranch,
705+
releaseBranch,
706+
versionComponents,
707+
isSecurityRelease
708+
} = this;
622709
const rev = this.getCurrentBranch();
623710

624-
if (rev === stagingBranch) {
625-
return false;
626-
}
627-
628711
if (rev === 'HEAD') {
629712
cli.warn(
630713
'You are in detached HEAD state. Please run git-node on a valid ' +
631714
'branch');
632715
return true;
633716
}
717+
const targetBranch = isSecurityRelease ? releaseBranch : stagingBranch;
718+
719+
if (rev === targetBranch) {
720+
return false;
721+
}
634722

635723
cli.warn(
636724
'You are trying to create a new release proposal branch for ' +
637725
`v${versionComponents.major}, but you're checked out on ` +
638-
`${rev} and not ${stagingBranch}.`);
726+
`${rev} and not ${targetBranch}.`);
639727
cli.separator();
640728
cli.info(
641-
`Switch to \`${stagingBranch}\` with \`git` +
642-
` checkout ${stagingBranch}\` before proceeding.`);
729+
`Switch to \`${targetBranch}\` with \`git` +
730+
` checkout ${targetBranch}\` before proceeding.`);
643731
cli.separator();
644732
return true;
645733
}

0 commit comments

Comments
 (0)