Auto Tagging and using Semantic Versioning with GitHub Actions

Aran
3 min readMar 10, 2022
Photo by Oskar Yildiz on Unsplash

In this post we are going to cover:

  • How to Auto-Tag
  • How to Dry-Run a version
  • How do we stop mismatched versions?

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?

Example yaml GitHub Action using anotherNick/github-tag-action on push to the ‘main’ branch

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).

Note the ‘DRY_RUN: true’ at the end

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.

Note ‘concurrency: production` on line 6 — this is set at workflow level

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!

--

--

Aran

Cloud Solution Architect at Slalom Build (UK)