Chronologic Versioning: No more arbitrary version updates and regressions
chronver.org
chronver.org
"The current version of TeX is 3.14159265; it was last updated on January 12, 2014. The design was frozen after version 3.0, and no new feature or fundamental change will be added, so all newer versions will contain only bug fixes. Even though Donald Knuth himself has suggested a few areas in which TeX could have been improved, he indicated that he firmly believes that having an unchanged system that will produce the same output now and in the future is more important than introducing new features. For this reason, he has stated that the "absolutely final change (to be made after my death)" will be to change the version number to π, at which point all remaining bugs will become features. Likewise, versions of Metafont after 2.0 asymptotically approach e (currently at 2.7182818), and a similar change will be applied after Knuth's death."
I sincerely wished that that was a more common sentiment. All this change for nothing doesn't move the needle at all and irritates users the world over.
A TeX layer implements mechanism, a LaTeX layer does the policy, and an Overleaf handles the UI chores.
(I'm a Spacemacs/org-mode/texlive user, personally.)
A better approach would be hybrid:
2.2020.01.01.3-bd
Where the first number is the release track, the next three are the date, the last number is to handle multiple releases in a day, and the letters (always in alphabetical order) are codes for:
b: this is a breaking change
d: there are deprecations in this release
I would also suggest a third letter code "z" to mark bad releases, where you unintentionally broke things to the point that this release should not be used (and for whatever reason cannot retract the release). So, to mark the above release as bad, tag the exact same version a second time:
2.2020.01.01.3-z
Which means that 2.2020.01.01.3 is a bad release. It will show up after 2.2020.01.01.3-bd because it's later in the alphabet in the release list. Anyone looking for the last release that matches whatever their criteria is will now know to avoid that particular version.
Edit: Formalized here: https://github.com/kstenerud/hyver
Meaning the tag is useless. If a release is “bad” you just yank it.
> it will show up as after 2.2020.1.1.3-bd
According to your scheme the last number is the release index in the day so this is nonsense: either -z replaces -bd or it’s a later release which appears before in the release list (assuming you have a descending alphanumeric sort).
You wouldn’t have both 2.2020.1.1.3-bd and 2.2020.1.1.3-z because they’re the same release with different crap tacked on.
The only changes people usually care about are "will it break my software?" and "Am I using deprecated calls?" Beyond that, there's no standardized way to know what has changed between releases, and you'd have to look at every release regardless. Of course we could always add another metadata letter "n" to signify "new features". In fact, I'll add it...
> If a release is “bad” you just yank it.
And what if you can't yank it? That's what the "z" tag is for. If you can yank it then by all means yank it.
Example:
Current release list:
...
2.2019.12.18.1
2.2019.12.19.1-n
2.2019.12.19.2
2.2020.01.01.3-bd
Bad release you can't yank: 2.2020.01.01.3-bdCreate a new marker release: 2.2020.01.01.3-z
New release list:
...
2.2019.12.18.1
2.2019.12.19.1-n
2.2019.12.19.2
2.2020.01.01.3-bd
2.2020.01.01.3-z
Now everyone knows that 2.2020.01.01.3 is bad but couldn't be yanked.Which is exactly what your scheme does not answer unless you go through every single version between current and latest one by one, at which point… what’s the point if your scheme? You’re going through every single version anyway you can explicitely list the changes.
> And what if you can't yank it?
Then you add support for yanking.
SemVer remains good for libraries, or anything where there's a clearly-defined API for consumption, because it clearly establishes a set of rules for what to expect. If you're using version 1.0.0 and upgrade to 1.10.30, with SemVer it would remain perfectly compatible, and no change should be required on your part (that's the ideal; of course developers are free to use whatever versions they want and pretend it's valid SemVer).
For applications though, I agree that ChronVer seems far more useful, because there's just no real "compatibility" contract with an application. After all, macOS 2017.09.25 seems far more descriptive than "10.13", which means nothing to anyone.
It's unfortunately becoming less common but there is still a "compatability contract" between developers and users. With 10.13 -> 10.14 upgrade I would expect no major disruptions as a user, I would expect the UI to be nearly identical and no features to be dropped. With a 10.13 -> 11.1 upgrade I would expect "breaking" changes to my interactions and plan to install the update at a convenient time to deal with this. For a 2017.05 -> 2019.08 upgrade I have no indication of what to expect.
For something like continuously delivered web applications I don't think any versioning scheme makes sense to user because they have zero control, it's useless information.
We do major.minor version numbers, with even major versions being releases and odd being development versions. We also have an user-selectable way to pick version (major and minor) of our program at launch. So if we "dun goofed" in one version, the user can always just relaunch the previous version which worked.
Right before xmas I changed it so that if you didn't enter a first name, it would skip the rest of the name and address fields. This went into a new major version, so users were not that surprised to discover this rather big change in UI flow.
However I had missed that in one special case, users were required to enter a postal code. The user that reported this could then just launch the previous major version until I got that issue sorted, getting bug fixes for other issues in the meantime.
Often have thought that crypto libraries should be using ChronVer. Unlikely that an implementation will have breaking changes.
Besides that certainly agree with everything else.
I don’t understand this argument. Dates are arbitrary, and are subject to how quickly something is released/iterated on. Was there 2 releases a year? Once every two years? It’s hard to understand between different versions how many major potential changes there are.
For something like macOS, the number of fundamental under the hood changes are tremendous, coming from a super large organization. Without semantic versioning, it is difficult to create dependencies or explain compatibility, let alone understand how “old” a version someone might be on —- time itself is subjective, while an incrementing counter is not.
see also vector clocks.
And then 2017.09.28.83456, 2017.09.28.83457, and 2017.09.28.83458 all come out at the same time.
One is a patch to El Capitan, one is a patch to Sierra, and one is a patch to High Sierra.
There's absolutely no way to tell which is which.
Go ahead and refer to Catalina as 2019.10 or 19.10 or 1910. But keep the same prefix when patching it.
- 2017.09.28-capitan - 2017.09.28-sierra - 2017.09.28-highsierra
These are perfectly valid in the spec.
Also this makes it impossible/stupidly hard to release security patches for a older but stable version of a library when a new version with a largely changed API is released (which might not yet be feature completely)
Sure there are some ecosystems what a lot of authors don't do semver right, or where due to (mostly dynamic) aspects of the language this is harder then it should be.
But why not: 1. Require semver for a ecosystem/package manage which clear rules as what constitutes as a breaking change 2. Remove/ban packages which don't keep with it (or at last put a warning up). Authors who don't like it can still release a major version update Everytime.
Honestly if this schema would be used in a library ecosystem thinks would be pretty fast become pretty bad with you having to pull in tens of versions of the same fundamental dependency which might even all be compatible but you can't tell automatically and have to check by hand which isn't something you can afford time wise.
- Does not support multiple release tracks. What if you have 'version 1' and 'version 2' with both receiving updates?
- Cannot visually guarantee that any version is greater than, less than, or equal to another. If you're using git, mercurial, or any other VCS with hash-based commit IDs, how can a user tell which release for a particular day is the latest?
This is probably fine for SaaS stuff where you only support one version at a time and the version number is more important to you than your users.
I don't see what is here to misunderstand.
If someone wants to take just a subset of the changes between 2 and 3 (say just one fix) and backport it over version 1, they are on their own.
That's a downstream problem that the project doesn't have to cater to in its versioning scheme. The project issued a bugfix, and that bugfix was applied when version 2 was superseded with 3; end of story.
Another example is python 2 and python 3, where python 2 was getting updates form 5+ years after python 3 released.
Two completely independently developed C compilers, or independent implementations of Common Lisp are much more compatible with each other than are Python 2 and Python 3.
They could as well have different names (think Perl vs. Rakudo).
Racket is more compatible with Scheme than Python 3 is with Python 2, yet has a different name, for good reasons.
Both Python 2 and Python 3 could respectively use a simple versioning numbering scheme. Python 3 version 1, version 2, version 3, ...
Idk how you'd be able to tell anything about a commit from its hash tbh.
You're right though, I primarily create/work on SaaS products and this versioning is perfect for it.
Simply moving from YEAR.MONTH.DAY.CHANGE_ID to YEAR.MONTH.DAY.UPDATE.CHANGE_ID, with UPDATE being a mandatory monotonically-increasing integer, would make this scheme more attractive to a wider variety of users.
Given two versions j and k, those being integers if j > k, then j is chronologically later than k.
That's what I use on the TXR project.
That being at version 230 means I made 230 releases since the project started in 2009.
Since that number "means" something, it has semantics; therefore, it is not only chronological but also semantic.
230-12-01-2020 to mean the 230th release since the start of the project, made on January 1st, 2020.
Edit: the great irony is that your example included an error which I then reproduced! Obviously, 1st jan is unambiguously:
230-2020-01-01
If you were representing 1st dec, though, I’d suggest:
230-2020-12-01
Surely this is either released on the first of December or the 12th of January?
I've used it in the past for Continuously Deployed web applications. The dates make it easy to determine the age of the release, and it's easy to automate away to a CI job[2].
[1] https://calver.org/ [2] https://dephell.readthedocs.io/cmd-project-bump.html
I'm biased but I like mine more (and have an npm module to increment automatically).
https://tools.ietf.org/html/rfc1912
I'm sure this strategy vastly predates 1996 in other computer applications.
Julian dates have a similar purpose, and have been used in the US Military Logistics system for a very long time, but I can't figure out how far back. Also some food products, beer especially, with "secret" expiration or manufacture dates, according to civilians anyway, are often strangely formatted Julian dates.
The problem with SemVer is that library owners are not strict with its intended usage (backwards incompatible changes in patch!) or don't fully understand it. Perhaps having a much more simple versioning strategy will help in some use cases.
The worst case I saw was when someone was just appending 9's to the version number every release (0.99999 -> 0.999999). I think this was a joke about asymptotically approaching version 1.0. The effect was that some error message when solving dependencies came out as "X wants version 0.99999999999, but Y wants version 0.99999999999". Very annoying!
What's the point of doing it if you're not gonna do it right?
Thanks for the kind words!
Maybe I should add a "prior art" section on the site, thanks for the link!
If the complaint is "semver numbers aren't always used the way they are meant to be" how does (what is effectively) `v<year>.<month>.<day>` solve that problem? With SemVer the numbers are at least _sometimes_ used as designed.
If the complaint is "I want to know how old the software is" then why not just append a timestamp to the SemVer number as in `v2.3.4-<date>` What's the advantage of making the date primary?
Does the breaking-change identifier only refer to the previous version chronologically? Then this system is incompatiable with any scenario in which you need to "patch" old versions of the software. And isn't that a pretty central problem that version numbers are meant to address?
I honestly don't understand the problem chronological versioning is solving, or if I do than it seems to me that `<semver>-<date>` is obviously a better way to solve it.
However, if they both used date-based versioning, then the compatible versions would in theory have the same-ish version of 2019.12.* when compatible with each other.
For the same reasons as in tons of other comments, I also don't think this theory would work out.
So with this system if you want to know whether two versions are compatible you would need to check versions of all releases between them for not having that label...
Then again perhaps in web apps there's something to be said for this when breaking changes ARE the consistency. I have to say that working in back-end technology, I don't really care whether something was built in 2010 or 2020 as long as it's doing its job well.
Unfortunately, most back-end technology still communicates with web API's at some point and then we're at the mercy of the service's "version".
I think a more modular versioning standard might be good as semantic versioning can be very helpful in certain projects like libraries.
Like if your project has x abstract property then include x. and y for a x.y versioning scheme.
Compatibility of APIs is retained if you require less or provide more. Breaking changes happen when you require more or provide less. Don't do it. Add a new and different function that requires more or provides less. Keep the old one. You now have a backward compatible interface.
> “Consistent with Racket’s version-numbering system, the first digit reflects major updates to Pollen that break backward compatibility. The second digit reflects feature updates that don’t affect existing features. > > “Inconsistent with this system, Pollen’s version also appends a build number, which is the age of the software in days and minutes.”
The current version is reported as 2.1.2329.415.
Does that mean this release (roughly v2.1.something) was compiled/packaged/released 2329 days and 415 minutes after some arbitrary project-start timestamp? That this was compiled/packaged/released 2329 days and 415 minutes _ago_? Are those literally the "days" and "minutes" fields they're talking about?
The former seems kinda crazy (as the version number would be mutable) but to be honest that's how I'd naively interpret "the age of the software" - I want to know how long ago this build was created, not how long after the project was first started.
If the version number is days-after-project start, why not just use the actual date? What's the value of the arbitrary baseline?
(Actually, now that I think about it I guess the arbitrary baseline does have an advantage if you are intentionally trying to obscure how old the build is in calendar time. *.2329.415 provides an easily interpreted, monotonically increasing identifier without making it obvious if this release happened yesterday or 10 years ago. I.e., this solves the problem that products with the year-of-release in their name have - surely people are eventually stop buying FooBar2015, whether or not there's a real need for an update in the past 5 years.)
Ideally I want enough introspection in my tooling to automatically pick up breaking changes by doing static analysis between versions and where breaking changes are impossible to detect I want humans to tell me what the breaking changes are in a structured way
I want my dependency manager to take me up to the next breakage free version and to see what the breaking changes are if specified, maybe with programmatic suggestions/fixes from the library maintainer
And perhaps hardest of all I want the culture of change to being hyper allergic to breaking changes in the rich hickey sense
This is an enormous pain in the ass with .NET NuGet packages, I have found, although I am sure it extends into other ecosystems as well.
It turns out one of the more interesting problems with version numbers is tools that assume that each number will fit within 2^8, or 2^16.
2020.0102.0345 if you stick to GMT.