Skip to content

Commit fb729a9

Browse files
committed
ncu-ci: command to start CI for PRs
1 parent ae3aeb9 commit fb729a9

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

bin/ncu-ci

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ const {
1414
PRBuild, BenchmarkRun, CommitBuild, HealthBuild,
1515
listBuilds, FailureAggregator, jobCache
1616
} = require('../lib/ci/ci_result_parser');
17+
const {
18+
RunPRJob
19+
} = require('../lib/ci/run_ci');
1720
const clipboardy = require('clipboardy');
1821
const { writeJson, writeFile } = require('../lib/file');
22+
const { getMergedConfig } = require('../lib/config');
1923

2024
const { runPromise } = require('../lib/run');
2125
const auth = require('../lib/auth');
@@ -70,6 +74,26 @@ const argv = yargs
7074
},
7175
handler
7276
})
77+
.command({
78+
command: 'run <prid>',
79+
desc: 'Run CI for given PR',
80+
builder: (yargs) => {
81+
yargs
82+
.positional('prid', {
83+
describe: 'ID of the PR',
84+
type: 'number'
85+
})
86+
.option('owner', {
87+
default: '',
88+
describe: 'GitHub repository owner'
89+
})
90+
.option('repo', {
91+
default: '',
92+
describe: 'GitHub repository name'
93+
});
94+
},
95+
handler
96+
})
7397
.command({
7498
command: 'url <url>',
7599
desc: 'Automatically detect CI type and show results',
@@ -147,6 +171,51 @@ const commandToType = {
147171
benchmark: BENCHMARK
148172
};
149173

174+
class RunPRJobCommand {
175+
constructor(cli, request, argv) {
176+
this.cli = cli;
177+
this.request = request;
178+
this.dir = process.cwd();
179+
this.argv = argv;
180+
this.config = getMergedConfig(this.dir);
181+
}
182+
183+
get owner() {
184+
return this.argv.owner || this.config.owner;
185+
}
186+
187+
get repo() {
188+
return this.argv.repo || this.config.repo;
189+
}
190+
191+
get prid() {
192+
return this.argv.prid;
193+
}
194+
195+
async start() {
196+
const {
197+
cli, request, prid, repo, owner
198+
} = this;
199+
let validArgs = true;
200+
if (!repo) {
201+
validArgs = false;
202+
cli.error('GitHub repository is missing, please set it via ncu-config ' +
203+
'or pass it via the --repo option');
204+
}
205+
if (!owner) {
206+
cli.error('GitHub owner is missing, please set it via ncu-config ' +
207+
'or pass it via the --owner option');
208+
validArgs = false;
209+
}
210+
if (!validArgs) {
211+
// this.setExitCode(1);
212+
return;
213+
}
214+
const jobRunner = new RunPRJob(cli, request, owner, repo, prid);
215+
return jobRunner.start();
216+
}
217+
}
218+
150219
class CICommand {
151220
constructor(cli, request, argv) {
152221
this.cli = cli;
@@ -343,6 +412,10 @@ async function main(command, argv) {
343412
let commandHandler;
344413
// Prepare queue.
345414
switch (command) {
415+
case 'run': {
416+
const jobRunner = new RunPRJobCommand(cli, request, argv);
417+
return jobRunner.start();
418+
}
346419
case 'rate': {
347420
commandHandler = new RateCommand(cli, request, argv);
348421
break;

lib/ci/run_ci.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
'use strict';
2+
3+
var FormData = require('form-data');
4+
5+
const {
6+
CI_DOMAIN,
7+
CI_TYPES,
8+
CI_TYPES_KEYS
9+
} = require('./ci_type_parser');
10+
11+
const CI_CRUMB_URL = `https://${CI_DOMAIN}/crumbIssuer/api/json`;
12+
const CI_PR_NAME = CI_TYPES.get(CI_TYPES_KEYS.PR).jobName;
13+
const CI_PR_URL = `https://${CI_DOMAIN}/job/${CI_PR_NAME}/build`;
14+
15+
class RunPRJob {
16+
constructor(cli, request, owner, repo, prid) {
17+
this.cli = cli;
18+
this.request = request;
19+
this.owner = owner;
20+
this.repo = repo;
21+
this.prid = prid;
22+
}
23+
24+
async getCrumb() {
25+
try {
26+
const { crumb } = await this.request.json(CI_CRUMB_URL);
27+
return crumb;
28+
} catch (e) {
29+
this.cli.error('Failed to get breadcrumbs');
30+
}
31+
}
32+
33+
get payload() {
34+
const payload = new FormData();
35+
payload.append('json', JSON.stringify({
36+
parameter: [
37+
{ name: 'CERTIFY_SAFE', value: 'on' },
38+
{ name: 'TARGET_GITHUB_ORG', value: this.owner },
39+
{ name: 'TARGET_REPO_NAME', value: this.repo },
40+
{ name: 'PR_ID', value: this.prid },
41+
{ name: 'REBASE_ONTO', value: '<pr base branch>' },
42+
{ name: 'DESCRIPTION_SETTER_DESCRIPTION', value: '' }
43+
]
44+
}));
45+
return payload;
46+
}
47+
48+
async start() {
49+
this.cli.startSpinner('Validating Jenkins credentials');
50+
const crumb = await this.getCrumb();
51+
52+
if (!crumb) return;
53+
this.cli.stopSpinner('Jenkins credentials valid');
54+
55+
try {
56+
this.cli.startSpinner('Starting PR CI job');
57+
await this.request.text(CI_PR_URL, {
58+
method: 'POST',
59+
headers: {
60+
'Jenkins-Crumb': crumb
61+
},
62+
body: this.payload
63+
});
64+
this.cli.stopSpinner('Starting PR CI job');
65+
this.cli.ok('CI job started');
66+
} catch (err) {
67+
this.cli.stopSpinner('');
68+
this.cli.error('Failed to start CI');
69+
}
70+
}
71+
}
72+
73+
module.exports = { RunPRJob };

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"core-validate-commit": "^3.13.1",
4040
"execa": "^4.0.1",
4141
"figures": "^3.2.0",
42+
"form-data": "^3.0.0",
4243
"fs-extra": "^9.0.0",
4344
"ghauth": "^4.0.0",
4445
"inquirer": "^7.1.0",

0 commit comments

Comments
 (0)