sver: Easy semantic versioning of your artifacts
Sep 7th, 2021
Vlad Iovanov
Engineering
As we all know, software versioning is super important. At Aserto, we mostly deal with go binaries and container images. We knew that we wanted to use semver as a strategy from the start, but we couldn’t find a solution with the right features for us. We looked at a few options, including great projects such as svu, git-semver, semantic-release, and goreleaser.
These didn’t work out, because they either prescribe a workflow that we didn’t want to adopt, or the versions they generate are not unique. None of them help with versioning container images.
We ended up creating our own so we could generate semantic versions that are unique, reproducible and sortable for each individual commit. Generated versions don’t collide between different commits.
In a nutshell, sver
reads your git repo for a tag, then calculates a version for you. If you’re on a tag, it will print that tag. If you’re not on a tag (you have some commits on top of a tag), it will create a version based on the last commit and the number of commits since the last tag.
We also detect if your repo is dirty so we can add a -dirty
pre-release identifier.
You can read more about this in the project’s README.
Installing
If you have Golang installed, you can get sver
with the following command:
$ go install github.com/aserto-dev/sver/cmd/sver@latest
For brew users:
$ brew tap aserto-dev/tap
$ brew install aserto-dev/tap/sver
Getting your current version
Let’s play with the sver
repository itself. You can clone it from github:
$ git clone git@github.com:aserto-dev/sver.git
$ cd sver
Now, we can run sver
and easily obtain the current version:
$ sver
1.3.2
Your current version is interesting, but so is the next. You can calculate it by using the -n
flag. You tell it which piece of the semver to bump — patch
, minor
, major
.
$ sver -n patch
1.3.3
$ sver -n minor
1.4.0
$ sver -n major
2.0.0
Docker image tagging
As I alluded to earlier, another thing that sver
can do is figure out how you should tag your docker image, which can sometimes be cumbersome to figure out.
When someone consumes an image, they sometimes use latest
to pull. But that’s not always best practice. You typically want to be specific about what versions you consume, because APIs change. This is the whole point of semantic versioning.
But you also don’t want to manually babysit upgrades. You likely want to pick a version, and receive bug-fixes for it without worrying too much about it. This means you want to tell your container runtime to pull a version that looks like x.y.*
or x.*
.
sver
helps you tag your images so such a thing becomes easy, and you don’t have to worry about it again.
Continuing with our example of looking at sver
itself, we can look at the proposed set of tags for sver
's next tagged container release:
$ sver tags -s ghcr.io aserto-dev/sver -u ogazitt -p <PAT>
1.3.2
1.3
1
latest
1.3.2
— your new version
1.3
— because it’s the latest in the 1.3.* series
1
— because it’s the latest in the 1.* series
latest
— because there’s no other version that’s higher
Now let’s say customer X uses version 0.1.0
, and they’ve found a bug. So you prepare a patch, and create tag 0.1.1
. When you ask sver
what the docker tags for your image should be, it will say:
0.1.1
— your new version
0.1
— because it’s the latest in the 0.1.* series
0
— because it’s the latest in the 0.* series
It’s not outputting latest
because 1.3.2
is higher than 0.1.1
.
Github action
We also maintain a github action for your convenience. You can use it in your workflows to determine your current version (including image tags) so you can build your artifacts.
You can also automatically calculate a next version if you want to automatically tag your repo when something happens.
Here’s an example of how we use sver
in a Github workflow for one of our repositories:
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Login to GitHub Packages Docker Registry
uses: docker/login-action@v1
with:
registry: https://ghcr.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Calculate Tags
id: "calc_tags"
uses: aserto-dev/sver-action@v0.0.13
with:
docker_image: "aserto-dev/aserto-console-backend"
docker_registry: "https://ghcr.io"
docker_username: ${{ secrets.DOCKER_USERNAME }}
docker_password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build Image
run: |
docker build -t "aserto-dev/aserto-console-backend" .
- name: Push image to GitHub Container Registry
run: |
echo "${{ steps.calc_tags.outputs.version }}" | \
xargs -I{} bash -c \
"docker tag aserto-dev/aserto-console-backend \
aserto-dev/aserto-console-backend:{} && \
docker push aserto-dev/aserto-console-backend:{}"
In conclusion…
If you have similar needs to ours when it comes to versioning, we invite you to use sver
and perhaps even contribute to make it better!
Vlad Iovanov
Founding Engineer
Related Content
Aserto on Aserto: an OPA authorization policy for Aserto tenants
How we've built Aserto's authorization model by "eating our own dogfood".
Sep 25th, 2021
Composing OPA solutions
Building awesome apps with OPA just got easier.
Sep 29th, 2021
Introducing the Open Policy Registry (OPCR) project
A Docker-inspired workflow for OPA policies, now available at openpolicyregistry.io!
Oct 12th, 2021