Increment project version from Travis
Warning: Please consider that this post is over 7 years old and the content may no longer be relevant.
Can you effectively use GitHub and Travis for continuous delivery? You sure can, but managing the version number can be difficult, here’s a way to automatically increment the patch number on every deployment from Travis.
We use a shared repository model for our JavaScript project on GitHub, the workflow goes something like this:
- The
master
branch is always the currently deployed production code - When someone wants to add a new feature or fix a bug, they create a branch (both locally and on GitHub)
- Travis builds all commits to all branches and runs the continuous integration test suite
- Once development is complete and tests pass they open a Pull Request
- Once someone has approved the Pull Request (we love the new functionality - thanks GitHub!), they then merge and squash onto
master
- Travis builds all commits onto the
master
branch, if tests pass it deploys the package to a private npm repository and deploys the artefacts to S3
The trick is that the version number in the package.json
file must be updated on every commit to master otherwise npm will reject it (rightly so). We used to manually update this before merging the Pull Request by doing an npm version patch
, but people forget to do this or they do it too early and get merge conflicts.
We now automate incrementing the version by using git tags. Before Travis builds the project, it pulls the latest git tag, then compares the major and minor version (x.x.0) to what’s in package.json
. If they match it increments the patch version (0.0.x) and creates a new git tag and updates the package.json file, if they don’t match we assume the developer has incremented either the minor or major version and so it resets the patch number to 0. At the end of a successful build on the master branch, the tag is pushed back to GitHub. This ensures a nice history of every commit on master having a git tag of the version number, which supports our continuous delivery workflow.
Here’s the relevant .travis.yaml
entries to make this work:
Let’s decompose that bash one-liner:
-
Read the current major and minor version from package.json (e.g.
1.2
)sed -nE 's/^[ \\t]*"version": "([0-9]{1,}\\.[0-9]{1,}\\.)[0-9x]{1,}",$/\\1/p' package.json;
-
Get the latest git tag (e.g.
v1.2.43
)git describe --abbrev=0
-
Split out the major and minor version and the patch version into separate parts (e.g.
1.2 43
)sed -E 's/^v([0-9]{1,}\\.[0-9]{1,}\\.)([0-9]{1,})$/\\1 \\2/g';
-
Take the output of 1. and 2. and create 3 space separated parts which are (in order)
<major.minor from package.json> <major.minor from git tag> <patch from git tag>
tr "\\n" " "
-
If part 1 and 2 match, just increment the patch version, otherwise use major.minor from package.json and reset patch to 0.
awk '{printf($1==$2?"v"$2$3+1:"v"$1"0")}'
-
Pipe the resulting version number into a git tag (e.g.
v1.2.44
)xargs -I {} git tag -a {} -m "{}"