Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit aa762dd

Browse files
committedJul 9, 2020
ncu-ci: command to start CI for PRs
1 parent 158efdf commit aa762dd

File tree

3 files changed

+155
-0
lines changed

3 files changed

+155
-0
lines changed
 

‎bin/ncu-ci

+76
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,54 @@ 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.cli.setExitCode(1);
212+
return;
213+
}
214+
const jobRunner = new RunPRJob(cli, request, owner, repo, prid);
215+
if (!jobRunner.start()) {
216+
this.cli.setExitCode(1);
217+
process.exitCode = 1;
218+
}
219+
}
220+
}
221+
150222
class CICommand {
151223
constructor(cli, request, argv) {
152224
this.cli = cli;
@@ -343,6 +415,10 @@ async function main(command, argv) {
343415
let commandHandler;
344416
// Prepare queue.
345417
switch (command) {
418+
case 'run': {
419+
const jobRunner = new RunPRJobCommand(cli, request, argv);
420+
return jobRunner.start();
421+
}
346422
case 'rate': {
347423
commandHandler = new RateCommand(cli, request, argv);
348424
break;

‎lib/ci/run_ci.js

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
'use strict';
2+
3+
const 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+
return false;
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+
const { cli } = this;
50+
cli.startSpinner('Validating Jenkins credentials');
51+
const crumb = await this.getCrumb();
52+
53+
if (crumb === false) {
54+
cli.stopSpinner('Jenkins credentials invalid',
55+
this.cli.SPINNER_STATUS.FAILED);
56+
return false;
57+
}
58+
cli.stopSpinner('Jenkins credentials valid');
59+
60+
try {
61+
cli.startSpinner('Starting PR CI job');
62+
await this.request.text(CI_PR_URL, {
63+
method: 'POST',
64+
headers: {
65+
'Jenkins-Crumb': crumb
66+
},
67+
body: this.payload
68+
});
69+
cli.stopSpinner('PR CI job successfully started');
70+
} catch (err) {
71+
cli.stopSpinner('Failed to start CI', this.cli.SPINNER_STATUS.FAILED);
72+
return false;
73+
}
74+
return true;
75+
}
76+
}
77+
78+
module.exports = { RunPRJob };

‎package.json

+1
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)
Please sign in to comment.