Skip to content

Instantly share code, notes, and snippets.

@dvdsgl
Created February 25, 2012 21:58
Show Gist options
  • Select an option

  • Save dvdsgl/1911084 to your computer and use it in GitHub Desktop.

Select an option

Save dvdsgl/1911084 to your computer and use it in GitHub Desktop.
Automated Jenkins Comments on GitHub Pull Requests

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.

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
{
"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": "*"
}
}
web: node server.js
require('coffee-script');
require('./app');
@justincampbell
Copy link
Copy Markdown

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

@dvdsgl
Copy link
Copy Markdown
Author

dvdsgl commented Apr 30, 2012 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment