@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.
- package/LICENSE +7 -0
- package/README.md +158 -0
- package/bin/get-metadata.js +11 -0
- package/bin/git-node.js +30 -0
- package/bin/ncu-ci.js +600 -0
- package/bin/ncu-config.js +101 -0
- package/bin/ncu-team.js +76 -0
- package/components/git/backport.js +70 -0
- package/components/git/epilogue.js +18 -0
- package/components/git/land.js +223 -0
- package/components/git/metadata.js +94 -0
- package/components/git/release.js +99 -0
- package/components/git/security.js +35 -0
- package/components/git/status.js +32 -0
- package/components/git/sync.js +24 -0
- package/components/git/v8.js +121 -0
- package/components/git/vote.js +84 -0
- package/components/git/wpt.js +87 -0
- package/components/metadata.js +49 -0
- package/lib/auth.js +133 -0
- package/lib/backport_session.js +302 -0
- package/lib/cache.js +107 -0
- package/lib/cherry_pick.js +304 -0
- package/lib/ci/build-types/benchmark_run.js +72 -0
- package/lib/ci/build-types/citgm_build.js +194 -0
- package/lib/ci/build-types/citgm_comparison_build.js +174 -0
- package/lib/ci/build-types/commit_build.js +112 -0
- package/lib/ci/build-types/daily_build.js +24 -0
- package/lib/ci/build-types/fanned_build.js +87 -0
- package/lib/ci/build-types/health_build.js +63 -0
- package/lib/ci/build-types/job.js +114 -0
- package/lib/ci/build-types/linter_build.js +35 -0
- package/lib/ci/build-types/normal_build.js +89 -0
- package/lib/ci/build-types/pr_build.js +101 -0
- package/lib/ci/build-types/test_build.js +186 -0
- package/lib/ci/build-types/test_run.js +41 -0
- package/lib/ci/ci_failure_parser.js +325 -0
- package/lib/ci/ci_type_parser.js +203 -0
- package/lib/ci/ci_utils.js +106 -0
- package/lib/ci/failure_aggregator.js +152 -0
- package/lib/ci/jenkins_constants.js +28 -0
- package/lib/ci/run_ci.js +120 -0
- package/lib/cli.js +192 -0
- package/lib/collaborators.js +140 -0
- package/lib/config.js +72 -0
- package/lib/figures.js +7 -0
- package/lib/file.js +43 -0
- package/lib/github/templates/next-security-release.md +97 -0
- package/lib/github/tree.js +162 -0
- package/lib/landing_session.js +506 -0
- package/lib/links.js +123 -0
- package/lib/mergeable_state.js +3 -0
- package/lib/metadata_gen.js +61 -0
- package/lib/pr_checker.js +605 -0
- package/lib/pr_data.js +115 -0
- package/lib/pr_summary.js +62 -0
- package/lib/prepare_release.js +772 -0
- package/lib/prepare_security.js +117 -0
- package/lib/proxy.js +21 -0
- package/lib/queries/DefaultBranchRef.gql +8 -0
- package/lib/queries/LastCommit.gql +16 -0
- package/lib/queries/PR.gql +37 -0
- package/lib/queries/PRComments.gql +27 -0
- package/lib/queries/PRCommits.gql +45 -0
- package/lib/queries/PRs.gql +25 -0
- package/lib/queries/Reviews.gql +23 -0
- package/lib/queries/SearchIssue.gql +51 -0
- package/lib/queries/Team.gql +22 -0
- package/lib/queries/TreeEntries.gql +12 -0
- package/lib/queries/VotePRInfo.gql +28 -0
- package/lib/release/utils.js +53 -0
- package/lib/request.js +185 -0
- package/lib/review_state.js +5 -0
- package/lib/reviews.js +178 -0
- package/lib/run.js +106 -0
- package/lib/session.js +415 -0
- package/lib/sync_session.js +15 -0
- package/lib/team_info.js +95 -0
- package/lib/update-v8/applyNodeChanges.js +49 -0
- package/lib/update-v8/backport.js +258 -0
- package/lib/update-v8/commitUpdate.js +26 -0
- package/lib/update-v8/common.js +35 -0
- package/lib/update-v8/constants.js +86 -0
- package/lib/update-v8/index.js +56 -0
- package/lib/update-v8/majorUpdate.js +171 -0
- package/lib/update-v8/minorUpdate.js +105 -0
- package/lib/update-v8/updateMaintainingDependencies.js +34 -0
- package/lib/update-v8/updateV8Clone.js +53 -0
- package/lib/update-v8/updateVersionNumbers.js +122 -0
- package/lib/update-v8/util.js +62 -0
- package/lib/user.js +4 -0
- package/lib/user_status.js +5 -0
- package/lib/utils.js +66 -0
- package/lib/verbosity.js +26 -0
- package/lib/voting_session.js +136 -0
- package/lib/wpt/index.js +243 -0
- package/lib/wpt/templates/README.md +16 -0
- package/package.json +69 -0
package/bin/ncu-ci.js
ADDED
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import yargs from 'yargs';
|
|
4
|
+
import clipboardy from 'clipboardy';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
JobParser,
|
|
8
|
+
parseJobFromURL,
|
|
9
|
+
CI_TYPES_KEYS
|
|
10
|
+
} from '../lib/ci/ci_type_parser.js';
|
|
11
|
+
import { setVerbosityFromEnv } from '../lib/verbosity.js';
|
|
12
|
+
import { listBuilds } from '../lib/ci/ci_utils.js';
|
|
13
|
+
import { jobCache } from '../lib/ci/build-types/job.js';
|
|
14
|
+
import { PRBuild } from '../lib/ci/build-types/pr_build.js';
|
|
15
|
+
import { CommitBuild } from '../lib/ci/build-types/commit_build.js';
|
|
16
|
+
import { DailyBuild } from '../lib/ci/build-types/daily_build.js';
|
|
17
|
+
import { FailureAggregator } from '../lib/ci/failure_aggregator.js';
|
|
18
|
+
import { BenchmarkRun } from '../lib/ci/build-types/benchmark_run.js';
|
|
19
|
+
import { HealthBuild } from '../lib/ci/build-types/health_build.js';
|
|
20
|
+
import { CITGMBuild } from '../lib/ci/build-types/citgm_build.js';
|
|
21
|
+
import {
|
|
22
|
+
CITGMComparisonBuild
|
|
23
|
+
} from '../lib/ci/build-types/citgm_comparison_build.js';
|
|
24
|
+
import {
|
|
25
|
+
RunPRJob
|
|
26
|
+
} from '../lib/ci/run_ci.js';
|
|
27
|
+
import { writeJson, writeFile } from '../lib/file.js';
|
|
28
|
+
import { getMergedConfig } from '../lib/config.js';
|
|
29
|
+
import { runPromise } from '../lib/run.js';
|
|
30
|
+
import auth from '../lib/auth.js';
|
|
31
|
+
import Request from '../lib/request.js';
|
|
32
|
+
import CLI from '../lib/cli.js';
|
|
33
|
+
import { hideBin } from 'yargs/helpers';
|
|
34
|
+
|
|
35
|
+
setVerbosityFromEnv();
|
|
36
|
+
|
|
37
|
+
const {
|
|
38
|
+
PR,
|
|
39
|
+
COMMIT,
|
|
40
|
+
BENCHMARK,
|
|
41
|
+
CITGM,
|
|
42
|
+
CITGM_NOBUILD,
|
|
43
|
+
DAILY_MASTER
|
|
44
|
+
} = CI_TYPES_KEYS;
|
|
45
|
+
|
|
46
|
+
const commandKeys = [
|
|
47
|
+
'rate',
|
|
48
|
+
'walk',
|
|
49
|
+
'url',
|
|
50
|
+
'pr',
|
|
51
|
+
'commit',
|
|
52
|
+
'citgm'
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
const args = yargs(hideBin(process.argv))
|
|
56
|
+
.completion('completion')
|
|
57
|
+
.command({
|
|
58
|
+
command: 'rate <type>',
|
|
59
|
+
desc: 'Calculate the green rate of a CI job in the last 100 runs',
|
|
60
|
+
builder: (yargs) => {
|
|
61
|
+
yargs
|
|
62
|
+
.positional('type', {
|
|
63
|
+
describe: 'type of CI',
|
|
64
|
+
choices: ['commit', 'pr']
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
handler
|
|
68
|
+
})
|
|
69
|
+
.command({
|
|
70
|
+
command: 'walk <type>',
|
|
71
|
+
desc: 'Walk the CI and display the failures',
|
|
72
|
+
builder: (yargs) => {
|
|
73
|
+
yargs
|
|
74
|
+
.positional('type', {
|
|
75
|
+
describe: 'type of CI',
|
|
76
|
+
choices: ['commit', 'pr']
|
|
77
|
+
})
|
|
78
|
+
.option('stats', {
|
|
79
|
+
default: false,
|
|
80
|
+
describe: 'Aggregate the results'
|
|
81
|
+
})
|
|
82
|
+
.option('cache', {
|
|
83
|
+
default: false,
|
|
84
|
+
describe: 'Cache the responses from Jenkins in .ncu/cache/ under' +
|
|
85
|
+
' the node-core-utils installation directory'
|
|
86
|
+
})
|
|
87
|
+
.option('limit', {
|
|
88
|
+
default: 99,
|
|
89
|
+
describe: 'Maximum number of CIs to get data from'
|
|
90
|
+
})
|
|
91
|
+
.option('since <date>', {
|
|
92
|
+
type: 'string',
|
|
93
|
+
describe: 'Time since when the CI results should be queried'
|
|
94
|
+
}).check(argv => {
|
|
95
|
+
try {
|
|
96
|
+
// eslint-disable-next-line no-new
|
|
97
|
+
new Date(argv.since);
|
|
98
|
+
} catch {
|
|
99
|
+
throw new Error('--since <date> should be string that can ' +
|
|
100
|
+
'be parsed by new Date()');
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
handler
|
|
106
|
+
})
|
|
107
|
+
.command({
|
|
108
|
+
command: 'run <prid>',
|
|
109
|
+
desc: 'Run CI for given PR',
|
|
110
|
+
builder: (yargs) => {
|
|
111
|
+
yargs
|
|
112
|
+
.positional('prid', {
|
|
113
|
+
describe: 'ID of the PR',
|
|
114
|
+
type: 'number'
|
|
115
|
+
})
|
|
116
|
+
.option('owner', {
|
|
117
|
+
default: '',
|
|
118
|
+
describe: 'GitHub repository owner'
|
|
119
|
+
})
|
|
120
|
+
.option('repo', {
|
|
121
|
+
default: '',
|
|
122
|
+
describe: 'GitHub repository name'
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
handler
|
|
126
|
+
})
|
|
127
|
+
.command({
|
|
128
|
+
command: 'url <url>',
|
|
129
|
+
desc: 'Automatically detect CI type and show results',
|
|
130
|
+
builder: (yargs) => {
|
|
131
|
+
yargs
|
|
132
|
+
.positional('url', {
|
|
133
|
+
describe: 'URL of the PR or the CI',
|
|
134
|
+
type: 'string'
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
handler
|
|
138
|
+
})
|
|
139
|
+
.command({
|
|
140
|
+
command: 'pr <jobid>',
|
|
141
|
+
desc: 'Show results of a node-test-pull-request CI job',
|
|
142
|
+
builder: (yargs) => {
|
|
143
|
+
yargs
|
|
144
|
+
.positional('jobid', {
|
|
145
|
+
describe: 'id of the job',
|
|
146
|
+
type: 'number'
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
handler
|
|
150
|
+
})
|
|
151
|
+
.command({
|
|
152
|
+
command: 'commit <jobid>',
|
|
153
|
+
desc: 'Show results of a node-test-commit CI job',
|
|
154
|
+
builder: (yargs) => {
|
|
155
|
+
yargs
|
|
156
|
+
.positional('jobid', {
|
|
157
|
+
describe: 'id of the first job',
|
|
158
|
+
type: 'number'
|
|
159
|
+
});
|
|
160
|
+
},
|
|
161
|
+
handler
|
|
162
|
+
})
|
|
163
|
+
.command({
|
|
164
|
+
command: 'benchmark <jobid>',
|
|
165
|
+
desc: 'Show results of a benchmark-node-micro-benchmarks CI job',
|
|
166
|
+
builder: (yargs) => {
|
|
167
|
+
yargs
|
|
168
|
+
.positional('jobid', {
|
|
169
|
+
describe: 'id of the job',
|
|
170
|
+
type: 'number'
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
handler
|
|
174
|
+
})
|
|
175
|
+
.command({
|
|
176
|
+
command: 'citgm <jobid> [jobid2]',
|
|
177
|
+
desc: 'Show results of a citgm-smoker CI job',
|
|
178
|
+
builder: (yargs) => {
|
|
179
|
+
yargs
|
|
180
|
+
.positional('jobid', {
|
|
181
|
+
describe: 'id of the job',
|
|
182
|
+
type: 'number'
|
|
183
|
+
})
|
|
184
|
+
.positional('jobid2', {
|
|
185
|
+
describe: 'id of the second job, if doing a comparison',
|
|
186
|
+
type: 'number'
|
|
187
|
+
});
|
|
188
|
+
},
|
|
189
|
+
handler
|
|
190
|
+
})
|
|
191
|
+
.command({
|
|
192
|
+
command: 'daily',
|
|
193
|
+
desc: 'Show recent results of node-daily-master',
|
|
194
|
+
builder: (yargs) => {
|
|
195
|
+
yargs
|
|
196
|
+
.option('stats', {
|
|
197
|
+
default: false,
|
|
198
|
+
describe: 'Aggregate the results'
|
|
199
|
+
})
|
|
200
|
+
.option('cache', {
|
|
201
|
+
default: false,
|
|
202
|
+
describe: 'Cache the responses from Jenkins in .ncu/cache/ under' +
|
|
203
|
+
' the node-core-utils installation directory'
|
|
204
|
+
})
|
|
205
|
+
.option('limit', {
|
|
206
|
+
default: 15,
|
|
207
|
+
describe: 'Maximum number of CIs to get data from'
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
handler
|
|
211
|
+
})
|
|
212
|
+
.demandCommand(1, 'must provide a valid command')
|
|
213
|
+
.option('copy', {
|
|
214
|
+
describe: 'Write the results as markdown to clipboard',
|
|
215
|
+
default: false,
|
|
216
|
+
type: 'boolean'
|
|
217
|
+
})
|
|
218
|
+
.option('nobuild', {
|
|
219
|
+
describe: 'If running cigtm, whether or not jobid is citgm-nobuild.',
|
|
220
|
+
type: 'boolean',
|
|
221
|
+
default: false
|
|
222
|
+
})
|
|
223
|
+
.option('json <path>', {
|
|
224
|
+
type: 'string',
|
|
225
|
+
describe: 'Write the results as json to <path>'
|
|
226
|
+
})
|
|
227
|
+
.option('markdown <path>', {
|
|
228
|
+
type: 'string',
|
|
229
|
+
describe: 'Write the results as markdown to <path>'
|
|
230
|
+
}).check(argv => {
|
|
231
|
+
if (argv.markdown && commandKeys.includes(argv.markdown)) {
|
|
232
|
+
throw new Error('--markdown <path> did not specify a valid path');
|
|
233
|
+
} else if (argv.json && commandKeys.includes(argv.json)) {
|
|
234
|
+
throw new Error('--json <path> did not specify a valid path');
|
|
235
|
+
}
|
|
236
|
+
return true;
|
|
237
|
+
})
|
|
238
|
+
.help();
|
|
239
|
+
|
|
240
|
+
args.parse();
|
|
241
|
+
|
|
242
|
+
const commandToType = {
|
|
243
|
+
commit: COMMIT,
|
|
244
|
+
pr: PR,
|
|
245
|
+
benchmark: BENCHMARK,
|
|
246
|
+
citgm: CITGM
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
class RunPRJobCommand {
|
|
250
|
+
constructor(cli, request, argv) {
|
|
251
|
+
this.cli = cli;
|
|
252
|
+
this.request = request;
|
|
253
|
+
this.dir = process.cwd();
|
|
254
|
+
this.argv = argv;
|
|
255
|
+
this.config = getMergedConfig(this.dir);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
get owner() {
|
|
259
|
+
return this.argv.owner || this.config.owner;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
get repo() {
|
|
263
|
+
return this.argv.repo || this.config.repo;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
get prid() {
|
|
267
|
+
return this.argv.prid;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async start() {
|
|
271
|
+
const {
|
|
272
|
+
cli, request, prid, repo, owner
|
|
273
|
+
} = this;
|
|
274
|
+
let validArgs = true;
|
|
275
|
+
if (!repo) {
|
|
276
|
+
validArgs = false;
|
|
277
|
+
cli.error('GitHub repository is missing, please set it via ncu-config ' +
|
|
278
|
+
'or pass it via the --repo option');
|
|
279
|
+
}
|
|
280
|
+
if (!owner) {
|
|
281
|
+
cli.error('GitHub owner is missing, please set it via ncu-config ' +
|
|
282
|
+
'or pass it via the --owner option');
|
|
283
|
+
validArgs = false;
|
|
284
|
+
}
|
|
285
|
+
if (!validArgs) {
|
|
286
|
+
this.cli.setExitCode(1);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const jobRunner = new RunPRJob(cli, request, owner, repo, prid);
|
|
290
|
+
if (!(await jobRunner.start())) {
|
|
291
|
+
this.cli.setExitCode(1);
|
|
292
|
+
process.exitCode = 1;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
class CICommand {
|
|
298
|
+
constructor(cli, request, argv) {
|
|
299
|
+
this.cli = cli;
|
|
300
|
+
this.request = request;
|
|
301
|
+
this.argv = argv;
|
|
302
|
+
this.queue = [];
|
|
303
|
+
this.json = [];
|
|
304
|
+
this.markdown = '';
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async drain() {
|
|
308
|
+
if (this.queue.length === 0) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const { cli, queue, argv, request } = this;
|
|
313
|
+
|
|
314
|
+
for (let i = 0; i < queue.length; ++i) {
|
|
315
|
+
const job = queue[i];
|
|
316
|
+
cli.separator('');
|
|
317
|
+
const progress = `[${i + 1}/${queue.length}]`;
|
|
318
|
+
if (job.link) {
|
|
319
|
+
cli.log(`${progress} Running ${job.link}`);
|
|
320
|
+
} else if (job.jobid) {
|
|
321
|
+
cli.log(`${progress} Running ${job.type}: ${job.jobid}`);
|
|
322
|
+
} else {
|
|
323
|
+
cli.log(`${progress} Running ${job.type}`);
|
|
324
|
+
}
|
|
325
|
+
cli.separator('');
|
|
326
|
+
|
|
327
|
+
let build;
|
|
328
|
+
switch (job.type) {
|
|
329
|
+
case 'health':
|
|
330
|
+
build = new HealthBuild(cli, request, job.ciType, job.builds);
|
|
331
|
+
break;
|
|
332
|
+
case PR:
|
|
333
|
+
build = new PRBuild(cli, request, job.jobid);
|
|
334
|
+
break;
|
|
335
|
+
case COMMIT:
|
|
336
|
+
build = new CommitBuild(cli, request, job.jobid);
|
|
337
|
+
break;
|
|
338
|
+
case CITGM:
|
|
339
|
+
case CITGM_NOBUILD:
|
|
340
|
+
if (job.jobid2) {
|
|
341
|
+
build = new CITGMComparisonBuild(cli, request, job);
|
|
342
|
+
} else {
|
|
343
|
+
build = new CITGMBuild(cli, request, job);
|
|
344
|
+
}
|
|
345
|
+
break;
|
|
346
|
+
case BENCHMARK:
|
|
347
|
+
build = new BenchmarkRun(cli, request, job.jobid);
|
|
348
|
+
break;
|
|
349
|
+
case DAILY_MASTER: {
|
|
350
|
+
const daily = new DailyBuild(cli, request, job.jobid);
|
|
351
|
+
const data = await daily.getBuildData();
|
|
352
|
+
const testCommitBuild = data.subBuilds.filter(subBuild => {
|
|
353
|
+
return subBuild.jobName === 'node-test-commit';
|
|
354
|
+
})[0];
|
|
355
|
+
if (testCommitBuild) {
|
|
356
|
+
build = new CommitBuild(cli, request, testCommitBuild.buildNumber);
|
|
357
|
+
break;
|
|
358
|
+
} else {
|
|
359
|
+
throw new Error('Could not find \'node-test-commit\' job');
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
default:
|
|
363
|
+
throw new Error(`Unknown job type ${job.type}`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
await build.getResults();
|
|
367
|
+
build.display();
|
|
368
|
+
|
|
369
|
+
// Set this.json regardless of whether the user has passed
|
|
370
|
+
// --json - it's needed for failure aggregation.
|
|
371
|
+
const json = build.formatAsJson();
|
|
372
|
+
if (json !== undefined) {
|
|
373
|
+
this.json = this.json.concat(json);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if ((argv.copy || argv.markdown) && !argv.stats) {
|
|
377
|
+
this.markdown += build.formatAsMarkdown();
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async aggregate() {} // noop
|
|
383
|
+
|
|
384
|
+
async serialize() {
|
|
385
|
+
const { argv, cli } = this;
|
|
386
|
+
|
|
387
|
+
if (argv.copy) {
|
|
388
|
+
if (this.markdown) {
|
|
389
|
+
clipboardy.writeSync(this.markdown);
|
|
390
|
+
cli.separator('');
|
|
391
|
+
cli.log('Written markdown to clipboard');
|
|
392
|
+
} else {
|
|
393
|
+
cli.error('No markdown generated');
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (argv.markdown) {
|
|
398
|
+
if (this.markdown) {
|
|
399
|
+
writeFile(argv.markdown, this.markdown);
|
|
400
|
+
cli.separator('');
|
|
401
|
+
cli.log(`Written markdown to ${argv.markdown}`);
|
|
402
|
+
} else {
|
|
403
|
+
cli.error('No markdown generated');
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (argv.json) {
|
|
408
|
+
if (this.json.length) {
|
|
409
|
+
writeJson(argv.json, this.json);
|
|
410
|
+
cli.separator('');
|
|
411
|
+
cli.log(`Wrote JSON to ${argv.json}`);
|
|
412
|
+
} else {
|
|
413
|
+
cli.error('No JSON generated');
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
class RateCommand extends CICommand {
|
|
420
|
+
async initialize() {
|
|
421
|
+
this.queue.push({
|
|
422
|
+
type: 'health',
|
|
423
|
+
ciType: commandToType[this.argv.type]
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
class WalkCommand extends CICommand {
|
|
429
|
+
constructor(cli, request, argv) {
|
|
430
|
+
super(cli, request, argv);
|
|
431
|
+
if (argv.cache) {
|
|
432
|
+
jobCache.enable();
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
async initialize() {
|
|
437
|
+
const ciType = commandToType[this.argv.type];
|
|
438
|
+
const since = this.argv.since ? new Date(this.argv.since) : undefined;
|
|
439
|
+
const builds = await listBuilds(this.cli, this.request, ciType, since);
|
|
440
|
+
if (builds.count === 0) {
|
|
441
|
+
this.cli.log('No applicable builds found.');
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
this.queue.push({ type: 'health', ciType, builds });
|
|
445
|
+
for (const build of builds.failed.slice(0, this.argv.limit)) {
|
|
446
|
+
this.queue.push(build);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async aggregate() {
|
|
451
|
+
const { argv, cli } = this;
|
|
452
|
+
if (this.queue.length === 0) {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
const aggregator = new FailureAggregator(cli, this.json);
|
|
456
|
+
this.json = aggregator.aggregate();
|
|
457
|
+
cli.log('');
|
|
458
|
+
cli.separator('Stats');
|
|
459
|
+
cli.log('');
|
|
460
|
+
aggregator.display();
|
|
461
|
+
|
|
462
|
+
if (argv.markdown || argv.copy) {
|
|
463
|
+
this.markdown = aggregator.formatAsMarkdown();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
class JobCommand extends CICommand {
|
|
469
|
+
constructor(cli, request, argv, command) {
|
|
470
|
+
super(cli, request, argv);
|
|
471
|
+
this.command = command;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
async initialize() {
|
|
475
|
+
const { queue, argv } = this;
|
|
476
|
+
|
|
477
|
+
queue.push({
|
|
478
|
+
type: commandToType[this.command],
|
|
479
|
+
jobid: argv.jobid,
|
|
480
|
+
jobid2: argv.jobid2,
|
|
481
|
+
noBuild: this.argv.nobuild
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
class URLCommand extends CICommand {
|
|
487
|
+
async initialize() {
|
|
488
|
+
const { argv, cli, request, queue } = this;
|
|
489
|
+
const parsed = parseJobFromURL(argv.url);
|
|
490
|
+
if (parsed) {
|
|
491
|
+
queue.push({
|
|
492
|
+
type: parsed.type,
|
|
493
|
+
jobid: parsed.jobid
|
|
494
|
+
});
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Parse CI links from PR.
|
|
499
|
+
const parser = await JobParser.fromPR(argv.url, cli, request);
|
|
500
|
+
if (!parser) { // Not a valid PR URL
|
|
501
|
+
cli.error(`${argv.url} is not a valid PR URL`);
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
const ciMap = parser.parse();
|
|
505
|
+
if (ciMap.size === 0) {
|
|
506
|
+
cli.info(`No CI run detected from ${argv.url}`);
|
|
507
|
+
}
|
|
508
|
+
for (const [type, ci] of ciMap) {
|
|
509
|
+
queue.push({
|
|
510
|
+
type,
|
|
511
|
+
jobid: ci.jobid
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
class DailyCommand extends CICommand {
|
|
518
|
+
constructor(cli, request, argv) {
|
|
519
|
+
super(cli, request, argv);
|
|
520
|
+
if (argv.cache) {
|
|
521
|
+
jobCache.enable();
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
async initialize() {
|
|
526
|
+
const ciType = DAILY_MASTER;
|
|
527
|
+
const builds = await listBuilds(this.cli, this.request, ciType);
|
|
528
|
+
this.queue.push({ type: 'health', ciType, builds });
|
|
529
|
+
for (const build of builds.failed.slice(0, this.argv.limit)) {
|
|
530
|
+
this.queue.push(build);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
async aggregate() {
|
|
535
|
+
const { argv, cli } = this;
|
|
536
|
+
const aggregator = new FailureAggregator(cli, this.json);
|
|
537
|
+
this.json = aggregator.aggregate();
|
|
538
|
+
cli.log('');
|
|
539
|
+
cli.separator('Stats');
|
|
540
|
+
cli.log('');
|
|
541
|
+
aggregator.display();
|
|
542
|
+
|
|
543
|
+
if (argv.markdown || argv.copy) {
|
|
544
|
+
this.markdown = aggregator.formatAsMarkdown();
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
async function main(command, argv) {
|
|
550
|
+
const cli = new CLI();
|
|
551
|
+
const credentials = await auth({
|
|
552
|
+
github: true,
|
|
553
|
+
jenkins: true
|
|
554
|
+
});
|
|
555
|
+
const request = new Request(credentials);
|
|
556
|
+
|
|
557
|
+
let commandHandler;
|
|
558
|
+
// Prepare queue.
|
|
559
|
+
switch (command) {
|
|
560
|
+
case 'run': {
|
|
561
|
+
const jobRunner = new RunPRJobCommand(cli, request, argv);
|
|
562
|
+
return jobRunner.start();
|
|
563
|
+
}
|
|
564
|
+
case 'rate': {
|
|
565
|
+
commandHandler = new RateCommand(cli, request, argv);
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
case 'walk': {
|
|
569
|
+
commandHandler = new WalkCommand(cli, request, argv);
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
case 'url': {
|
|
573
|
+
commandHandler = new URLCommand(cli, request, argv);
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
case 'pr':
|
|
577
|
+
case 'commit':
|
|
578
|
+
case 'citgm':
|
|
579
|
+
case 'benchmark': {
|
|
580
|
+
commandHandler = new JobCommand(cli, request, argv, command);
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
case 'daily': {
|
|
584
|
+
commandHandler = new DailyCommand(cli, request, argv, command);
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
587
|
+
default:
|
|
588
|
+
return args.showHelp();
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
await commandHandler.initialize();
|
|
592
|
+
await commandHandler.drain();
|
|
593
|
+
await commandHandler.aggregate();
|
|
594
|
+
await commandHandler.serialize();
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
function handler(argv) {
|
|
598
|
+
const [command] = argv._;
|
|
599
|
+
runPromise(main(command, argv));
|
|
600
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import yargs from 'yargs';
|
|
4
|
+
import { hideBin } from 'yargs/helpers';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
getConfig, updateConfig, GLOBAL_CONFIG, PROJECT_CONFIG, LOCAL_CONFIG
|
|
8
|
+
} from '../lib/config.js';
|
|
9
|
+
import { setVerbosityFromEnv } from '../lib/verbosity.js';
|
|
10
|
+
|
|
11
|
+
setVerbosityFromEnv();
|
|
12
|
+
|
|
13
|
+
const args = yargs(hideBin(process.argv))
|
|
14
|
+
.completion('completion')
|
|
15
|
+
.command({
|
|
16
|
+
command: 'set <key> <value>',
|
|
17
|
+
desc: 'Set a config variable',
|
|
18
|
+
builder: (yargs) => {
|
|
19
|
+
yargs
|
|
20
|
+
.positional('key', {
|
|
21
|
+
describe: 'key of the configuration',
|
|
22
|
+
type: 'string'
|
|
23
|
+
})
|
|
24
|
+
.positional('value', {
|
|
25
|
+
describe: 'value of the configuration'
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
handler: setHandler
|
|
29
|
+
})
|
|
30
|
+
.command({
|
|
31
|
+
command: 'get <key>',
|
|
32
|
+
desc: 'Get a config variable',
|
|
33
|
+
builder: (yargs) => {
|
|
34
|
+
yargs
|
|
35
|
+
.positional('key', {
|
|
36
|
+
describe: 'key of the configuration',
|
|
37
|
+
type: 'string'
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
handler: getHandler
|
|
41
|
+
})
|
|
42
|
+
.command({
|
|
43
|
+
command: 'list',
|
|
44
|
+
desc: 'List the configurations',
|
|
45
|
+
handler: listHandler
|
|
46
|
+
})
|
|
47
|
+
.demandCommand(1, 'must provide a valid command')
|
|
48
|
+
// Can't set default of boolean variables if using conflict
|
|
49
|
+
// https://github.com/yargs/yargs/issues/929
|
|
50
|
+
// default: false
|
|
51
|
+
.option('global', {
|
|
52
|
+
alias: 'g',
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
describe: 'Use global config (~/.ncurc)'
|
|
55
|
+
})
|
|
56
|
+
.option('project', {
|
|
57
|
+
alias: 'p',
|
|
58
|
+
type: 'boolean',
|
|
59
|
+
describe: 'Use project config (./.ncurc)'
|
|
60
|
+
})
|
|
61
|
+
.conflicts('global', 'project')
|
|
62
|
+
.help();
|
|
63
|
+
|
|
64
|
+
const argv = args.parse();
|
|
65
|
+
|
|
66
|
+
function getConfigType(argv) {
|
|
67
|
+
if (argv.global) {
|
|
68
|
+
return { configName: 'global', configType: GLOBAL_CONFIG };
|
|
69
|
+
}
|
|
70
|
+
if (argv.project) {
|
|
71
|
+
return { configName: 'project', configType: PROJECT_CONFIG };
|
|
72
|
+
}
|
|
73
|
+
return { configName: 'local', configType: LOCAL_CONFIG };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function setHandler(argv) {
|
|
77
|
+
const { configName, configType } = getConfigType(argv);
|
|
78
|
+
const config = getConfig(configType);
|
|
79
|
+
console.log(
|
|
80
|
+
`Updating ${configName} configuration ` +
|
|
81
|
+
`[${argv.key}]: ${config[argv.key]} -> ${argv.value}`);
|
|
82
|
+
updateConfig(configType, { [argv.key]: argv.value });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function getHandler(argv) {
|
|
86
|
+
const { configType } = getConfigType(argv);
|
|
87
|
+
const config = getConfig(configType);
|
|
88
|
+
console.log(config[argv.key]);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function listHandler(argv) {
|
|
92
|
+
const { configType } = getConfigType(argv);
|
|
93
|
+
const config = getConfig(configType);
|
|
94
|
+
for (const key of Object.keys(config)) {
|
|
95
|
+
console.log(`${key}: ${config[key]}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!['get', 'set', 'list'].includes(argv._[0])) {
|
|
100
|
+
args.showHelp();
|
|
101
|
+
}
|