From 15f4b71d72f5ea6bef99386cbf5d7e99e1a70b43 Mon Sep 17 00:00:00 2001 From: Phillip Johnsen Date: Thu, 28 Apr 2016 21:55:16 +0200 Subject: [PATCH 1/7] First shot at polling Jenkins for PR/build status --- lib/poll-jenkins.js | 58 ++++++++++++++++++++++++++++++++++ package.json | 1 + scripts/node-jenkins-status.js | 19 +++++++++++ 3 files changed, 78 insertions(+) create mode 100644 lib/poll-jenkins.js create mode 100644 scripts/node-jenkins-status.js diff --git a/lib/poll-jenkins.js b/lib/poll-jenkins.js new file mode 100644 index 00000000..8b6c4f7f --- /dev/null +++ b/lib/poll-jenkins.js @@ -0,0 +1,58 @@ +'use strict' + +const request = require('request') + +const githubClient = require('./github-client') + +const sixtySeconds = 60 * 1000; + +function pollJenkins(options, checkNumber) { + const url = `https://ci.nodejs.org/job/node-test-pull-request/${options.prId}/api/json` + checkNumber = checkNumber || 1 + + request({ url, json: true }, (err, response, data) => { + const nextCheckNumber = checkNumber + 1 + + if (!err) { + const buildResult = data.result + + if (buildResult === 'SUCCESS') { + console.log(`* ${prInfoStr(options)} CI build was a success`) + return + } + } + + console.log(`* ${prInfoStr(options)} Build not finished yet, will do check #${checkNumber + 1} in one minute`) + + setTimeout(pollJenkins, sixtySeconds, prId, nextCheckNumber) + }) +} + +function createGhStatusFn (options) { + const prInfo = prInfoStr(options) + + return (state, travisId, message) => { + const buildUrl = `https://ci.nodejs.org/job/node-test-pull-request/${options.prId}` + + githubClient.statuses.create({ + user: options.owner, + repo: options.repoName, + sha: options.lastCommit.sha, + target_url: buildUrl, + context: 'Jenkins CI via nodejs-github-bot', + state: state, + description: message + }, (err, res) => { + if (err) { + return console.error(`! ${prInfo} Error while updating Jenkins / GitHub PR status`, err) + } + console.log(`* ${prInfo} Jenkins / Github PR status updated`) + }) + } +} + +function prInfoStr (options) { + return `nodejs/node/#${options.prId}` +} + +module.exports = pollJenkins diff --git a/package.json b/package.json index 82319046..7cf7adc8 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "express": "^4.13.4", "github": "^0.2.4", "glob": "^7.0.3", + "request": "^2.72.0", "travis-ci": "^2.1.0" }, "devDependencies": { diff --git a/scripts/node-jenkins-status.js b/scripts/node-jenkins-status.js new file mode 100644 index 00000000..f7b79391 --- /dev/null +++ b/scripts/node-jenkins-status.js @@ -0,0 +1,19 @@ +'use strict' + +const pollJenkins = require('../lib/poll-jenkins') + +module.exports = function (app) { + + // to trigger polling manually + app.get('/jenkins/:prId', (req, res) => { + const prId = req.params.prId + + pollJenkins({ + owner: 'nodejs', + repoName: 'node', + prId: parseInt(prId, 10) + }) + + res.end() + }) +} From 55e7fcb06ac7b3aa42ff2a7caa16adb5b43ffeca Mon Sep 17 00:00:00 2001 From: Phillip Johnsen Date: Mon, 2 May 2016 22:19:20 +0200 Subject: [PATCH 2/7] Handled errors and mapped more Jenkins build statuses -> GH statuses --- lib/poll-jenkins.js | 82 ++++++++++++++++++++++++++++------ scripts/node-jenkins-status.js | 1 - 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/lib/poll-jenkins.js b/lib/poll-jenkins.js index 8b6c4f7f..5df8da24 100644 --- a/lib/poll-jenkins.js +++ b/lib/poll-jenkins.js @@ -4,40 +4,88 @@ const request = require('request') const githubClient = require('./github-client') -const sixtySeconds = 60 * 1000; +const sixtySeconds = 60 * 1000 +const jenkinsToGhStatusMap = { + 'SUCCESS': { + state: 'success', + message: 'all tests passed' + }, + 'FAILURE': { + state: 'failure', + message: 'build failure' + }, + 'ABORTED': { + state: 'error', + message: 'build aborted' + }, + 'UNSTABLE': { + state: 'error', + message: 'build unstable' + } +} -function pollJenkins(options, checkNumber) { +/** + * NOTES TO SELF: + * + * Jenkins build could be matched by related PR by filtering on build parameters: + * request -> build.actions.find(parameters !== undefined).filter({ name: 'PR_ID' && value: }) + * example response: https://ci.nodejs.org/job/node-test-pull-request/2460/api/json + */ + +function pollJenkins (options, checkNumber) { const url = `https://ci.nodejs.org/job/node-test-pull-request/${options.prId}/api/json` checkNumber = checkNumber || 1 - request({ url, json: true }, (err, response, data) => { + // we should probably not poll forever .. lets stop after 420 polls (7 hours) + if (checkNumber >= 420) { + return console.warn(`* ${prInfoStr(options)} Wasn't able to a conclusive build result, stopping poll now :(`) + } + + request({ url, json: true }, (err, response, build) => { const nextCheckNumber = checkNumber + 1 - if (!err) { - const buildResult = data.result + if (err) { + console.error(`* ${prInfoStr(options)} Error when requesting Jenkins API, will do check #${checkNumber + 1} in one minute. Error: ${err}`) + return setTimeout(pollJenkins, sixtySeconds, options, nextCheckNumber) + } - if (buildResult === 'SUCCESS') { - console.log(`* ${prInfoStr(options)} CI build was a success`) - return - } + if (response.statusCode === 404) { + console.log(`* ${prInfoStr(options)} Jenkins build not found yet, will do check #${checkNumber + 1} in one minute`) + return setTimeout(pollJenkins, sixtySeconds, options, nextCheckNumber) } + // we should have enough data to push a github status update + const buildResult = build.result + const isFinished = buildResult !== null + const optsWithSha = extendWithLastCommitSha(options, build) + const createGhStatus = createGhStatusFn(optsWithSha) + + const matchedGhStatus = jenkinsToGhStatusMap[buildResult] + + if (matchedGhStatus) { + return createGhStatus(matchedGhStatus.state, matchedGhStatus.message) + } else if (isFinished) { + return console.error(`! ${prInfoStr(options)} Unknown Jenkins build result '${buildResult}', aborting poll for this PR`) + } + + // as build isn't finished yet, we'll have to keep polling Jenkins for new build status console.log(`* ${prInfoStr(options)} Build not finished yet, will do check #${checkNumber + 1} in one minute`) + createGhStatus('pending', 'build in progress') - setTimeout(pollJenkins, sixtySeconds, prId, nextCheckNumber) + setTimeout(pollJenkins, sixtySeconds, options, nextCheckNumber) }) } function createGhStatusFn (options) { const prInfo = prInfoStr(options) - return (state, travisId, message) => { + return (state, message) => { const buildUrl = `https://ci.nodejs.org/job/node-test-pull-request/${options.prId}` githubClient.statuses.create({ user: options.owner, repo: options.repoName, - sha: options.lastCommit.sha, + sha: options.sha, target_url: buildUrl, context: 'Jenkins CI via nodejs-github-bot', state: state, @@ -46,11 +94,19 @@ function createGhStatusFn (options) { if (err) { return console.error(`! ${prInfo} Error while updating Jenkins / GitHub PR status`, err) } - console.log(`* ${prInfo} Jenkins / Github PR status updated`) + console.log(`* ${prInfo} Jenkins / Github PR status updated to '${state}'`) }) } } +function extendWithLastCommitSha (options, build) { + const lastChangeSet = build.changeSet.items[0] + + return Object.assign({ + sha: lastChangeSet.commitId + }, options) +} + function prInfoStr (options) { return `nodejs/node/#${options.prId}` } diff --git a/scripts/node-jenkins-status.js b/scripts/node-jenkins-status.js index f7b79391..a3a6f2b9 100644 --- a/scripts/node-jenkins-status.js +++ b/scripts/node-jenkins-status.js @@ -3,7 +3,6 @@ const pollJenkins = require('../lib/poll-jenkins') module.exports = function (app) { - // to trigger polling manually app.get('/jenkins/:prId', (req, res) => { const prId = req.params.prId From 6bfdafa1b89a6738b91dbf9d108ef688f6476fd0 Mon Sep 17 00:00:00 2001 From: Phillip Johnsen Date: Sat, 7 May 2016 00:35:14 +0200 Subject: [PATCH 3/7] First shot at pushing GH update from Jenkins --- lib/poll-jenkins.js | 114 ---------------------------- lib/push-jenkins-update.js | 80 +++++++++++++++++++ package.json | 1 - scripts/node-jenkins-status.js | 16 ++-- test/_fixtures/error-payload.json | 12 +++ test/_fixtures/pending-payload.json | 12 +++ test/_fixtures/success-payload.json | 12 +++ 7 files changed, 122 insertions(+), 125 deletions(-) delete mode 100644 lib/poll-jenkins.js create mode 100644 lib/push-jenkins-update.js create mode 100644 test/_fixtures/error-payload.json create mode 100644 test/_fixtures/pending-payload.json create mode 100644 test/_fixtures/success-payload.json diff --git a/lib/poll-jenkins.js b/lib/poll-jenkins.js deleted file mode 100644 index 5df8da24..00000000 --- a/lib/poll-jenkins.js +++ /dev/null @@ -1,114 +0,0 @@ -'use strict' - -const request = require('request') - -const githubClient = require('./github-client') - -const sixtySeconds = 60 * 1000 -const jenkinsToGhStatusMap = { - 'SUCCESS': { - state: 'success', - message: 'all tests passed' - }, - 'FAILURE': { - state: 'failure', - message: 'build failure' - }, - 'ABORTED': { - state: 'error', - message: 'build aborted' - }, - 'UNSTABLE': { - state: 'error', - message: 'build unstable' - } -} - -/** - * NOTES TO SELF: - * - * Jenkins build could be matched by related PR by filtering on build parameters: - * request -> build.actions.find(parameters !== undefined).filter({ name: 'PR_ID' && value: }) - * example response: https://ci.nodejs.org/job/node-test-pull-request/2460/api/json - */ - -function pollJenkins (options, checkNumber) { - const url = `https://ci.nodejs.org/job/node-test-pull-request/${options.prId}/api/json` - checkNumber = checkNumber || 1 - - // we should probably not poll forever .. lets stop after 420 polls (7 hours) - if (checkNumber >= 420) { - return console.warn(`* ${prInfoStr(options)} Wasn't able to a conclusive build result, stopping poll now :(`) - } - - request({ url, json: true }, (err, response, build) => { - const nextCheckNumber = checkNumber + 1 - - if (err) { - console.error(`* ${prInfoStr(options)} Error when requesting Jenkins API, will do check #${checkNumber + 1} in one minute. Error: ${err}`) - return setTimeout(pollJenkins, sixtySeconds, options, nextCheckNumber) - } - - if (response.statusCode === 404) { - console.log(`* ${prInfoStr(options)} Jenkins build not found yet, will do check #${checkNumber + 1} in one minute`) - return setTimeout(pollJenkins, sixtySeconds, options, nextCheckNumber) - } - - // we should have enough data to push a github status update - const buildResult = build.result - const isFinished = buildResult !== null - const optsWithSha = extendWithLastCommitSha(options, build) - const createGhStatus = createGhStatusFn(optsWithSha) - - const matchedGhStatus = jenkinsToGhStatusMap[buildResult] - - if (matchedGhStatus) { - return createGhStatus(matchedGhStatus.state, matchedGhStatus.message) - } else if (isFinished) { - return console.error(`! ${prInfoStr(options)} Unknown Jenkins build result '${buildResult}', aborting poll for this PR`) - } - - // as build isn't finished yet, we'll have to keep polling Jenkins for new build status - console.log(`* ${prInfoStr(options)} Build not finished yet, will do check #${checkNumber + 1} in one minute`) - createGhStatus('pending', 'build in progress') - - setTimeout(pollJenkins, sixtySeconds, options, nextCheckNumber) - }) -} - -function createGhStatusFn (options) { - const prInfo = prInfoStr(options) - - return (state, message) => { - const buildUrl = `https://ci.nodejs.org/job/node-test-pull-request/${options.prId}` - - githubClient.statuses.create({ - user: options.owner, - repo: options.repoName, - sha: options.sha, - target_url: buildUrl, - context: 'Jenkins CI via nodejs-github-bot', - state: state, - description: message - }, (err, res) => { - if (err) { - return console.error(`! ${prInfo} Error while updating Jenkins / GitHub PR status`, err) - } - console.log(`* ${prInfo} Jenkins / Github PR status updated to '${state}'`) - }) - } -} - -function extendWithLastCommitSha (options, build) { - const lastChangeSet = build.changeSet.items[0] - - return Object.assign({ - sha: lastChangeSet.commitId - }, options) -} - -function prInfoStr (options) { - return `nodejs/node/#${options.prId}` -} - -module.exports = pollJenkins diff --git a/lib/push-jenkins-update.js b/lib/push-jenkins-update.js new file mode 100644 index 00000000..1767c4e3 --- /dev/null +++ b/lib/push-jenkins-update.js @@ -0,0 +1,80 @@ +'use strict' + +const githubClient = require('./github-client') + +const jenkinsToGhStatusMap = { + 'SUCCESS': { + state: 'success', + message: 'all tests passed' + }, + 'FAILURE': { + state: 'failure', + message: 'build failure' + }, + 'ABORTED': { + state: 'error', + message: 'build aborted' + }, + 'UNSTABLE': { + state: 'error', + message: 'build unstable' + } +} + +const rxDisplayName = /node\-test\-commit\-(\w+)/ + +function pushJenkinsUpdate (options, build) { + const statusOpts = extendWithBuildData(options, build) + const createGhStatus = createGhStatusFn(statusOpts) + const isPending = build.result === null + const matchedGhStatus = jenkinsToGhStatusMap[build.result] + + if (isPending) { + createGhStatus('pending', 'build in progress') + } else if (matchedGhStatus) { + createGhStatus(matchedGhStatus.state, matchedGhStatus.message) + } else { + console.error(`! ${prInfoStr(options)} Unknown Jenkins build result '${build.result}'`) + } +} + +function createGhStatusFn (options) { + const prInfo = prInfoStr(options) + + return (state, message) => { + githubClient.statuses.create({ + user: options.owner, + repo: options.repoName, + sha: options.sha, + target_url: options.url, + context: options.context, + state: state, + description: message + }, (err, res) => { + if (err) { + return console.error(`! ${prInfo} Error while updating Jenkins / GitHub PR status`, err) + } + console.log(`* ${prInfo} Jenkins / Github PR status updated to '${state}'`) + }) + } +} + +function extendWithBuildData (options, build) { + const lastChangeSet = build.changeSet.items[0] + + return Object.assign({ + sha: lastChangeSet.commitId, + url: build.url, + context: jobNameToStatusCtx(build.fullDisplayName) + }, options) +} + +function jobNameToStatusCtx (displayName) { + return rxDisplayName.exec(displayName)[1] +} + +function prInfoStr (options) { + return `${options.owner}/${options.repoName}` +} + +module.exports = pushJenkinsUpdate diff --git a/package.json b/package.json index 7cf7adc8..82319046 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "express": "^4.13.4", "github": "^0.2.4", "glob": "^7.0.3", - "request": "^2.72.0", "travis-ci": "^2.1.0" }, "devDependencies": { diff --git a/scripts/node-jenkins-status.js b/scripts/node-jenkins-status.js index a3a6f2b9..92e34347 100644 --- a/scripts/node-jenkins-status.js +++ b/scripts/node-jenkins-status.js @@ -1,17 +1,13 @@ 'use strict' -const pollJenkins = require('../lib/poll-jenkins') +const pushJenkinsUpdate = require('../lib/push-jenkins-update') module.exports = function (app) { - // to trigger polling manually - app.get('/jenkins/:prId', (req, res) => { - const prId = req.params.prId - - pollJenkins({ - owner: 'nodejs', - repoName: 'node', - prId: parseInt(prId, 10) - }) + app.post('/node/jenkins', (req, res) => { + pushJenkinsUpdate({ + owner: 'TestOrgPleaseIgnore', + repoName: 'node' + }, req.body) res.end() }) diff --git a/test/_fixtures/error-payload.json b/test/_fixtures/error-payload.json new file mode 100644 index 00000000..1164720f --- /dev/null +++ b/test/_fixtures/error-payload.json @@ -0,0 +1,12 @@ +{ + "fullDisplayName": "node-test-commit-arm #3087", + "result": "FAILURE", + "changeSet": { + "items": [ + { + "commitId": "7190bd23810f0880d95605bf6f785224a345d477" + } + ] + }, + "url": "https://ci.nodejs.org/job/node-test-commit-arm/3087/" +} \ No newline at end of file diff --git a/test/_fixtures/pending-payload.json b/test/_fixtures/pending-payload.json new file mode 100644 index 00000000..e7b53b13 --- /dev/null +++ b/test/_fixtures/pending-payload.json @@ -0,0 +1,12 @@ +{ + "fullDisplayName": "node-test-commit-linux #3176", + "result": null, + "changeSet": { + "items": [ + { + "commitId": "7190bd23810f0880d95605bf6f785224a345d477" + } + ] + }, + "url": "https://ci.nodejs.org/job/node-test-commit-linux/3176/" +} \ No newline at end of file diff --git a/test/_fixtures/success-payload.json b/test/_fixtures/success-payload.json new file mode 100644 index 00000000..e7b06262 --- /dev/null +++ b/test/_fixtures/success-payload.json @@ -0,0 +1,12 @@ +{ + "fullDisplayName": "node-test-commit-osx #3157", + "result": "SUCCESS", + "changeSet": { + "items": [ + { + "commitId": "7190bd23810f0880d95605bf6f785224a345d477" + } + ] + }, + "url": "https://ci.nodejs.org/job/node-test-commit-osx/3157/" +} \ No newline at end of file From 783220e5796fa5ac2d32e7af74057a766b63114c Mon Sep 17 00:00:00 2001 From: Phillip Johnsen Date: Mon, 9 May 2016 20:38:31 +0200 Subject: [PATCH 4/7] Simplified fixtures and deleted lots of code --- lib/push-jenkins-update.js | 41 +++-------------------------- test/_fixtures/error-payload.json | 15 ++++------- test/_fixtures/pending-payload.json | 15 ++++------- test/_fixtures/success-payload.json | 15 ++++------- 4 files changed, 18 insertions(+), 68 deletions(-) diff --git a/lib/push-jenkins-update.js b/lib/push-jenkins-update.js index 1767c4e3..d6fe6a38 100644 --- a/lib/push-jenkins-update.js +++ b/lib/push-jenkins-update.js @@ -2,40 +2,11 @@ const githubClient = require('./github-client') -const jenkinsToGhStatusMap = { - 'SUCCESS': { - state: 'success', - message: 'all tests passed' - }, - 'FAILURE': { - state: 'failure', - message: 'build failure' - }, - 'ABORTED': { - state: 'error', - message: 'build aborted' - }, - 'UNSTABLE': { - state: 'error', - message: 'build unstable' - } -} - -const rxDisplayName = /node\-test\-commit\-(\w+)/ - function pushJenkinsUpdate (options, build) { const statusOpts = extendWithBuildData(options, build) const createGhStatus = createGhStatusFn(statusOpts) - const isPending = build.result === null - const matchedGhStatus = jenkinsToGhStatusMap[build.result] - if (isPending) { - createGhStatus('pending', 'build in progress') - } else if (matchedGhStatus) { - createGhStatus(matchedGhStatus.state, matchedGhStatus.message) - } else { - console.error(`! ${prInfoStr(options)} Unknown Jenkins build result '${build.result}'`) - } + createGhStatus(build.status, build.message) } function createGhStatusFn (options) { @@ -60,19 +31,13 @@ function createGhStatusFn (options) { } function extendWithBuildData (options, build) { - const lastChangeSet = build.changeSet.items[0] - return Object.assign({ - sha: lastChangeSet.commitId, + sha: build.commit, url: build.url, - context: jobNameToStatusCtx(build.fullDisplayName) + context: build.identifier }, options) } -function jobNameToStatusCtx (displayName) { - return rxDisplayName.exec(displayName)[1] -} - function prInfoStr (options) { return `${options.owner}/${options.repoName}` } diff --git a/test/_fixtures/error-payload.json b/test/_fixtures/error-payload.json index 1164720f..e280f4be 100644 --- a/test/_fixtures/error-payload.json +++ b/test/_fixtures/error-payload.json @@ -1,12 +1,7 @@ { - "fullDisplayName": "node-test-commit-arm #3087", - "result": "FAILURE", - "changeSet": { - "items": [ - { - "commitId": "7190bd23810f0880d95605bf6f785224a345d477" - } - ] - }, + "identifier": "test/arm", + "status": "failure", + "message": "tests failed", + "commit": "8a5fec2a6bade91e544a30314d7cf21f8a200de1", "url": "https://ci.nodejs.org/job/node-test-commit-arm/3087/" -} \ No newline at end of file +} diff --git a/test/_fixtures/pending-payload.json b/test/_fixtures/pending-payload.json index e7b53b13..2f9600f7 100644 --- a/test/_fixtures/pending-payload.json +++ b/test/_fixtures/pending-payload.json @@ -1,12 +1,7 @@ { - "fullDisplayName": "node-test-commit-linux #3176", - "result": null, - "changeSet": { - "items": [ - { - "commitId": "7190bd23810f0880d95605bf6f785224a345d477" - } - ] - }, + "identifier": "test/linux", + "status": "pending", + "message": "checking for errors", + "commit": "8a5fec2a6bade91e544a30314d7cf21f8a200de1", "url": "https://ci.nodejs.org/job/node-test-commit-linux/3176/" -} \ No newline at end of file +} diff --git a/test/_fixtures/success-payload.json b/test/_fixtures/success-payload.json index e7b06262..d4a2d355 100644 --- a/test/_fixtures/success-payload.json +++ b/test/_fixtures/success-payload.json @@ -1,12 +1,7 @@ { - "fullDisplayName": "node-test-commit-osx #3157", - "result": "SUCCESS", - "changeSet": { - "items": [ - { - "commitId": "7190bd23810f0880d95605bf6f785224a345d477" - } - ] - }, + "identifier": "test/osx", + "status": "success", + "message": "tests passed", + "commit": "8a5fec2a6bade91e544a30314d7cf21f8a200de1", "url": "https://ci.nodejs.org/job/node-test-commit-osx/3157/" -} \ No newline at end of file +} From 77f373437c09c9480a5bfd6b6829ecf723627260 Mon Sep 17 00:00:00 2001 From: Phillip Johnsen Date: Tue, 10 May 2016 15:57:37 +0200 Subject: [PATCH 5/7] Push updates to nodejs/node --- scripts/node-jenkins-status.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/node-jenkins-status.js b/scripts/node-jenkins-status.js index 92e34347..7202cf27 100644 --- a/scripts/node-jenkins-status.js +++ b/scripts/node-jenkins-status.js @@ -5,7 +5,7 @@ const pushJenkinsUpdate = require('../lib/push-jenkins-update') module.exports = function (app) { app.post('/node/jenkins', (req, res) => { pushJenkinsUpdate({ - owner: 'TestOrgPleaseIgnore', + owner: 'nodejs', repoName: 'node' }, req.body) From 7760e69a62a8b05d3b73e5de2f1ee5afeb967f31 Mon Sep 17 00:00:00 2001 From: Phillip Johnsen Date: Tue, 10 May 2016 16:32:54 +0200 Subject: [PATCH 6/7] Print commit sha when logging --- lib/push-jenkins-update.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/push-jenkins-update.js b/lib/push-jenkins-update.js index d6fe6a38..a29205b6 100644 --- a/lib/push-jenkins-update.js +++ b/lib/push-jenkins-update.js @@ -39,7 +39,8 @@ function extendWithBuildData (options, build) { } function prInfoStr (options) { - return `${options.owner}/${options.repoName}` + const shortSha = options.sha.substr(0, 7) + return `${options.owner}/${options.repoName}/${shortSha}` } module.exports = pushJenkinsUpdate From 41a8208269bfb4b23f2d82074018b6bfe4432e7f Mon Sep 17 00:00:00 2001 From: Phillip Johnsen Date: Tue, 10 May 2016 21:14:32 +0200 Subject: [PATCH 7/7] Added a couple of tests --- package.json | 2 ++ scripts/node-jenkins-status.js | 2 +- test/push-jenkins-update.test.js | 62 ++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 test/push-jenkins-update.test.js diff --git a/package.json b/package.json index b6ed255c..c1e6cc35 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,11 @@ }, "devDependencies": { "eventsource": "^0.2.1", + "nock": "^8.0.0", "nodemon": "^1.9.1", "request": "^2.72.0", "standard": "^6.0.7", + "supertest": "^1.2.0", "tap": "^5.7.1" } } diff --git a/scripts/node-jenkins-status.js b/scripts/node-jenkins-status.js index 7202cf27..c5be6949 100644 --- a/scripts/node-jenkins-status.js +++ b/scripts/node-jenkins-status.js @@ -9,6 +9,6 @@ module.exports = function (app) { repoName: 'node' }, req.body) - res.end() + res.status(201).end() }) } diff --git a/test/push-jenkins-update.test.js b/test/push-jenkins-update.test.js new file mode 100644 index 00000000..b9639268 --- /dev/null +++ b/test/push-jenkins-update.test.js @@ -0,0 +1,62 @@ +'use strict' + +const tap = require('tap') +const fs = require('fs') +const path = require('path') +const url = require('url') +const nock = require('nock') +const supertest = require('supertest') + +const app = require('../app') + +tap.test('Sends POST requests to https://api.github.com/repos/nodejs/node/statuses/', (t) => { + const fixture = readFixture('success-payload.json') + const scope = nock('https://api.github.com') + .filteringPath(ignoreQueryParams) + .post('/repos/nodejs/node/statuses/8a5fec2a6bade91e544a30314d7cf21f8a200de1') + .reply(201) + + t.plan(1) + t.tearDown(() => scope.done()) + + supertest(app) + .post('/node/jenkins') + .send(fixture) + .expect(201) + .end((err, res) => { + t.equal(err, null) + }) +}) + +tap.test('Forwards payload provided in incoming POST to GitHub status API', (t) => { + const fixture = readFixture('success-payload.json') + const scope = nock('https://api.github.com') + .filteringPath(ignoreQueryParams) + .post('/repos/nodejs/node/statuses/8a5fec2a6bade91e544a30314d7cf21f8a200de1', { + state: 'success', + context: 'test/osx', + description: 'tests passed', + target_url: 'https://ci.nodejs.org/job/node-test-commit-osx/3157/' + }) + .reply(201) + + t.plan(1) + t.tearDown(() => scope.done()) + + supertest(app) + .post('/node/jenkins') + .send(fixture) + .expect(201) + .end((err, res) => { + t.equal(err, null) + }) +}) + +function ignoreQueryParams (pathAndQuery) { + return url.parse(pathAndQuery, true).pathname +} + +function readFixture (fixtureName) { + const content = fs.readFileSync(path.join(__dirname, '_fixtures', fixtureName)).toString() + return JSON.parse(content) +}