Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Automated Jenkins Comments on GitHub Pull Requests

View Procfile

Configure the post-build hook and launch it on Heroku:

$ git clone git://gist.github.com/1911084.git jenkins-comments
$ cd jenkins-comments
$ heroku create --stack cedar
$ heroku config:add NODE_ENV=production
$ heroku config:add GITHUB_USER_LOGIN=...
$ heroku config:add GITHUB_USER_PASSWORD=...
$ heroku config:add JENKINS_URL=...
$ git push heroku master
$ heroku ps:scale web=1

Then configure your Jenkins job to call the post-build hook to report job status:

$ curl "http://your.herokuapp.com/jenkins/post_build?\
    user=$GITHUB_USER\
    &repo=$GITHUB_REPO\
    &sha=$GIT_COMMIT\
    &status=$BUILD_STATUS\
    &job=$BUILD_NUMBER"

You'll have to specify GITHUB_USER, GITHUB_REPO, and your build should set BUILD_STATUS=success if the build succeeded.

View Procfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
async = require 'async'
request = require 'request'
express = require 'express'
_ = require 'underscore'
_s = require 'underscore.string'
 
class PullRequestCommenter
BUILDREPORT = "**Build Status**:"
 
constructor: (@sha, @job, @user, @repo, @succeeded) ->
@job_url = "#{process.env.JENKINS_URL}/job/#{@repo}/#{@job}"
@api = "https://#{process.env.GITHUB_USER_LOGIN}:#{process.env.GITHUB_USER_PASSWORD}@api.github.com/#{@user}/#{@repo}"
 
post: (path, obj, cb) =>
request.post { uri: "#{@api}#{path}", json: obj }, (e, r, body) ->
cb e, body
 
get: (path, cb) =>
request.get { uri: "#{@api}#{path}", json: true }, (e, r, body) ->
cb e, body
 
del: (path, cb) =>
request.del { uri: "#{@api}#{path}" }, (e, r, body) ->
cb e, body
 
getCommentsForIssue: (issue, cb) =>
@get "/issues/#{issue}/comments", cb
 
deleteComment: (id, cb) =>
@del "/issues/comments/#{id}", cb
 
getPulls: (cb) =>
@get "/pulls", cb
 
getPull: (id, cb) =>
@get "/pulls/#{id}", cb
 
commentOnIssue: (issue, comment) =>
@post "/repos/#{@user}/#{@repo}/issues/#{issue}/comments", (body: comment), (e, body) ->
console.log e if e?
 
successComment: ->
"#{BUILDREPORT} `Succeeded` (#{@sha}, [job info](#{@job_url}))"
 
errorComment: ->
"#{BUILDREPORT} `Failed` (#{@sha}, [job info](#{@job_url}))"
 
# Find the first open pull with a matching HEAD sha
findMatchingPull: (pulls, cb) =>
pulls = _.filter pulls, (p) => p.state is 'open'
async.detect pulls, (pull, detect_if) =>
@getPull pull.number, (e, { head }) =>
return cb e if e?
detect_if head.sha is @sha
, (match) =>
return cb "No pull request for #{@sha} found" unless match?
cb null, match
 
removePreviousPullComments: (pull, cb) =>
@getCommentsForIssue pull.number, (e, comments) =>
return cb e if e?
old_comments = _.filter comments, ({ body }) -> _s.include body, BUILDREPORT
async.forEach old_comments, (comment, done_delete) =>
@deleteComment comment.id, done_delete
, () -> cb null, pull
 
makePullComment: (pull, cb) =>
comment = if @succeeded then @successComment() else @errorComment()
@commentOnIssue pull.number, comment
cb()
 
updateComments: (cb) ->
async.waterfall [
@getPulls
@findMatchingPull
@removePreviousPullComments
@makePullComment
], cb
 
app = module.exports = express.createServer()
 
app.configure 'development', ->
app.set "port", 3000
 
app.configure 'production', ->
app.use express.errorHandler()
app.set "port", parseInt process.env.PORT
 
# Jenkins lets us know when a build has failed or succeeded.
app.get '/jenkins/post_build', (req, res) ->
sha = req.param 'sha'
job = parseInt req.param 'job'
user = req.param 'user'
repo = req.param 'repo'
succeeded = req.param('status') is 'success'
 
# Look for an open pull request with this SHA and make comments.
commenter = new PullRequestCommenter sha, job, user, repo, succeeded
commenter.updateComments (e, r) -> console.log e if e?
res.send 'Ok', 200
 
app.listen app.settings.port
View Procfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14
{
"name": "jenkins-pull-request-commenter"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.7"
, "jade": ">= 0.0.1"
, "coffee-script": "1.2.x"
, "underscore": "*"
, "underscore.string": "*"
, "request": "*"
, "async": "*"
}
}
View Procfile
1 2
require('coffee-script');
require('./app');

We modified this to store Jenkins' results in Redis and insta-comment when a pull is opened if you're interested: https://github.com/cramerdev/jenkins-comments

Owner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.