Skip to content

Commit 06dfd34

Browse files
committed
git-node: add promotion step
1 parent 9d9fb2f commit 06dfd34

File tree

3 files changed

+111
-6
lines changed

3 files changed

+111
-6
lines changed

components/git/release.js

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22

33
const yargs = require('yargs');
44

5+
const auth = require('../../lib/auth');
56
const CLI = require('../../lib/cli');
67
const ReleasePreparation = require('../../lib/prepare_release');
8+
const ReleasePromotion = require('../../lib/promote_release');
9+
const TeamInfo = require('../../lib/team_info');
10+
const Request = require('../../lib/request');
711
const { runPromise } = require('../../lib/run');
812

913
const PREPARE = 'prepare';
1014
const PROMOTE = 'promote';
15+
const RELEASERS = 'releasers';
1116

1217
const releaseOptions = {
1318
prepare: {
@@ -30,7 +35,9 @@ function builder(yargs) {
3035
describe: 'Version number of the release to be prepared or promoted'
3136
})
3237
.example('git node release --prepare 1.2.3',
33-
'Prepare a new release of Node.js tagged v1.2.3');
38+
'Prepare a new release of Node.js tagged v1.2.3')
39+
.example('git node release --promote 1.2.3',
40+
'Promote a prepared release of Node.js tagged v1.2.3');
3441
}
3542

3643
function handler(argv) {
@@ -67,15 +74,17 @@ module.exports = {
6774
};
6875

6976
async function main(state, argv, cli, dir) {
77+
let release;
78+
7079
if (state === PREPARE) {
71-
const prep = new ReleasePreparation(argv, cli, dir);
80+
release = new ReleasePreparation(argv, cli, dir);
7281

73-
if (prep.warnForWrongBranch()) return;
82+
if (release.warnForWrongBranch()) return;
7483

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

8190
if (!create) {
@@ -84,8 +93,23 @@ async function main(state, argv, cli, dir) {
8493
}
8594
}
8695

87-
return prep.prepare();
96+
return release.prepare();
8897
} else if (state === PROMOTE) {
89-
// TODO(codebytere): implement release promotion.
98+
release = new ReleasePromotion(argv, cli, dir);
99+
100+
cli.startSpinner('Verifying Releaser status');
101+
const credentials = await auth({ github: true });
102+
const request = new Request(credentials);
103+
const info = new TeamInfo(cli, request, 'nodejs', RELEASERS);
104+
105+
const releasers = await info.getMembers();
106+
if (!releasers.some(r => r.login === release.username)) {
107+
cli.stopSpinner(
108+
`${release.username} is not a Releaser; aborting release`);
109+
return;
110+
}
111+
cli.stopSpinner('Verified Releaser status');
112+
113+
return release.promote();
90114
}
91115
}

lib/promote_release.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
'use strict';
2+
3+
const path = require('path');
4+
const { promises: fs } = require('fs');
5+
const semver = require('semver');
6+
7+
const { getMergedConfig } = require('./config');
8+
const { runAsync, runSync } = require('./run');
9+
const { writeJson, readJson } = require('./file');
10+
11+
const isWindows = process.platform === 'win32';
12+
13+
class ReleasePreparation {
14+
constructor(argv, cli, dir) {
15+
this.cli = cli;
16+
this.dir = dir;
17+
this.isSecurityRelease = argv.security;
18+
this.isLTS = await this.checkIsLTS;
19+
this.ltsCodename = '';
20+
this.date = '';
21+
this.config = getMergedConfig(this.dir);
22+
}
23+
24+
async promote() {
25+
// Verify that CI is green
26+
27+
// Verify that the PR has at least one approval from a Releaser
28+
29+
//
30+
}
31+
32+
async checkIsLTS() {
33+
const filePath = path.resolve('src', 'node_version.h');
34+
const data = await fs.readFile(filePath, 'utf8');
35+
const arr = data.split('\n');
36+
37+
for (let idx = 0; idx < arr.length; idx++) {
38+
const line = arr[idx];
39+
if (line.includes('#define NODE_VERSION_IS_LTS')) {
40+
return line.split(' ')[2] === '1';
41+
}
42+
}
43+
}
44+
45+
// Returns the LTS codename for the Release line; e.g 'Erbium' for 12.x.
46+
async checkReleaseCodename() {
47+
const filePath = path.resolve('src', 'node_version.h');
48+
const data = await fs.readFile(filePath, 'utf8');
49+
const arr = data.split('\n');
50+
51+
for (let idx = 0; idx < arr.length; idx++) {
52+
const line = arr[idx];
53+
if (line.includes('#define NODE_VERSION_LTS_CODENAME')) {
54+
return line.split(' ')[2];
55+
}
56+
}
57+
58+
59+
}
60+
61+
// Set up the branch so that nightly builds are produced with the next
62+
// version number and a pre-release tag.
63+
async setupForNextRelease() {
64+
const { versionComponents } = this;
65+
66+
const filePath = path.resolve('src', 'node_version.h');
67+
const data = await fs.readFile(filePath, 'utf8');
68+
const arr = data.split('\n');
69+
70+
arr.forEach((line, idx) => {
71+
if (line.includes('#define NODE_PATCH_VERSION')) {
72+
arr[idx] = `#define NODE_PATCH_VERSION ${versionComponents.patch + 1}`;
73+
} else if (line.includes('#define NODE_VERSION_IS_RELEASE')) {
74+
arr[idx] = '#define NODE_VERSION_IS_RELEASE 0';
75+
}
76+
});
77+
78+
await fs.writeFile(filePath, arr.join('\n'));
79+
}
80+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"figures": "^3.1.0",
4242
"fs-extra": "^8.1.0",
4343
"ghauth": "^4.0.0",
44+
"git-secure-tag": "^2.3.1",
4445
"inquirer": "^7.0.0",
4546
"listr": "^0.14.3",
4647
"listr-input": "^0.2.0",

0 commit comments

Comments
 (0)