TLDR; Use DRY_RUN
to understand what version the tag will be, do your build (passing the version through) and then set the tag at the end, assuming all builds have passed. If build fails, then the tag will not update (as the action won’t be hit).
Use concurrency
on the GitHub Action to make sure that only one build can happen at a time, preserving release order and preventing version mismatches.
Let’s imagine you are part of an organisation that is developing a dockerised Web App. The App is being tested locally within the organisation. Testers are giving feedback, but because you are such a fast moving DevOps organisation (right?) and are doing CD into production multiple times a day, you’re not sure what version of your application people are seeing.
Essentially you need to know what version of the web-app people are viewing when they are testing. Someone from the business, err let’s say Mr. B, says, “Hey, let’s show in big letters at the top of the web-page, the current version of the application!” in an unusually and suspiciously excited tone. Great, this sounds like a job for:
Auto-Tagging
What’s the problem? we are already automatically tagging our releases! See?
We are using the anotherNick/github-tag-action (great action by the way) to auto tag our releases. Every-time something is pushed to master we create a new release. Great. We can even empower our developers to bump versions themselves using commit messages (read more on the action’s page)!
“But how does the web-app know what version it is?” Mr. B asks. Well.. we could just auto-tag first and then pass that value into the build?
“But what if your build breaks?” asks Mr. B, whom you now suspect has some sort of dev experience. When we fix the build (eventually) we’d just jump a couple or few versions ahead, which is fine, but it’s probably a bit too hack-y for a soon-to-be production system.
Then you have another idea: What if we auto-tag at the end?. Mr. B laughs at your suggestion, knowing you’ve fallen right into his recursive trap “But how does the web-app know what version it is?”. You cannot set the version after you build the web-app, because the application has no clue what version it would be.
So, we need to do a bit of both:
Doing a Dry-Run with Auto-Tagging
This is where doing a dry-run comes in (using the same action as before).
If we pass the DRY_RUN: true
environment variable to the action we are telling it to process things like it normally would, but just don’t do the actual creation of the tag.
That means we can access the value that the tag will be, before we actually assign it.
So, we can Dry-Run the auto tagging. Pass that value into the build of our web-app (via env variables), and if all goes well we can actually do the increment at the end:
This Outputs:
The next tag version will be: v0.2.0
The current tag is: v0.1.0
The version increment was: minor
This solves our issue! But, you realise because your team releases so frequently, you often get 2 builds hitting master at the same time. This will cause;
Version Mismatches
If we take our code above and run it twice, there is a chance that 2 versions of our application will both show v0.2.0
even though one of them should actually be showing v0.3.0
.
The easy solution is to only allow one build to happen at a time, we can achieve this using the concurrency
flag within the GitHub Action.
We set a concurrency group, which in our case is set to: concurrency: production
. That means whenever this action is run multiple times, the first one will run, subsequent runs will sit waiting until it the first one completes, then run, one-by-one.
And that’s it! This will enable you to pass your version through to your app-build and then ensure your release tag version is the same.
Thanks for reading!