Managing releases with tags in github flow
6 December, 2022
I develop and release open source software for Boavizta.org (e.g. GitHub - Boavizta/cloud-scanner: 📡 Get Boavizta impact data for your aws cloud account usage. ).
In this context, my preferred git flow model is an adaptation of the"github flow" which is mainly trunk based development. However this flow rises the question of how to identify a given release in time or retrieve a published artefact easily (pinning versions in docker compose for example).
This article describe the workflow that I put in place, which I expect to be:
- simple enough to be easy to grasp (and easy to mostly automate)
- but still allow to publish correctives or pre-versions.
General principle
I use main
branch to maintain the latest published release (minor changes) but rather use a dev
branch to prepare the future major version (that may include breaking changes).
- develop new things (or fix) on feature branches
- use the
main
branch to represent latest release software (plus eventual minor bug fixes) - use
dev
branch to prepare next major release and publish release candidates (i.e. alpha versions). - merge to the
main
branch (using PR mechanism to discuss before a merge) when a fix or the next release is ready.
Not sure about the name but it seems to be a variation of the Github flow.
Using tags
In case of software we like to version things using semver conventions. It gives explicit semantic versioning to the content of the release.
The idea is to tag the software we intend to deliver with a specific version number. In practice, after the software is merge to main branch we tag the specif commit with a release tag representing the version (like 1.2.3 or 1.2.4-alpha.0).
This can be done manually in git .
Or using the release mechanism of github: Github releases
Tagging strategy:
- We tag with a version number on
main
branch to delivering a public release. - We tag with version number on the
dev
branch (for future, alpha versions).
Limitations
We can only easily produce correctives for the published branch (i.e. fixes are always based on main
).
Publishing artifacts
We need to be able to access a previously published version of a given artifact (like a docker image) but also pre-release version (like 1.2.3-alpha.1) for testing purposes. So we reuse the tags and branches to explicitly name our artifacts.
Docker images
We use CI (github actions or gitlab ci) to automatically build and publish the docker image and tag the image with the version number (retrieved from the git tag).
Docker tagging strategy
- A tag is pushed on
main
branch:- build the main branch
- tag docker image with
latest
+version
(tag number)
- A tag is pushed on
dev
branch:- build on dev branch
- tag docker image with
dev
+version
(which should be something like x.x.x-alpha.x)
crates or other packages
When publishing packages (using crates for Rust or npm for JS), we rely on the version number that is set inside the package meta description (cargo.toml for Rust).
This involves a manual step (we need to remember to increment the package number before publishing it) but the logic is similar to the docker tagging strategy in CI.
How to publish a fix
- Start a dedicated branch (starting from the latest released version from
main
) - develop the fix
- increment version number in the package (generally a minor increment).
- open PR to main
- After merging, tag the main branch (or use github release mechanism) to trigger publication of the artifact.
This model makes correcting an old version difficult after the next major release has been published (it is harder to automate in CI), but this seems OK for the projects where I'am using it.