From d1bfac2ad05e47e2d2450798e70bc1f6f3fe26a0 Mon Sep 17 00:00:00 2001 From: Mary Marchini Date: Sun, 2 Aug 2020 16:27:18 -0700 Subject: [PATCH 1/2] feat: relay jenkins events to github actions These changes are meant to allow us to write GitHub Actions in selected repositories in the nodejs github organization, as a reaction to Jenkins events. It works by dispatching repository events, which we can use as triggers for GitHub Action workflows. Here's a concrete repository dispatch event caused by the Jenkins job `node-test-commit-osx`: ``` event_type: jenkins.node-test-commit-osx.start or jenkins.node-test-commit-osx.end client_payload: { "identifier": "node-test-commit-osx", "status": "success", "message": "tests passed", "commit": "8a5fec2a6bade91e544a30314d7cf21f8a200de1", "url": "https://ci.nodejs.org/job/node-test-commit/3157/", "ref": "refs/pull/12345/head" } ``` Refs: - https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#repository_dispatch - https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#create-a-repository-dispatch-event --- lib/jenkins-events.js | 5 ++++- scripts/event-relay.js | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 scripts/event-relay.js diff --git a/lib/jenkins-events.js b/lib/jenkins-events.js index d46991c8..a57cff19 100644 --- a/lib/jenkins-events.js +++ b/lib/jenkins-events.js @@ -3,7 +3,9 @@ const pushJenkinsUpdate = require('../lib/push-jenkins-update') const debug = require('debug')('jenkins-events') -const enabledRepos = ['citgm', 'http-parser', 'node', 'node-auto-test'] +const enabledRepos = process.env.JENKINS_ENABLED_REPOS + ? process.env.JENKINS_ENABLED_REPOS.split(',') + : ['citgm', 'http-parser', 'node', 'node-auto-test'] const listOfKnownJenkinsIps = process.env.JENKINS_WORKER_IPS ? process.env.JENKINS_WORKER_IPS.split(',') : [] @@ -74,6 +76,7 @@ module.exports = (app, events) => { data.logger.info('Emitting Jenkins event') debug(data) + events.emit(`jenkins`, data) return events.emit(`jenkins.${event}`, data) } } diff --git a/scripts/event-relay.js b/scripts/event-relay.js new file mode 100644 index 00000000..d8986cc4 --- /dev/null +++ b/scripts/event-relay.js @@ -0,0 +1,25 @@ +'use strict' + +const githubClient = require('../lib/github-client') + +async function handleJenkinsRelay (event) { + const { owner, repo, identifier } = event + const eventType = `jenkins.${identifier}.${event.event}` + try { + event.logger.debug(`Relaying ${eventType} to ${owner}/${repo}`) + await githubClient.repos.createDispatchEvent({ + owner, + repo, + event_type: eventType, + client_payload: event + }) + return true + } catch (err) { + event.logger.error(err, `Failed to relay ${eventType} to ${owner}/${repo}`) + return false + } +} + +module.exports = function (_, event) { + event.on('jenkins', handleJenkinsRelay) +} From 3ef74ac5fb7c5029fbede0f177d676d2f3983c17 Mon Sep 17 00:00:00 2001 From: Phillip Johnsen Date: Sun, 29 Nov 2020 21:05:44 +0100 Subject: [PATCH 2/2] test: verify jenkins event gets relayed as repository event --- .../event-relay-to-github-actions.test.js | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 test/integration/event-relay-to-github-actions.test.js diff --git a/test/integration/event-relay-to-github-actions.test.js b/test/integration/event-relay-to-github-actions.test.js new file mode 100644 index 00000000..ce69a750 --- /dev/null +++ b/test/integration/event-relay-to-github-actions.test.js @@ -0,0 +1,38 @@ +'use strict' + +const tap = require('tap') +const url = require('url') +const nock = require('nock') +const supertest = require('supertest') + +const { app, events } = require('../../app') + +const readFixture = require('../read-fixture') + +require('../../scripts/event-relay')(app, events) + +tap.test('Sends POST requests to https://api.github.com/repos/nodejs//dispatches', (t) => { + const jenkinsPayload = readFixture('success-payload.json') + + nock('https://api.github.com') + .filteringPath(ignoreQueryParams) + .post('/repos/nodejs/node/dispatches') + .reply(204) + .on('replied', (req, interceptor) => { + t.doesNotThrow(() => interceptor.scope.done()) + }) + + t.plan(2) + + supertest(app) + .post('/node/jenkins/start') + .send(jenkinsPayload) + .expect(200) + .end((err, res) => { + t.equal(err, null) + }) +}) + +function ignoreQueryParams (pathAndQuery) { + return url.parse(pathAndQuery, true).pathname +}