Skip to content

Commit b014e26

Browse files
committed
feat: check Actions and handle doc-only changes
Doc-only changes don't need a full Jenkins CI, instead we can check if the last Actions run was successful. Therefore this commit also adds check for Action runs. Jenkins CI messages were improved as well. Fix: #324 Fix: nodejs/node#32335 Fix: nodejs/node#29770
1 parent 4b32ebc commit b014e26

File tree

9 files changed

+802
-15
lines changed

9 files changed

+802
-15
lines changed

lib/ci/ci_type_parser.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ const CI_TYPE_ENUM = {
2525
};
2626

2727
const CI_PROVIDERS = {
28-
JENKINS: 'jenkins',
29-
GITHUB: 'github-check'
28+
GITHUB: 'github-check',
29+
NODEJS: 'nodejs'
3030
};
3131

3232
const { JOB_CI, FULL_CI } = CI_TYPE_ENUM;

lib/pr_checker.js

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class PRChecker {
204204
}
205205

206206
async checkCI() {
207-
const ciType = this.argv.ciType || CI_PROVIDERS.JENKINS;
207+
const ciType = this.argv.ciType || CI_PROVIDERS.NODEJS;
208208
const providers = Object.values(CI_PROVIDERS);
209209

210210
if (!providers.includes(ciType)) {
@@ -214,8 +214,8 @@ class PRChecker {
214214
}
215215

216216
let status = false;
217-
if (ciType === CI_PROVIDERS.JENKINS) {
218-
status = await this.checkJenkinsCI();
217+
if (ciType === CI_PROVIDERS.NODEJS) {
218+
status = await this.checkNodejsCI();
219219
} else if (ciType === CI_PROVIDERS.GITHUB) {
220220
status = this.checkGitHubCI();
221221
}
@@ -233,7 +233,7 @@ class PRChecker {
233233

234234
let status = true;
235235
if (!ciMap.size) {
236-
cli.error('No CI runs detected');
236+
cli.error('No Jenkins CI runs detected');
237237
this.CIStatus = false;
238238
return false;
239239
} else if (!this.hasFullCI(ciMap)) {
@@ -292,17 +292,61 @@ class PRChecker {
292292
cli.error(
293293
`${failures.length} failure(s) on the last Jenkins CI run`);
294294
status = false;
295+
// NOTE(mmarchini): not sure why PEDING returns null
296+
} else if (result === null) {
297+
cli.error(
298+
'Last Jenkins CI still running');
299+
status = false;
300+
} else {
301+
cli.ok('Last Jenkins CI successful');
295302
}
296303
}
297304

298305
this.CIStatus = status;
299306
return status;
300307
}
301308

309+
checkActionsCI() {
310+
const { cli, commits } = this;
311+
312+
if (!commits || commits.length === 0) {
313+
cli.error('No commits detected');
314+
return false;
315+
}
316+
317+
// NOTE(mmarchini): we only care about the last commit. Maybe in the future
318+
// we'll want to check all commits for a successful CI.
319+
const { commit } = commits[commits.length - 1];
320+
321+
this.CIStatus = false;
322+
const checkSuites = commit.checkSuites || { nodes: [] };
323+
if (!commit.status && checkSuites.nodes.length === 0) {
324+
cli.error('No GitHub CI runs detected');
325+
return false;
326+
}
327+
328+
// GitHub new Check API
329+
for (const { status, conclusion } of checkSuites.nodes) {
330+
if (status !== 'COMPLETED') {
331+
cli.error('GitHub CI is still running');
332+
return false;
333+
}
334+
335+
if (!['SUCCESS', 'NEUTRAL'].includes(conclusion)) {
336+
cli.error('Last GitHub CI failed');
337+
return false;
338+
}
339+
}
340+
341+
cli.ok('Last GitHub Actions successful');
342+
this.CIStatus = true;
343+
return true;
344+
}
345+
302346
checkGitHubCI() {
303347
const { cli, commits } = this;
304348

305-
if (!commits) {
349+
if (!commits || commits.length === 0) {
306350
cli.error('No commits detected');
307351
return false;
308352
}
@@ -314,7 +358,7 @@ class PRChecker {
314358
this.CIStatus = false;
315359
const checkSuites = commit.checkSuites || { nodes: [] };
316360
if (!commit.status && checkSuites.nodes.length === 0) {
317-
cli.error('No CI runs detected');
361+
cli.error('No GitHub CI runs detected');
318362
return false;
319363
}
320364

@@ -350,6 +394,33 @@ class PRChecker {
350394
return true;
351395
}
352396

397+
isOnlyDocChanges() {
398+
const { cli, pr } = this;
399+
400+
// NOTE(mmarchini): if files not present, fallback
401+
// to old behavior. This should only be the case on old tests
402+
// TODO(mmarchini): add files to all fixtures on old tests
403+
if (!pr.files) {
404+
return false;
405+
}
406+
407+
for (const { path } of pr.files.nodes) {
408+
if (!path.endsWith('.md')) {
409+
return false;
410+
}
411+
}
412+
cli.info('Doc-only changes');
413+
return true;
414+
}
415+
416+
async checkNodejsCI() {
417+
let status = this.checkActionsCI();
418+
if (!this.isOnlyDocChanges()) {
419+
status &= await this.checkJenkinsCI();
420+
}
421+
return status;
422+
}
423+
353424
checkAuthor() {
354425
const { cli, commits, pr } = this;
355426

lib/queries/PR.gql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ query PR($prid: Int!, $owner: String!, $repo: String!) {
1818
name
1919
}
2020
},
21+
files(first: 100) {
22+
nodes {
23+
path
24+
}
25+
},
2126
title,
2227
baseRefName,
2328
headRefName,

lib/session.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class Session {
9999
}
100100

101101
get ciType() {
102-
return this.config.ciType || 'jenkins';
102+
return this.config.ciType || 'nodejs';
103103
}
104104

105105
get pullName() {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
{
3+
"publishedAt": "2018-10-22T04:16:36.458Z",
4+
"bodyText": "CI: https://ci.nodejs.org/job/node-test-pull-request/15442/"
5+
}
6+
]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
{
3+
"publishedAt": "2018-10-22T04:16:36.458Z",
4+
"bodyText": "CI: https://ci.nodejs.org/job/node-test-pull-request/32777/"
5+
}
6+
]

test/fixtures/data.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ const approvingReviews = readJSON('reviews_approved.json');
3636
const requestingChangesReviews = readJSON('reviews_requesting_changes.json');
3737

3838
const commentsWithCI = readJSON('comments_with_ci.json');
39+
const commentsWithFailedCI = readJSON('comments_with_failed_ci.json');
3940
const commentsWithLGTM = readJSON('comments_with_lgtm.json');
41+
const commentsWithPendingCI = readJSON('comments_with_pending_ci.json');
4042

4143
const oddCommits = readJSON('odd_commits.json');
4244
const incorrectGitConfigCommits = readJSON('incorrect_git_config_commits.json');
@@ -99,6 +101,18 @@ for (const item of readdirSync(path('./github-ci'))) {
99101
githubCI[basename(item, '.json')] = readJSON(`./github-ci/${item}`);
100102
};
101103

104+
const jenkinsCI = {};
105+
106+
for (const subdir of readdirSync(path('./jenkins'))) {
107+
for (const item of readdirSync(path(`./jenkins/${subdir}`))) {
108+
if (!item.endsWith('.json')) {
109+
continue;
110+
}
111+
jenkinsCI[`${subdir}/${basename(item, '.json')}`] =
112+
readJSON(`./jenkins/${subdir}/${item}`);
113+
}
114+
};
115+
102116
module.exports = {
103117
approved,
104118
requestedChanges,
@@ -109,8 +123,11 @@ module.exports = {
109123
approvingReviews,
110124
requestingChangesReviews,
111125
commentsWithCI,
126+
commentsWithFailedCI,
112127
commentsWithLGTM,
128+
commentsWithPendingCI,
113129
oddCommits,
130+
jenkinsCI,
114131
githubCI,
115132
incorrectGitConfigCommits,
116133
simpleCommits,

0 commit comments

Comments
 (0)