This is a build number, not a version number. I don’t see how it works as a version number if you can never rebuild the same version. Also it presumes there is only one entity building the code, otherwise the CI mapping wouldn’t work.
You might as well just assign it a build number as a flat integer and keep track of all the metadata separately, it’s easy and there’s no risk for collisions since it’s bound to the CI system anyway. That spares yourself from the annoyance of trying to communicate these monstrous monikers to other people.
A large major version number is perfectly semver compatible, and surely YAGNI anyway.
You could always change the artifact name if you had to adopt a different scheme. I don’t think you’d use this scheme for an artifact where the artifact name is UX in the way it is for e.g. a Linux package.
I agree with a slight difference. Shift everything right, then you have all the meaningful numbers next to each other. e.g., 0.0.20241127214906-g1f8292a-12058740477-1. The FAQ on “Why only use the MAJOR SemVer part as a timestamp?” has a reasonable argument for going with major, though.
Interestingly, this is why Linux distro versions often have an epoch field – it’s meant to be a “super major version number”, for when the versioning scheme changes.
I’ve had success using a timestamp based on the commit’s commit-date rather than the CI run date; it makes it stable across rebuilds of a single commit, and if you haven’t included the commit sha in metadata somewhere, you stand a good chance of figuring out the commit based on the timestamp.
The fun thing with git is that commit dates can run in reverse if the time of the VM that does the commit is wrong. I’ve had the occasional git commit history that suddenly jumps back two years in the middle. Cherry picks will also, I believe, keep their original date, so if you cherry pick a fix from another branch you may not have linear time.
You can enforce monotonic time with receive hooks, but if you don’t then using the commit timestamp can be very interesting.
if you are not using merge commits, but a linear history, your time may till jump forward and backwards. The timestamp of the commits may not be in the same order in which they were applied to the branch.
Note that git commits have two dates, author and committer. Generally the author date is the date at which the commit was first created, and the committer date was when the commit was last modified. So while the author date is never expected to be monotonic, the committer date generally is. But as you pointed out this isn’t completely reliable – even beyond local time differences you can just set GIT_COMMITTER_DATE.
i’ll just point out that it’s not every thing that is built from CI; and it’s often quite annoying when version numbers are only valid if they are computed by CI.
indeed, imo it’s basically always wrong to have a version that is somehow related to the implementation-detail of the repo using git!
what you have here is, of course, an extremely useful bit of metadata, but probably a quite unfortunate actual version number.
This is a build number, not a version number. I don’t see how it works as a version number if you can never rebuild the same version. Also it presumes there is only one entity building the code, otherwise the CI mapping wouldn’t work.
You might as well just assign it a build number as a flat integer and keep track of all the metadata separately, it’s easy and there’s no risk for collisions since it’s bound to the CI system anyway. That spares yourself from the annoyance of trying to communicate these monstrous monikers to other people.
Should start with a leading
0.
in case you need to adopt semver laterA large major version number is perfectly semver compatible, and surely YAGNI anyway.
You could always change the artifact name if you had to adopt a different scheme. I don’t think you’d use this scheme for an artifact where the artifact name is UX in the way it is for e.g. a Linux package.
I agree with a slight difference. Shift everything right, then you have all the meaningful numbers next to each other. e.g.,
0.0.20241127214906-g1f8292a-12058740477-1
. The FAQ on “Why only use the MAJOR SemVer part as a timestamp?” has a reasonable argument for going with major, though.Interestingly, this is why Linux distro versions often have an epoch field – it’s meant to be a “super major version number”, for when the versioning scheme changes.
That reminds me of the CoreOS versions, pre-Red Hat, in which the version was the number of days since inception plus a patch number.
See also https://samver.org/ – similar concept, but doesn’t include a CI job id.
I’ve had success using a timestamp based on the commit’s commit-date rather than the CI run date; it makes it stable across rebuilds of a single commit, and if you haven’t included the commit sha in metadata somewhere, you stand a good chance of figuring out the commit based on the timestamp.
The fun thing with git is that commit dates can run in reverse if the time of the VM that does the commit is wrong. I’ve had the occasional git commit history that suddenly jumps back two years in the middle. Cherry picks will also, I believe, keep their original date, so if you cherry pick a fix from another branch you may not have linear time.
You can enforce monotonic time with receive hooks, but if you don’t then using the commit timestamp can be very interesting.
Isn’t that just the author date, just like what happens for rebases? The commit date should be updated.
yes! we hit that in our first test as we started with author date. Commit date does change on rebases and cherry-picks.
True! In our case, we are only versioning the
main
commits, which are made by our git host only - so we’re reasonably sure the date in accurate…if you are not using merge commits, but a linear history, your time may till jump forward and backwards. The timestamp of the commits may not be in the same order in which they were applied to the branch.
Note that git commits have two dates, author and committer. Generally the author date is the date at which the commit was first created, and the committer date was when the commit was last modified. So while the author date is never expected to be monotonic, the committer date generally is. But as you pointed out this isn’t completely reliable – even beyond local time differences you can just set
GIT_COMMITTER_DATE
.If you want something like a monotonic numeric version, one way to do it is via a generation number. For a DAG the generation number (sometimes called the height) is defined as 1 + max(generation number of parents). See https://devblogs.microsoft.com/devops/supercharging-the-git-commit-graph-iii-generations/.
i’ll just point out that it’s not every thing that is built from CI; and it’s often quite annoying when version numbers are only valid if they are computed by CI.
indeed, imo it’s basically always wrong to have a version that is somehow related to the implementation-detail of the repo using git!
what you have here is, of course, an extremely useful bit of metadata, but probably a quite unfortunate actual version number.
I’m kinda used to these alt-versioning schemes being bad, but in this case, I’m not sure it is.