Skip to content

Commit 19175c0

Browse files
committed
feat: post CI results in PRs
Signed-off-by: avivkeller <me@aviv.sh>
1 parent 8133381 commit 19175c0

7 files changed

Lines changed: 8356 additions & 2581 deletions

File tree

lib/jenkins-ci-results.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Writable } from 'node:stream'
2+
3+
import CLI from 'node-core-utils/lib/cli.js'
4+
import Request from 'node-core-utils/lib/request.js'
5+
import { PRBuild } from 'node-core-utils/lib/ci/build-types/pr_build.js'
6+
7+
import { createPrComment } from './github-comment.js'
8+
9+
export function extractBuildNumber (build) {
10+
// e.g. https://ci.nodejs.org/job/node-test-pull-request/21633/
11+
const match = /\/job\/node-test-pull-request\/(\d+)/.exec(build.url || '')
12+
return match ? parseInt(match[1], 10) : null
13+
}
14+
15+
export async function fetchResultsMarkdown (buildNumber) {
16+
// node-core-utils insists on writing progress output to a stream
17+
const nullStream = new Writable({ write (chunk, encoding, callback) { callback() } })
18+
const cli = new CLI(nullStream)
19+
const request = new Request({
20+
jenkins: Buffer.from(process.env.JENKINS_API_CREDENTIALS).toString('base64')
21+
})
22+
23+
const prBuild = new PRBuild(cli, request, buildNumber)
24+
await prBuild.getResults()
25+
return prBuild.formatAsMarkdown()
26+
}
27+
28+
export async function postBuildResults (options, build, fetchResults = fetchResultsMarkdown) {
29+
const { pr } = options
30+
const buildNumber = extractBuildNumber(build)
31+
32+
const traceFields = { pr, job: build.identifier, gitRef: build.ref, buildNumber }
33+
const logger = options.logger.child(traceFields, true)
34+
35+
if (!process.env.JENKINS_API_CREDENTIALS) {
36+
logger.info('JENKINS_API_CREDENTIALS is not set, skipping CI results comment')
37+
return
38+
}
39+
40+
if (buildNumber === null) {
41+
logger.warn('Unable to find build number in build URL, skipping CI results comment')
42+
return
43+
}
44+
45+
const markdown = await fetchResults(buildNumber)
46+
47+
if (!markdown) {
48+
logger.warn('Got no CI results back from node-core-utils, skipping CI results comment')
49+
return
50+
}
51+
52+
await createPrComment({ issue_number: pr, ...options, logger }, markdown)
53+
logger.info('Jenkins CI results comment posted')
54+
}

lib/push-jenkins-update.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import githubClient from './github-client.js'
22
import { createPrComment } from './github-comment.js'
3+
import { postBuildResults } from './jenkins-ci-results.js'
34

45
export function pushStarted (options, build, cb) {
56
const pr = findPrInRef(build.ref)
@@ -54,6 +55,14 @@ export function pushEnded (options, build, cb) {
5455

5556
const optsWithPr = Object.assign({ pr }, options)
5657

58+
if (build.identifier === 'node-test-pull-request') {
59+
// fetching the CI results involves many Jenkins API calls, so let them
60+
// finish in the background instead of holding up the status update
61+
postBuildResults(optsWithPr, build).catch((err) => {
62+
logger.error(err, 'Error while posting Jenkins CI results')
63+
})
64+
}
65+
5766
findLatestCommitInPr(optsWithPr).then(latestCommit => {
5867
const statusOpts = Object.assign({
5968
sha: latestCommit.sha,

0 commit comments

Comments
 (0)