Skip to content

Commit 824016f

Browse files
committed
refactor: pull some builds into own files
1 parent c1dfbd0 commit 824016f

File tree

7 files changed

+571
-488
lines changed

7 files changed

+571
-488
lines changed

bin/ncu-ci

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ const argv = yargs
107107
builder: (yargs) => {
108108
yargs
109109
.positional('jobid', {
110-
describe: 'id of the job',
110+
describe: 'id of the first job',
111111
type: 'number'
112112
});
113113
},
@@ -316,9 +316,11 @@ class JobCommand extends CICommand {
316316
}
317317

318318
async initialize() {
319-
this.queue.push({
319+
const { queue, argv } = this;
320+
321+
queue.push({
320322
type: commandToType[this.command],
321-
jobid: this.argv.jobid
323+
jobid: argv.jobid
322324
});
323325
}
324326
}

lib/ci/build-types/citgm_build.js

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
'use strict';
2+
3+
const { TestBuild } = require('./test_build');
4+
const { flatten } = require('../../utils');
5+
const { getNodeName, pad } = require('../ci_utils');
6+
7+
const {
8+
CITGM_MAIN_TREE,
9+
CITGM_REPORT_TREE
10+
} = require('../jenkins_constants');
11+
const {
12+
FAILURE_TYPES: { NCU_FAILURE },
13+
FAILURE_CONSTRUCTORS: {
14+
[NCU_FAILURE]: NCUFailure
15+
}
16+
} = require('./ci_failure_parser');
17+
18+
class CITGMBuild extends TestBuild {
19+
constructor(cli, request, id) {
20+
// There will always be at least one job id.
21+
const path = `job/citgm-smoker/${id}/`;
22+
const tree = CITGM_MAIN_TREE;
23+
24+
super(cli, request, path, tree);
25+
26+
this.id = id;
27+
}
28+
29+
async getResults() {
30+
const { apiUrl, id } = this;
31+
32+
let headerData;
33+
try {
34+
headerData = await this.getBuildData('Summary');
35+
} catch (err) {
36+
this.failures = [
37+
new NCUFailure({ url: this.apiUrl }, err.message)
38+
];
39+
return this.failures;
40+
}
41+
const { result } = headerData;
42+
43+
this.setBuildData(headerData);
44+
45+
// CITGM jobs store results in a different location than
46+
// they do summary data, so we need to update the endpoint
47+
// and issue a second API call in order to fetch result data.
48+
this.tree = CITGM_REPORT_TREE;
49+
this.path = `job/citgm-smoker/${id}/testReport/`;
50+
51+
let resultData;
52+
try {
53+
resultData = await this.getBuildData('Results');
54+
} catch (err) {
55+
this.failures = [
56+
new NCUFailure({ url: apiUrl }, err.message)
57+
];
58+
return this.failures;
59+
}
60+
61+
this.results = this.parseResults(resultData);
62+
63+
// Update id again so that it correctly displays in Summary output.
64+
this.path = `job/citgm-smoker/${id}/`;
65+
66+
return { result };
67+
}
68+
69+
parseResults(data) {
70+
const { childReports, totalCount, skipCount, failCount } = data;
71+
const results = { all: {}, failures: {}, statistics: {} };
72+
73+
const passCount = totalCount - failCount - skipCount;
74+
results.statistics.passed = passCount;
75+
results.statistics.total = totalCount;
76+
results.statistics.skipped = skipCount;
77+
results.statistics.failed = failCount;
78+
79+
childReports.forEach(platform => {
80+
const cases = flatten(platform.result.suites[0].cases);
81+
const url = platform.child.url;
82+
const nodeName = getNodeName(url);
83+
84+
results.all[nodeName] = { url, modules: cases };
85+
86+
const failedModules = cases.filter(c => c.status === 'FAILED');
87+
results.failures[nodeName] = { url, modules: failedModules };
88+
});
89+
90+
return results;
91+
}
92+
93+
displayBuilds() {
94+
const { cli, results } = this;
95+
const { failed, skipped, passed, total } = results.statistics;
96+
97+
cli.separator('Statistics');
98+
console.table({
99+
Failed: failed,
100+
Skipped: skipped,
101+
Passed: passed,
102+
Total: total
103+
});
104+
105+
cli.separator('Failures');
106+
const output = {};
107+
for (const platform in results.failures) {
108+
const modules = results.failures[platform].modules;
109+
const failures = modules.map(f => f.name);
110+
111+
output[platform] = failures;
112+
}
113+
114+
console.table(output);
115+
}
116+
117+
formatAsJson() {
118+
const { jobUrl, results, sourceURL } = this;
119+
120+
const result = {
121+
source: sourceURL,
122+
upstream: jobUrl,
123+
...results.statistics,
124+
...results.failures
125+
};
126+
127+
return JSON.parse(JSON.stringify(result));
128+
}
129+
130+
formatAsMarkdown() {
131+
const { jobUrl, result, results, id } = this;
132+
133+
let output = `# CITGM Data for [${id}](${jobUrl})\n\n`;
134+
135+
const { failed, skipped, passed, total } = results.statistics;
136+
137+
output += `## Statistics for job [${id}](${jobUrl})\n\n`;
138+
output += '| FAILED | SKIPPED | PASSED | TOTAL |\n';
139+
output += '| -------- | --------- | -------- | ------- |\n';
140+
output += `| ${pad(failed, 8)} | ${pad(skipped, 9)} |`;
141+
output += ` ${pad(passed, 8)} | ${pad(total, 7)} |\n\n`;
142+
143+
if (result === 'success') {
144+
output += `Job [${id}](${jobUrl}) is green.`;
145+
return output;
146+
}
147+
148+
output += `## Failures in job [${id}](${jobUrl})\n\n`;
149+
for (const failure in results.failures) {
150+
const data = results.failures[failure];
151+
output += `### [${failure}](${data.url})\n\n`;
152+
153+
const failures = data.modules.map(f => `* ${f.name}`);
154+
output += `${failures.join('\n')}\n\n`;
155+
}
156+
return output;
157+
}
158+
}
159+
160+
module.exports = { CITGMBuild };

lib/ci/build-types/job.js

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
'use strict';
2+
3+
const qs = require('querystring');
4+
const { CI_DOMAIN } = require('../ci_type_parser');
5+
const Cache = require('../../cache');
6+
const CIFailureParser = require('../ci_failure_parser');
7+
const {
8+
FAILURE_TYPES: { NCU_FAILURE },
9+
FAILURE_CONSTRUCTORS: {
10+
[NCU_FAILURE]: NCUFailure
11+
},
12+
CIResult
13+
} = CIFailureParser;
14+
15+
class Job {
16+
constructor(cli, request, path, tree) {
17+
this.cli = cli;
18+
this.request = request;
19+
this.path = path;
20+
this.tree = tree;
21+
}
22+
23+
get jobUrl() {
24+
const { path } = this;
25+
return `https://${CI_DOMAIN}/${path}`;
26+
}
27+
28+
get apiUrl() {
29+
const { tree, jobUrl } = this;
30+
const query = tree ? `?tree=${qs.escape(tree)}` : '';
31+
return `${jobUrl}api/json${query}`;
32+
}
33+
34+
get consoleUrl() {
35+
const { path } = this;
36+
return `https://${CI_DOMAIN}/${path}consoleText`;
37+
}
38+
39+
get consoleUIUrl() {
40+
const { path } = this;
41+
return `https://${CI_DOMAIN}/${path}console`;
42+
}
43+
44+
async getBuildData(type = 'Build') {
45+
const { cli, path } = this;
46+
cli.startSpinner(`Querying data for ${path}`);
47+
const data = await this.getAPIData();
48+
cli.stopSpinner(`${type} data downloaded`);
49+
return data;
50+
}
51+
52+
getCause(actions) {
53+
if (actions && actions.find(item => item.causes)) {
54+
const action = actions.find(item => item.causes);
55+
return action.causes[0];
56+
}
57+
}
58+
59+
async getAPIData() {
60+
const { apiUrl, cli, request, path } = this;
61+
cli.updateSpinner(`Querying API for ${path}`);
62+
return request.json(apiUrl);
63+
}
64+
65+
async getConsoleText() {
66+
const { cli, consoleUrl, request, path } = this;
67+
cli.updateSpinner(`Querying console text for ${path}`);
68+
const data = await request.text(consoleUrl);
69+
return data.replace(/\r/g, '');
70+
}
71+
72+
getCacheKey() {
73+
return this.path
74+
.replace(/job\//, '')
75+
.replace(/\//g, '-')
76+
.replace(/-$/, '');
77+
}
78+
79+
async parseConsoleText() {
80+
let text;
81+
try {
82+
text = await this.getConsoleText();
83+
} catch (err) {
84+
this.failures = [
85+
new NCUFailure({
86+
url: this.consoleUrl, builtOn: this.builtOn
87+
}, err.message)
88+
];
89+
return this.failures;
90+
}
91+
92+
const parser = new CIFailureParser(this, text);
93+
let results = parser.parse();
94+
if (!results) {
95+
results = [
96+
new CIResult({ url: this.jobUrl, builtOn: this.builtOn }, 'Unknown')
97+
];
98+
}
99+
100+
this.failures = results;
101+
return results;
102+
}
103+
}
104+
105+
// TODO(joyeecheung): do not cache pending jobs
106+
const jobCache = new Cache();
107+
jobCache.wrap(Job, {
108+
getConsoleText() {
109+
return { key: this.getCacheKey(), ext: '.txt' };
110+
},
111+
getAPIData() {
112+
return { key: this.getCacheKey(), ext: '.json' };
113+
}
114+
});
115+
116+
module.exports = { Job, jobCache };

0 commit comments

Comments
 (0)