@node-core/utils 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +158 -0
  3. package/bin/get-metadata.js +11 -0
  4. package/bin/git-node.js +30 -0
  5. package/bin/ncu-ci.js +600 -0
  6. package/bin/ncu-config.js +101 -0
  7. package/bin/ncu-team.js +76 -0
  8. package/components/git/backport.js +70 -0
  9. package/components/git/epilogue.js +18 -0
  10. package/components/git/land.js +223 -0
  11. package/components/git/metadata.js +94 -0
  12. package/components/git/release.js +99 -0
  13. package/components/git/security.js +35 -0
  14. package/components/git/status.js +32 -0
  15. package/components/git/sync.js +24 -0
  16. package/components/git/v8.js +121 -0
  17. package/components/git/vote.js +84 -0
  18. package/components/git/wpt.js +87 -0
  19. package/components/metadata.js +49 -0
  20. package/lib/auth.js +133 -0
  21. package/lib/backport_session.js +302 -0
  22. package/lib/cache.js +107 -0
  23. package/lib/cherry_pick.js +304 -0
  24. package/lib/ci/build-types/benchmark_run.js +72 -0
  25. package/lib/ci/build-types/citgm_build.js +194 -0
  26. package/lib/ci/build-types/citgm_comparison_build.js +174 -0
  27. package/lib/ci/build-types/commit_build.js +112 -0
  28. package/lib/ci/build-types/daily_build.js +24 -0
  29. package/lib/ci/build-types/fanned_build.js +87 -0
  30. package/lib/ci/build-types/health_build.js +63 -0
  31. package/lib/ci/build-types/job.js +114 -0
  32. package/lib/ci/build-types/linter_build.js +35 -0
  33. package/lib/ci/build-types/normal_build.js +89 -0
  34. package/lib/ci/build-types/pr_build.js +101 -0
  35. package/lib/ci/build-types/test_build.js +186 -0
  36. package/lib/ci/build-types/test_run.js +41 -0
  37. package/lib/ci/ci_failure_parser.js +325 -0
  38. package/lib/ci/ci_type_parser.js +203 -0
  39. package/lib/ci/ci_utils.js +106 -0
  40. package/lib/ci/failure_aggregator.js +152 -0
  41. package/lib/ci/jenkins_constants.js +28 -0
  42. package/lib/ci/run_ci.js +120 -0
  43. package/lib/cli.js +192 -0
  44. package/lib/collaborators.js +140 -0
  45. package/lib/config.js +72 -0
  46. package/lib/figures.js +7 -0
  47. package/lib/file.js +43 -0
  48. package/lib/github/templates/next-security-release.md +97 -0
  49. package/lib/github/tree.js +162 -0
  50. package/lib/landing_session.js +506 -0
  51. package/lib/links.js +123 -0
  52. package/lib/mergeable_state.js +3 -0
  53. package/lib/metadata_gen.js +61 -0
  54. package/lib/pr_checker.js +605 -0
  55. package/lib/pr_data.js +115 -0
  56. package/lib/pr_summary.js +62 -0
  57. package/lib/prepare_release.js +772 -0
  58. package/lib/prepare_security.js +117 -0
  59. package/lib/proxy.js +21 -0
  60. package/lib/queries/DefaultBranchRef.gql +8 -0
  61. package/lib/queries/LastCommit.gql +16 -0
  62. package/lib/queries/PR.gql +37 -0
  63. package/lib/queries/PRComments.gql +27 -0
  64. package/lib/queries/PRCommits.gql +45 -0
  65. package/lib/queries/PRs.gql +25 -0
  66. package/lib/queries/Reviews.gql +23 -0
  67. package/lib/queries/SearchIssue.gql +51 -0
  68. package/lib/queries/Team.gql +22 -0
  69. package/lib/queries/TreeEntries.gql +12 -0
  70. package/lib/queries/VotePRInfo.gql +28 -0
  71. package/lib/release/utils.js +53 -0
  72. package/lib/request.js +185 -0
  73. package/lib/review_state.js +5 -0
  74. package/lib/reviews.js +178 -0
  75. package/lib/run.js +106 -0
  76. package/lib/session.js +415 -0
  77. package/lib/sync_session.js +15 -0
  78. package/lib/team_info.js +95 -0
  79. package/lib/update-v8/applyNodeChanges.js +49 -0
  80. package/lib/update-v8/backport.js +258 -0
  81. package/lib/update-v8/commitUpdate.js +26 -0
  82. package/lib/update-v8/common.js +35 -0
  83. package/lib/update-v8/constants.js +86 -0
  84. package/lib/update-v8/index.js +56 -0
  85. package/lib/update-v8/majorUpdate.js +171 -0
  86. package/lib/update-v8/minorUpdate.js +105 -0
  87. package/lib/update-v8/updateMaintainingDependencies.js +34 -0
  88. package/lib/update-v8/updateV8Clone.js +53 -0
  89. package/lib/update-v8/updateVersionNumbers.js +122 -0
  90. package/lib/update-v8/util.js +62 -0
  91. package/lib/user.js +4 -0
  92. package/lib/user_status.js +5 -0
  93. package/lib/utils.js +66 -0
  94. package/lib/verbosity.js +26 -0
  95. package/lib/voting_session.js +136 -0
  96. package/lib/wpt/index.js +243 -0
  97. package/lib/wpt/templates/README.md +16 -0
  98. package/package.json +69 -0
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+
3
+ import yargs from 'yargs';
4
+ import { hideBin } from 'yargs/helpers';
5
+
6
+ import Request from '../lib/request.js';
7
+ import auth from '../lib/auth.js';
8
+ import { runPromise } from '../lib/run.js';
9
+ import CLI from '../lib/cli.js';
10
+ import TeamInfo from '../lib/team_info.js';
11
+
12
+ import { setVerbosityFromEnv } from '../lib/verbosity.js';
13
+
14
+ setVerbosityFromEnv();
15
+
16
+ yargs(hideBin(process.argv))
17
+ .completion('completion')
18
+ .command({
19
+ command: 'list <team> [org]',
20
+ desc: 'Get the list of members in a team',
21
+ builder: (yargs) => {
22
+ yargs
23
+ .positional('team', {
24
+ describe: 'Name of the team',
25
+ type: 'string'
26
+ })
27
+ .positional('org', {
28
+ describe: 'Name of the organization',
29
+ type: 'string',
30
+ default: 'nodejs'
31
+ });
32
+ },
33
+ handler
34
+ })
35
+ .command({
36
+ command: 'sync <file>',
37
+ desc:
38
+ 'Synchronize the <!-- ncu-team-sync.team($org/$team) --> block in a file',
39
+ builder: (yargs) => {
40
+ yargs
41
+ .positional('file', {
42
+ describe: 'Path to the file to update',
43
+ type: 'string'
44
+ });
45
+ },
46
+ handler
47
+ })
48
+ .demandCommand(1, 'must provide a valid command')
49
+ .help()
50
+ .parse();
51
+
52
+ function handler(argv) {
53
+ runPromise(main(argv));
54
+ }
55
+
56
+ async function main(argv) {
57
+ const cli = new CLI();
58
+ const credentials = await auth({
59
+ github: true
60
+ });
61
+ const request = new Request(credentials);
62
+
63
+ const [command] = argv._;
64
+ switch (command) {
65
+ case 'list': {
66
+ const info = new TeamInfo(cli, request, argv.org, argv.team);
67
+ await info.listMembers();
68
+ break;
69
+ }
70
+ case 'sync':
71
+ await TeamInfo.syncFile(cli, request, argv.file);
72
+ break;
73
+ default:
74
+ throw new Error(`Unknown command ${command}`);
75
+ }
76
+ }
@@ -0,0 +1,70 @@
1
+ import { parsePRFromURL } from '../../lib/links.js';
2
+ import CLI from '../../lib/cli.js';
3
+ import { runPromise } from '../../lib/run.js';
4
+ import BackportSession from '../../lib/backport_session.js';
5
+
6
+ export const command = 'backport <identifier>';
7
+ export const describe = 'Backport a PR to a release staging branch.';
8
+
9
+ const epilogue = `====================== Example =======================
10
+ Demo: https://asciinema.org/a/221244
11
+ Backporting https://github.com/nodejs/node/pull/24816 to v11.x
12
+
13
+ # Sync main with upstream for the commits, if they are not yet there
14
+ $ git checkout main
15
+ $ ncu-config set branch main
16
+ $ git node sync
17
+
18
+ # Backport existing commits from main to v11.x-staging
19
+ $ git checkout v11.x-staging
20
+ $ ncu-config set branch v11.x-staging
21
+ $ git node sync
22
+ $ git node backport 24816 --to 11
23
+ =====================================================
24
+ `;
25
+
26
+ let yargsInstance;
27
+
28
+ export function builder(yargs) {
29
+ yargsInstance = yargs;
30
+ return yargs
31
+ .options({
32
+ to: {
33
+ describe: 'release to backport the commits to',
34
+ type: 'number',
35
+ required: true
36
+ }
37
+ })
38
+ .positional('identifier', {
39
+ type: 'string',
40
+ describe: 'ID or URL of the pull request'
41
+ })
42
+ .epilogue(epilogue)
43
+ .wrap(90);
44
+ }
45
+
46
+ async function main(argv, parsed) {
47
+ const merged = (await import('../../lib/config.js')).getMergedConfig();
48
+ const config = Object.assign({}, argv, parsed, merged);
49
+ const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
50
+ const cli = new CLI(logStream);
51
+ cli.setFigureIndent(0);
52
+ const dir = process.cwd();
53
+ const session = new BackportSession(cli, dir, config.prid, config.to);
54
+ return session.backport();
55
+ }
56
+
57
+ export function handler(argv) {
58
+ let parsed = {};
59
+ const prid = Number.parseInt(argv.identifier);
60
+ if (!Number.isNaN(prid)) {
61
+ parsed.prid = prid;
62
+ } else {
63
+ parsed = parsePRFromURL(argv.identifier);
64
+ if (!parsed) {
65
+ return yargsInstance.showHelp();
66
+ }
67
+ }
68
+
69
+ return runPromise(main(argv, parsed));
70
+ }
@@ -0,0 +1,18 @@
1
+ export default `Steps to land a pull request:
2
+ ==============================================================================
3
+ $ cd path/to/node/project
4
+
5
+ # If you have not configured it before
6
+ $ ncu-config set upstream <name-of-remote-to-nodejs/node>
7
+ $ ncu-config set branch main # Assuming you are landing commits on main
8
+
9
+ $ git checkout main
10
+ $ git node land --abort # Abort a landing session, just in case
11
+ $ git node land $PRID # Start a new landing session
12
+ $ git node land $URL # Start a new landing session using the PR URL
13
+
14
+ # Follow instructions provided.
15
+
16
+ $ git node land --final # Verify all the commit messages
17
+ ==============================================================================
18
+ Watch https://asciinema.org/a/148627 for a complete demo`;
@@ -0,0 +1,223 @@
1
+ import auth from '../../lib/auth.js';
2
+ import { parsePRFromURL } from '../../lib/links.js';
3
+ import { getMetadata } from '../metadata.js';
4
+ import CLI from '../../lib/cli.js';
5
+ import Request from '../../lib/request.js';
6
+ import { runPromise } from '../../lib/run.js';
7
+ import LandingSession from '../../lib/landing_session.js';
8
+ import epilogue from './epilogue.js';
9
+
10
+ export const command = 'land [prid|options]';
11
+ export const describe =
12
+ 'Manage the current landing session or start a new one for a pull request';
13
+
14
+ const landActions = {
15
+ apply: {
16
+ describe: 'Apply a patch with the given PR id',
17
+ type: 'number'
18
+ },
19
+ amend: {
20
+ describe: 'Amend the current commit',
21
+ type: 'boolean'
22
+ },
23
+ continue: {
24
+ alias: 'c',
25
+ describe: 'Continue the landing session',
26
+ type: 'boolean'
27
+ },
28
+ final: {
29
+ describe: 'Verify the landed PR and clean up',
30
+ type: 'boolean'
31
+ },
32
+ abort: {
33
+ describe: 'Abort the current landing session',
34
+ type: 'boolean'
35
+ },
36
+ backport: {
37
+ describe: 'Land a backport PR onto a staging branch',
38
+ default: false,
39
+ type: 'boolean'
40
+ },
41
+ 'gpg-sign': {
42
+ describe: 'GPG-sign commits, will be passed to the git process',
43
+ alias: 'S'
44
+ },
45
+ autorebase: {
46
+ describe: 'Automatically rebase branches with multiple commits',
47
+ default: false,
48
+ type: 'boolean'
49
+ },
50
+ fixupAll: {
51
+ describe: 'Automatically fixup all commits to the first one dismissing ' +
52
+ 'other commit messages',
53
+ default: false,
54
+ type: 'boolean'
55
+ },
56
+ oneCommitMax: {
57
+ describe: 'When run in conjunction with the --yes and --autorebase ' +
58
+ 'options, will abort the session if trying to land more than one commit',
59
+ default: false,
60
+ type: 'boolean'
61
+ }
62
+ };
63
+
64
+ const landOptions = {
65
+ yes: {
66
+ type: 'boolean',
67
+ default: false,
68
+ describe: 'Assume "yes" as answer to all prompts and run ' +
69
+ 'non-interactively. If an undesirable situation occurs, such as a pull ' +
70
+ 'request or commit check fails, then git node land will abort.'
71
+ },
72
+ skipRefs: {
73
+ describe: 'Prevent adding Fixes and Refs information to commit metadata',
74
+ default: false,
75
+ type: 'boolean'
76
+ },
77
+ lint: {
78
+ describe: 'Run linter while landing commits',
79
+ default: false,
80
+ type: 'boolean'
81
+ },
82
+ checkCI: {
83
+ describe: 'Query Jenkins CI results when checking the PR',
84
+ default: true,
85
+ type: 'boolean'
86
+ }
87
+ };
88
+
89
+ let yargsInstance;
90
+
91
+ export function builder(yargs) {
92
+ yargsInstance = yargs;
93
+ return yargs
94
+ .options(Object.assign({}, landOptions, landActions))
95
+ .positional('prid', {
96
+ describe: 'ID or URL of the Pull Request'
97
+ })
98
+ .epilogue(epilogue)
99
+ .example('git node land https://github.com/nodejs/node/pull/12344',
100
+ 'Land https://github.com/nodejs/node/pull/12344 in the current directory')
101
+ .example('git node land 12344',
102
+ 'Land https://github.com/nodejs/node/pull/12344 in the current directory')
103
+ .example('git node land --abort',
104
+ 'Abort the current session')
105
+ .example('git node land --amend',
106
+ 'Append metadata to the current commit message')
107
+ .example('git node land --final',
108
+ 'Verify the landed PR and clean up')
109
+ .example('git node land --continue',
110
+ 'Continue the current landing session');
111
+ }
112
+
113
+ const START = 'start';
114
+ const APPLY = 'apply';
115
+ const AMEND = 'amend';
116
+ const FINAL = 'final';
117
+ const CONTINUE = 'continue';
118
+ const ABORT = 'abort';
119
+
120
+ export function handler(argv) {
121
+ if (argv.prid) {
122
+ if (Number.isInteger(argv.prid)) {
123
+ return land(START, argv);
124
+ } else {
125
+ const parsed = parsePRFromURL(argv.prid);
126
+ if (parsed) {
127
+ Object.assign(argv, parsed);
128
+ return land(START, argv);
129
+ }
130
+ }
131
+ yargsInstance.showHelp();
132
+ return;
133
+ }
134
+
135
+ const provided = [];
136
+ for (const type of Object.keys(landActions)) {
137
+ if (argv[type]) {
138
+ provided.push(type);
139
+ }
140
+ }
141
+
142
+ if (provided.length === 1) {
143
+ return land(provided[0], argv);
144
+ }
145
+
146
+ // If the more than one action is provided or no valid action
147
+ // is provided, show help.
148
+ yargsInstance.showHelp();
149
+ }
150
+
151
+ function land(state, argv) {
152
+ const cli = new CLI(process.stderr);
153
+ if (argv.yes) {
154
+ cli.setAssumeYes();
155
+ }
156
+ const dir = process.cwd();
157
+
158
+ return runPromise(main(state, argv, cli, dir)).catch((err) => {
159
+ if (cli.spinner.enabled) {
160
+ cli.spinner.fail();
161
+ }
162
+ throw err;
163
+ });
164
+ }
165
+
166
+ async function main(state, argv, cli, dir) {
167
+ const credentials = await auth({
168
+ github: true
169
+ });
170
+ const req = new Request(credentials);
171
+ let session = new LandingSession(cli, req, dir);
172
+
173
+ if (state !== AMEND &&
174
+ state !== CONTINUE &&
175
+ await session.warnForWrongBranch()) {
176
+ return;
177
+ }
178
+
179
+ if (argv.yes) {
180
+ cli.setAssumeYes();
181
+ }
182
+ try {
183
+ session.restore();
184
+ } catch (err) { // JSON error?
185
+ if (state === ABORT) {
186
+ await session.abort();
187
+ return;
188
+ }
189
+ cli.warn(
190
+ 'Failed to detect previous session. ' +
191
+ 'please run `git node land --abort`');
192
+ return;
193
+ }
194
+
195
+ if (state === START) {
196
+ if (session.hasStarted()) {
197
+ cli.warn(
198
+ 'Previous `git node land` session for ' +
199
+ `${session.pullName} in progress.`);
200
+ cli.log('run `git node land --abort` before starting a new session');
201
+ return;
202
+ }
203
+ session = new LandingSession(cli, req, dir, argv);
204
+ const metadata = await getMetadata(session.argv, argv.skipRefs, cli);
205
+ if (argv.backport) {
206
+ const split = metadata.metadata.split('\n')[0];
207
+ if (split === 'PR-URL: ') {
208
+ cli.error('Commit message is missing PR-URL');
209
+ }
210
+ }
211
+ return session.start(metadata);
212
+ } else if (state === APPLY) {
213
+ return session.apply();
214
+ } else if (state === AMEND) {
215
+ return session.amend();
216
+ } else if (state === FINAL) {
217
+ return session.final();
218
+ } else if (state === ABORT) {
219
+ return session.abort();
220
+ } else if (state === CONTINUE) {
221
+ return session.continue();
222
+ }
223
+ }
@@ -0,0 +1,94 @@
1
+ import { parsePRFromURL } from '../../lib/links.js';
2
+ import { getMetadata } from '../metadata.js';
3
+ import CLI from '../../lib/cli.js';
4
+ import { getMergedConfig } from '../../lib/config.js';
5
+ import { runPromise, IGNORE } from '../../lib/run.js';
6
+
7
+ export const command = 'metadata <identifier>';
8
+ export const describe =
9
+ 'Retrieves metadata for a PR and validates them against nodejs/node PR rules';
10
+
11
+ const config = getMergedConfig();
12
+
13
+ const options = {
14
+ owner: {
15
+ alias: 'o',
16
+ describe: 'GitHub owner of the PR repository',
17
+ default: 'nodejs',
18
+ type: 'string'
19
+ },
20
+ repo: {
21
+ default: 'node',
22
+ alias: 'r',
23
+ describe: 'GitHub repository of the PR',
24
+ type: 'string'
25
+ },
26
+ file: {
27
+ alias: 'f',
28
+ describe: 'File to write the metadata in',
29
+ type: 'string'
30
+ },
31
+ readme: {
32
+ describe: 'Path to file that contains collaborator contacts',
33
+ type: 'string'
34
+ },
35
+ 'check-comments': {
36
+ describe: 'Check for \'LGTM\' in comments',
37
+ type: 'boolean'
38
+ },
39
+ 'max-commits': {
40
+ describe: 'Number of commits to warn',
41
+ type: 'number',
42
+ default: 3
43
+ }
44
+ };
45
+
46
+ let yargsInstance;
47
+
48
+ export function builder(yargs) {
49
+ yargsInstance = yargs;
50
+ return yargs
51
+ .options(options)
52
+ .positional('identifier', {
53
+ type: 'string',
54
+ describe: 'ID or URL of the pull request'
55
+ })
56
+ .example('git node metadata 12344',
57
+ 'Retrieve the metadata of https://github.com/nodejs/node/pull/12344 ' +
58
+ 'and validate the PR')
59
+ .example('git node metadata https://github.com/nodejs/node/pull/12344',
60
+ 'Retrieve the metadata of https://github.com/nodejs/node/pull/12344 ' +
61
+ 'and validate it')
62
+ .example('git node metadata 167 --repo llnode --readme ../node/README.md',
63
+ 'Retrieve the metadata of https://github.com/nodejs/llnode/pull/167 ' +
64
+ 'and validate it using the README in ../node/README.md')
65
+ .wrap(90);
66
+ }
67
+
68
+ export function handler(argv) {
69
+ let parsed = {};
70
+ const prid = Number.parseInt(argv.identifier);
71
+ if (!Number.isNaN(prid)) {
72
+ parsed.prid = prid;
73
+ } else {
74
+ parsed = parsePRFromURL(argv.identifier);
75
+ if (!parsed) {
76
+ return yargsInstance.showHelp();
77
+ }
78
+ }
79
+
80
+ if (!Number.isInteger(argv.maxCommits) || argv.maxCommits < 0) {
81
+ return yargsInstance.showHelp();
82
+ }
83
+
84
+ const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
85
+ const cli = new CLI(logStream);
86
+
87
+ const merged = Object.assign({}, argv, parsed, config);
88
+ return runPromise(getMetadata(merged, false, cli)
89
+ .then(({ status }) => {
90
+ if (status === false) {
91
+ throw new Error(IGNORE);
92
+ }
93
+ }));
94
+ }
@@ -0,0 +1,99 @@
1
+ import CLI from '../../lib/cli.js';
2
+ import ReleasePreparation from '../../lib/prepare_release.js';
3
+ import { runPromise } from '../../lib/run.js';
4
+
5
+ export const command = 'release [newVersion|options]';
6
+ export const describe = 'Manage an in-progress release or start a new one.';
7
+
8
+ const PREPARE = 'prepare';
9
+ const PROMOTE = 'promote';
10
+
11
+ const releaseOptions = {
12
+ prepare: {
13
+ describe: 'Prepare a new release of Node.js',
14
+ type: 'boolean'
15
+ },
16
+ promote: {
17
+ describe: 'Promote new release of Node.js',
18
+ type: 'boolean'
19
+ },
20
+ security: {
21
+ describe: 'Demarcate the new security release as a security release',
22
+ type: 'boolean'
23
+ },
24
+ filterLabel: {
25
+ describe: 'Labels separated by "," to filter security PRs',
26
+ type: 'string'
27
+ },
28
+ skipBranchDiff: {
29
+ describe: 'Skips the initial branch-diff check when preparing releases',
30
+ type: 'boolean'
31
+ },
32
+ startLTS: {
33
+ describe: 'Mark the release as the transition from Current to LTS',
34
+ type: 'boolean'
35
+ }
36
+ };
37
+
38
+ let yargsInstance;
39
+
40
+ export function builder(yargs) {
41
+ yargsInstance = yargs;
42
+ return yargs
43
+ .options(releaseOptions).positional('newVersion', {
44
+ describe: 'Version number of the release to be prepared or promoted'
45
+ })
46
+ .example('git node release --prepare 1.2.3',
47
+ 'Prepare a release of Node.js tagged v1.2.3')
48
+ .example('git node --prepare --startLTS',
49
+ 'Prepare the first LTS release');
50
+ }
51
+
52
+ export function handler(argv) {
53
+ if (argv.prepare) {
54
+ return release(PREPARE, argv);
55
+ } else if (argv.promote) {
56
+ return release(PROMOTE, argv);
57
+ }
58
+
59
+ // If more than one action is provided or no valid action
60
+ // is provided, show help.
61
+ yargsInstance.showHelp();
62
+ }
63
+
64
+ function release(state, argv) {
65
+ const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
66
+ const cli = new CLI(logStream);
67
+ const dir = process.cwd();
68
+
69
+ return runPromise(main(state, argv, cli, dir)).catch((err) => {
70
+ if (cli.spinner.enabled) {
71
+ cli.spinner.fail();
72
+ }
73
+ throw err;
74
+ });
75
+ }
76
+
77
+ async function main(state, argv, cli, dir) {
78
+ if (state === PREPARE) {
79
+ const prep = new ReleasePreparation(argv, cli, dir);
80
+
81
+ if (prep.warnForWrongBranch()) return;
82
+
83
+ // If the new version was automatically calculated, confirm it.
84
+ if (!argv.newVersion) {
85
+ const create = await cli.prompt(
86
+ `Create release with new version ${prep.newVersion}?`,
87
+ { defaultAnswer: true });
88
+
89
+ if (!create) {
90
+ cli.error('Aborting release preparation process');
91
+ return;
92
+ }
93
+ }
94
+
95
+ return prep.prepare();
96
+ } else if (state === PROMOTE) {
97
+ // TODO(codebytere): implement release promotion.
98
+ }
99
+ }
@@ -0,0 +1,35 @@
1
+ import CLI from '../../lib/cli.js';
2
+ import SecurityReleaseSteward from '../../lib/prepare_security.js';
3
+
4
+ export const command = 'security [options]';
5
+ export const describe = 'Manage an in-progress security release or start a new one.';
6
+
7
+ const securityOptions = {
8
+ start: {
9
+ describe: 'Start security release process',
10
+ type: 'boolean'
11
+ }
12
+ };
13
+
14
+ let yargsInstance;
15
+
16
+ export function builder(yargs) {
17
+ yargsInstance = yargs;
18
+ return yargs.options(securityOptions).example(
19
+ 'git node security --start',
20
+ 'Prepare a security release of Node.js');
21
+ }
22
+
23
+ export function handler(argv) {
24
+ if (argv.start) {
25
+ return startSecurityRelease(argv);
26
+ }
27
+ yargsInstance.showHelp();
28
+ }
29
+
30
+ async function startSecurityRelease(argv) {
31
+ const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
32
+ const cli = new CLI(logStream);
33
+ const release = new SecurityReleaseSteward(cli);
34
+ return release.start();
35
+ }
@@ -0,0 +1,32 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+
4
+ import { readJson } from './../../lib/file.js';
5
+ import { getNcuDir } from './../../lib/config.js';
6
+ import CLI from '../../lib/cli.js';
7
+
8
+ const cli = new CLI();
9
+
10
+ export const command = 'status';
11
+ export const describe =
12
+ 'Return status and information about the current git-node land session.';
13
+
14
+ export function handler() {
15
+ const ncuDir = getNcuDir(process.cwd());
16
+ const landPath = path.join(ncuDir, 'land');
17
+
18
+ if (fs.existsSync(landPath)) {
19
+ const { state, prid, config } = readJson(landPath);
20
+ const { username, branch, upstream } = config;
21
+
22
+ cli.ok('Landing session in progress');
23
+ cli.separator();
24
+ cli.table('PR:', `https:/github.com/nodejs/node/pull/${prid}`);
25
+ cli.table('State:', state);
26
+ cli.table('Username:', username);
27
+ cli.table('Upstream:', upstream);
28
+ cli.table('Branch:', branch);
29
+ } else {
30
+ cli.warn('No landing session in progress');
31
+ }
32
+ }
@@ -0,0 +1,24 @@
1
+ import CLI from '../../lib/cli.js';
2
+ import { runPromise } from '../../lib/run.js';
3
+ import SyncSession from '../../lib/sync_session.js';
4
+
5
+ export const command = 'sync';
6
+ export const describe = 'Sync the branch specified by ncu-config.';
7
+
8
+ export function builder(yargs) {
9
+ return yargs
10
+ .epilogue('Demo: https://asciinema.org/a/221230')
11
+ .wrap(90);
12
+ }
13
+
14
+ async function main() {
15
+ const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
16
+ const cli = new CLI(logStream);
17
+ const dir = process.cwd();
18
+ const session = new SyncSession(cli, dir);
19
+ await session.sync();
20
+ }
21
+
22
+ export function handler(argv) {
23
+ return runPromise(main());
24
+ }