About Archives

Bump version after a green build


The problem

After each green build in Bamboo, you create a new image with the contents of your application and push it to Docker Hub, simple enough.

You then decide to improve it and instead of using the tag latest (because it’s wrong),
you tag each one of your Docker Images using a different tag.
For example, you can use the ${bamboo.buildResultKey} to make sure you have something unique (more info about Bamboo variables).

This way, your Docker Image tags will look something like this:

But that doesn’t make much sense does it? I mean, wouldn’t it be better to say “Please pull the image 2.2.1 which has the bugfix you requested” instead of “Please pull PRJ-BACK-MJ-138”.

Additionally, it would be nice to have the repository commits tagged with the version so we can easily navigate them.

The solution

package.json has a property called version which is intended to do this, why not use it?
Not only that, npm has a command called version which bumps, tags and commits automatically.
You can then extract that version # and use it to tag the Docker Images.

Repository config

You will need to make a small modification to your Repositories tab, under Advanced Options -> Exclude changesets please write ^(\[AUTO\]).*$.

This is to avoid infinite build loops, since after each successful build Bamboo will make a new push to the repository which in turn will trigger another build and so on...

If your app is in the root of the repository:

You will need to add 6 tasks, thankfully it is really simple to do.

Add a new task “Prepare environment” of type Script, with these contents:

git config --global user.email "your@emailgoeshere.com"
git config --global user.name "Bamboo Updater"
git config --global push.default matching

The second task will bump the version. To do this, please add a new Docker task called “Bump version”

Command: Run a Docker container
Docker image: node:latest
Container command: /bin/bash -c 'npm version patch -m "[AUTO] Bumped version to %s" && chmod 777 -R .git'
Volumes: Please mount /home/bamboo/.gitconfig to /root/.gitconfig

The third Docker task “Extract package.json version to version.txt” will do exactly as called.

Command: Run a Docker container
Docker image: node:latest
Container command: node -e "var data = require('./package.json'); var fs = require('fs'); fs.writeFileSync('version.txt',data.version);"

The fourth task “Docker push” is of type Script

export APPVERSION=$(cat version.txt)
echo "App version is $APPVERSION"
cat tmp.txt | awk '/Successfully built/{print $NF}' > tmp2.txt
IMAGE_ID=`cat tmp2.txt`
echo "===============================> The image ID is $IMAGE_ID"
rm -f tmp.txt tmp2.txt version.txt

I know it looks horrible, but I had to redirect the output of docker build to a file then `awk` it because Bamboo wouldn't allow me to use the `-q` flag. It just didn't output anything... too bad.

The fifth script task is called “Push to repo”

git remote rm origin
git remote add origin https://username:password@bitbucket.org/repouser/reponame
git push --set-upstream origin master
git push --tags

The last task (of Docker type) goes in the “Final” section

Command: Run a Docker container
Docker image: node:latest
Container command: chmod -R 777 .git

When you use Docker to touch files, it likes to chown files to root, but since Bamboo uses the bamboo user, if you retry the build it will break because of permissions error.
By executing the task above in all the builds (green and red) we make sure that it will always be able to run.

If your app is in a subfolder of the repository:

Assuming your subfolder is called app, it’s basically the same steps as above with minor changes:

  1. Prepare environment task: Add cd app at the end of the script
  2. Bump version task: Change command to /bin/bash -c 'cp app/package.json . && npm --no-git-tag-version version patch && mv package.json app && git add app/package.json && chmod 777 -R .git'
  3. Extract package.json version to version.txt task: Change the container working directory to your subfolder
  4. Docker push task: Change the 2nd line of the bash script to export APPVERSION=$(cat app/version.txt). DO NOT rm version.txt as you will use it on the next task.
  5. Push to repo task: Change the 4th line of the bash script to export APPVERSION=$(cat app/version.txt)

Nice, but what about Frontend (bower) repos?

bower also has a version command. Simply change npm for bower and you will get the same results!.

The final result

Docker hub now looks like this:

Bitbucket repo looks like this:

And the commit is simple enough:

Your build pipeline will definitely improve after implementing this!.