1
+ import auth from '../../lib/auth.js' ;
1
2
import CLI from '../../lib/cli.js' ;
2
3
import ReleasePreparation from '../../lib/prepare_release.js' ;
4
+ import ReleasePromotion from '../../lib/promote_release.js' ;
5
+ import TeamInfo from '../../lib/team_info.js' ;
6
+ import Request from '../../lib/request.js' ;
3
7
import { runPromise } from '../../lib/run.js' ;
4
8
5
- export const command = 'release [newVersion |options]' ;
9
+ export const command = 'release [prid |options]' ;
6
10
export const describe = 'Manage an in-progress release or start a new one.' ;
7
11
8
12
const PREPARE = 'prepare' ;
9
13
const PROMOTE = 'promote' ;
14
+ const RELEASERS = 'releasers' ;
10
15
11
16
const releaseOptions = {
17
+ filterLabel : {
18
+ describe : 'Labels separated by "," to filter security PRs' ,
19
+ type : 'string'
20
+ } ,
21
+ 'gpg-sign' : {
22
+ describe : 'GPG-sign commits, will be passed to the git process' ,
23
+ alias : 'S'
24
+ } ,
25
+ newVersion : {
26
+ describe : 'Version number of the release to be prepared' ,
27
+ type : 'string'
28
+ } ,
12
29
prepare : {
13
30
describe : 'Prepare a new release of Node.js' ,
14
31
type : 'boolean'
@@ -21,14 +38,16 @@ const releaseOptions = {
21
38
describe : 'Default relase date when --prepare is used. It must be YYYY-MM-DD' ,
22
39
type : 'string'
23
40
} ,
41
+ run : {
42
+ describe : 'Run steps that involve touching more than the local clone, ' +
43
+ 'including `git push` commands. Might not work if a passphrase ' +
44
+ 'required to push to the remote clone.' ,
45
+ type : 'boolean'
46
+ } ,
24
47
security : {
25
48
describe : 'Demarcate the new security release as a security release' ,
26
49
type : 'boolean'
27
50
} ,
28
- filterLabel : {
29
- describe : 'Labels separated by "," to filter security PRs' ,
30
- type : 'string'
31
- } ,
32
51
skipBranchDiff : {
33
52
describe : 'Skips the initial branch-diff check when preparing releases' ,
34
53
type : 'boolean'
@@ -49,11 +68,16 @@ let yargsInstance;
49
68
export function builder ( yargs ) {
50
69
yargsInstance = yargs ;
51
70
return yargs
52
- . options ( releaseOptions ) . positional ( 'newVersion' , {
53
- describe : 'Version number of the release to be prepared or promoted'
71
+ . options ( releaseOptions ) . positional ( 'prid' , {
72
+ describe : 'PR number or URL of the release proposal to be promoted' ,
73
+ type : 'string'
54
74
} )
55
- . example ( 'git node release --prepare 1.2.3' ,
56
- 'Prepare a release of Node.js tagged v1.2.3' )
75
+ . example ( 'git node release --prepare --security' ,
76
+ 'Prepare a new security release of Node.js with auto-determined version' )
77
+ . example ( 'git node release --prepare --newVersion=1.2.3' ,
78
+ 'Prepare a new release of Node.js tagged v1.2.3' )
79
+ . example ( 'git node release --promote 12345' ,
80
+ 'Promote a prepared release of Node.js with PR #12345' )
57
81
. example ( 'git node --prepare --startLTS' ,
58
82
'Prepare the first LTS release' ) ;
59
83
}
@@ -88,17 +112,21 @@ function release(state, argv) {
88
112
}
89
113
90
114
async function main ( state , argv , cli , dir ) {
115
+ const prID = / ^ (?: h t t p s : \/ \/ g i t h u b \. c o m \/ n o d e j s \/ n o d e \/ p u l l \/ ) ? ( \d + ) $ / . exec ( argv . prid ) ;
116
+ if ( prID ) {
117
+ argv . prid = Number ( prID [ 1 ] ) ;
118
+ }
91
119
if ( state === PREPARE ) {
92
- const prep = new ReleasePreparation ( argv , cli , dir ) ;
120
+ const release = new ReleasePreparation ( argv , cli , dir ) ;
93
121
94
- await prep . prepareLocalBranch ( ) ;
122
+ await release . prepareLocalBranch ( ) ;
95
123
96
- if ( prep . warnForWrongBranch ( ) ) return ;
124
+ if ( release . warnForWrongBranch ( ) ) return ;
97
125
98
126
// If the new version was automatically calculated, confirm it.
99
127
if ( ! argv . newVersion ) {
100
128
const create = await cli . prompt (
101
- `Create release with new version ${ prep . newVersion } ?` ,
129
+ `Create release with new version ${ release . newVersion } ?` ,
102
130
{ defaultAnswer : true } ) ;
103
131
104
132
if ( ! create ) {
@@ -107,8 +135,30 @@ async function main(state, argv, cli, dir) {
107
135
}
108
136
}
109
137
110
- return prep . prepare ( ) ;
138
+ return release . prepare ( ) ;
111
139
} else if ( state === PROMOTE ) {
112
- // TODO(codebytere): implement release promotion.
140
+ const credentials = await auth ( { github : true } ) ;
141
+ const request = new Request ( credentials ) ;
142
+ const release = new ReleasePromotion ( argv , request , cli , dir ) ;
143
+
144
+ cli . startSpinner ( 'Verifying Releaser status' ) ;
145
+ const info = new TeamInfo ( cli , request , 'nodejs' , RELEASERS ) ;
146
+
147
+ const releasers = await info . getMembers ( ) ;
148
+ if ( release . username === undefined ) {
149
+ cli . stopSpinner ( 'Failed to verify Releaser status' ) ;
150
+ cli . info (
151
+ 'Username was undefined - do you have your .ncurc set up correctly?' ) ;
152
+ return ;
153
+ } else if ( releasers . every ( r => r . login !== release . username ) ) {
154
+ cli . stopSpinner ( `${ release . username } is not a Releaser` , 'failed' ) ;
155
+ if ( ! argv . dryRun ) {
156
+ throw new Error ( 'aborted' ) ;
157
+ }
158
+ } else {
159
+ cli . stopSpinner ( `${ release . username } is a Releaser` ) ;
160
+ }
161
+
162
+ return release . promote ( ) ;
113
163
}
114
164
}
0 commit comments