HOME | EDIT | RSS | ARCHIVE | INDEX | ABOUT

what's wrong with Bamboo

if you used travis-ci on github, you may familiar with this thing when sending pull request

Screen-Shot-2015-02-17-at-4.19.12-PM.png

those green things came from github status api.

but bamboo does not come with native support for github status api

but here's some hack you can do to achieve similar thing travis does.

bamboo magic

there's thing in bamboo called custom build, which mean you can custom variable in bamboo's build.

you can simply trigger a custom build via GUI

Contracts---Condor-AWS--Plan-summary---Atlassian-Bamboo.png

or API

curl -XPOST -u name:password http://your.bamboo.domain/rest/api/latest/queue/:build-key?bamboo.variable.blah=blahblah

then the custom varibale is available via $bamboo_blah

and your build will also display a little bit different such as

Contracts---Condor-AWS-113--Build-result-summary---Atlassian-Bamboo.png

github webhook

now we can config github webhook say, ok, I'd like bamboo to be trigger whenever a pull request is opened.

with the hubot endpoint and variable we need

http://your.hubot.com/trigger-bamboo?bamboo=http://your.bamboo.com&buildKey=planBuildKey&room=optional-slack-channel

Screen-Shot-2015-02-13-at-11.35.29-AM.png

but what about the custom variables

bamboo need special form of variables, so we need something middleware to convert webhook payload from github…

I simply create a hubot and a very simple script1 to achieve that.

robot.router.post "/hubot/trigger-bamboo", (req, res) ->
    query = querystring.parse(url.parse(req.url).query)
    bamboo_url = query.bamboo
    build_key = query.buildKey
    room = query.room
    res.end "" if !bamboo_url || !room
    data = req.body
    eventType = req.headers["x-github-event"]
    console.log "Processing event type #{eventType}..."

    try
      if eventType in eventTypes
        robot.http("#{bamboo_url}/rest/api/latest/queue/#{build_key}?bamboo.variable.pull_sha=#{data.pull_request.head.sha}&bamboo.variable.pull_num=#{data.number}") (post-bamboo-api)
          .post()

you can easily install the script for you hubot

npm install hubot-bamboo-pr --save

andd add it to external-scripts.json file

[
  "hubot-something-else",
  + "hubot-bamboo-pr"
]

then point your github hook to hubot.

config Bamboo plan

We'd like only run the PR only in testing, and stop build after testing. imaging if your build originally looks like this:

  • testing
    • checkout code
    • run test
  • tagging
  • publish
  • deploy to Staging
  • deploy to Production

so here're things a PR build should look like:

  • testing
    • checkout code
    • checkout pull request code
    • run test
    • notify github status api
  • stop build when it's a PR build
  • tagging
  • publish
  • deploy to Staging
  • deploy to Production

so when build trigger by hubot with custom variables, ideally your build should look like:

Screen-Shot-2015-02-26-at-2.48.32-PM.png

some credentials you may need

  • $bamboo_GITHUB_STATUS_API_password

you need github status api token here there and everywhere

you can get a status api token from github GUI Setting > Applications > Generate new token

tick only repo:status for Status API purpose only and much more safer.

  • $bamboo_BAMBOO_password

you need bamboo password for stoping build, just create a share user with less permission

checkout PR code

#!/bin/bash
GITHUB_API=https://api.github.com
# if github enterprise https://your.github.domain/api/v3
if [[ -n ${bamboo_pull_num} ]]; then
  echo "== send pending status =="
  curl -H "Authorization: token $bamboo_GITHUB_STATUS_API_password" --request POST -k --data "{\"state\": \"pending\", \"description\": \"building...\", \"target_url\": \"$bamboo_resultsUrl\"}" https://$GITHUB_API/repos/the-money/condor/statuses/$bamboo_pull_sha > /dev/null  
  echo "git fetch PR $bamboo_pull_num =="
  git fetch ${bamboo.repository.git.repositoryUrl} +refs/pull/$bamboo_pull_num/merge:
  git checkout FETCH_HEAD
fi

notify github status

 1: #!/bin/bash
 2: STATUS=$?
 3: if [[ -n ${bamboo_pull_sha} ]]; then
 4:   if [ $STATUS != 0 ]; then
 5:     echo 'pull reqeust build failed'
 6:     curl -k -H "Authorization: token $bamboo_GITHUB_STATUS_API_password" --request POST --data "{\"state\": \"failure\", \"description\": \"failure:(\", \"target_url\": \"${bamboo.buildResultsUrl}\"}" $GITHUB_API/repos/:user/:repo/statuses/$bamboo_pull_sha > /dev/null
 7:   else
 8:     echo 'pull request build success'
 9:     curl -k -H "Authorization: token $bamboo_GITHUB_STATUS_API_password" --request POST --data "{\"state\": \"success\", \"description\": \"Success:)\", \"target_url\": \"${bamboo.buildResultsUrl}\"}" $GITHUB_API/repos/:user/:repo/statuses/$bamboo_pull_sha > /dev/null
10:   fi
11: fi

place checkout PR and notify github status script in this order

Contracts---Condor-AWS---Condor-Jasmine-Tests--Edit-job-configuration---Atlassian-Bamboo.png

stop build if PR

create new stage for stop build task

1: #!/bin/bash 
2: if [[ -n ${bamboo_pull_num} ]]; then
3:   echo 'stoping bamboo'
4:   curl "http://${bamboo_BAMBOO_USER}:${bamboo_BAMBOO_password}@your.bamboo.domain/build/admin/stopPlan.action?${bamboo.planResultKey}-${bamboo.buildNumber}"
5: fi

Footnotes:

1

checkout completed source code here https://gist.github.com/jcouyang/0201a80d4657b000cec7