1. 11

This was motivated by the cockroachlabs’s decision to switch to a calendar versioning. Their problem is that they want to signal a major change in features, but they do keep their backwards compatibility. For a lay-person, the major version number signals capability, and it is not encouraging when that does not change.

From what I can see, there are two main uses for versioning – one to determine whether a given version introduces breaking changes to an existing API, and another to specify an increase in capability. I wonder if explicitly tagging them as such, with no ordering specified would help resolve the issue. The idea is to tag the major version with C (for compatibility) and minor with F (for features). (Perhaps P for patches too for software like Latex or algorithms that are not expected to change in functionality.)

For example, F2.C1.P0 signals that We have a significant improvement over F1.C1.P0. It is exactly same as C1.F2.P0. On the other hand F3.C2.P0 signals that the API changed when compared to F3.C1.P0. Indeed, the developers may choose to increment the F part also when breaking changes are introduced. It can be converted to the semver 2.0 format by simply splitting by . sorting, and stripping the first alphabet.


  2. 18

    I propose JudgeVer: use your judgement to do the sane thing, and not worry too much.

    So what if you jump from 2.1.5 to 3.0 without strictly introducing API changes? Are you sure that the new optimizer in CockroachDB will be better in 100% of the cases? What if performance is significantly worse in 1% of the use cases, and you rely heavily on that 1%? Then this will be a breaking change for you.

    Just because the API is compatible doesn’t mean the product is compatible with your needs. I once fixed a bug so that all unicode whitespace was properly treated as whitespace, but at least one person was relying on the old behaviour. Compatible API, but breaking behaviour.

    In JudgeVer you bump to 3.0 because it makes sense. So what that the spec says something else? The specification isn’t law, and you won’t get arrested if you do something else.

    Publishing an incompatible version with a compatible version number can potentially cause a lot of problems, while the reverse has significantly less potential to cause problems. So when in doubt: just bump that major version. One rule of thumb I’ve seen floating around is “if it broke a test, it’s a major version bump”, which strikes me as reasonable (although not comprehensive).

    No doubt that the purists will balk at this 🤷. Honestly, I find these really complex specifications/schemas for versioning rather … tiring, and generally tap out of the discussion once someone starts using “argumentum ad that’s-how-it’s-in-the-spec”, rather than just doing the sensible or safe thing.

    1. 2

      I pretty much agree with you. Either you are super lazy and you just upgrade dependencies willy-nilly and pray for the best(and maybe run a test or three), or you actually care about your dependencies and then you MUST read the changelog at the very least anyway. So version numbers are only marginally useful, either way.

      1. 2

        Updating dependencies can be very time consuming if you read all ChangeLogs, especially in environments with a lot of dependencies. npm is of course the canonical example of this, but a standard Ruby on Rails application also has quite a few dependencies (Lobste.rs has exactly 100 in Gemfile.lock).

        I don’t think version numbers are completely useless. If there are 50 updates, then major version update change will be more likely to introduce a breaking change for me, and a minor version change will be more likely to be breaking than a patch version. So I can prioritize which ChangeLogs I want to read, and get the best return of investment of my time.

        Not that reading ChangeLogs is any guarantee anyway. If the library authors didn’t immediately realize that a change is breaking, then there’s a decent chance that I won’t either. Especially not for larger applications where no single person understands all of it (which is large chunk of real applications).

        Another issue is the lack of tooling; pkg-manage update should have an option to display a ChangeLog, for example. And ChangeLog format should be standardized so that important information can be parsed out of it.

        1. 3

          Agreed, but for any code that lives past a few dependency upgrades, you quickly get a feel for the dependencies that never cause problems, and the ones that do nothing but cause problems. You then prioritize your time along those lines.

          I agree it would be nice if changelogs were easier found/viewable directly from the tooling around upgrading dependencies. Even OS packagers don’t do this all that well for the most part.

          1. 2

            The apt-listchanges package in Debian will display important changelogs in packages when they’re upgraded. Important meaning, breaks something in a stable release, or otherwise may require human review.

      2. 2

        I was just starting to get exactly the same itch reading this.

        When something exists in ‘human space’ and has a huge number of possible states subjective to many view points (in this case all of the vectors of what are ‘bugs’ and ‘features’ according to different subjective use cases), there is no way to formalise and the effort to do is painful and fruitless - everyone has to resolve their own subjective viewpoint.

        1. 1

          I am not a purist :). However, my understanding of semver is that it doesn’t absolve you of having to verify that your product works as expected. If an external component is crucial to your product, I would expect you to be vigilant about any changes made (including running your own integration and regression tests), and not just rely on the version string.

          For the other places however, I believe that it would be better to not specify the version requirements too tightly (which is what your proposal would do – Does every product that uses your product care about that optimizer?) and provide the automated tools that space to work with to resolve version requirements.

          1. 2

            If an external component is crucial to your product, I would expect you to be vigilant about any changes made (including running your own integration and regression tests)

            The problem with that is that I can’t test behaviour that I didn’t realize that exists, or didn’t realize was important for the correct working of my program. Even if you’re the sole author of an application of 50k lines, then chances are you can’t remember every implied assumption in those 50k lines when reading the ChangeLog for a library.

          2. 1

            I once fixed a bug so that all unicode whitespace was properly treated as whitespace, but at least one person was relying on the old behaviour. Compatible API, but breaking behaviour.

            I wrote a blog post along the same lines, riffing off of “What’s better than semver?” by @leeg. As you say, when you’re publishing a library, fixing a bug can break consumers just as badly as any other kind of change. As a library author, you can lessen the pain by documenting your library thoroughly, including defining as explicitly as possible which behaviors are part of your API and which are incidental.

            For example, if you provide a function that returns an array of items, you should define whether the items will be sorted according to a specific criterion; returned in no particular order, but the order will always be the same for a given set of items and a given library version; or just not in any particular order at all. If you make an internal change that affects the order of the items, your consumer-facing documentation can guide you on whether you’ve made an API-breaking change or not. Of course, there will always be times when someone is relying on the incidental behavior of your library instead of the specified behavior, and then their application is broken by a “non-API-breaking” change. Making this situation as unlikely as possible is a human problem and it can only solved by human-facing affordances like changelogs and API docs, not by machine-readable data like version numbers.

            1. 2

              I think that Lee’s claim that “there is no such thing as an “internal change that fixes incorrect behavior” that is “backwards compatible”” is too strong. If using a Unicode space would throw an exception or produce clearly broken output (e.g. by treating all bytes as one character and returning giberish) then the change in behaviour would be backward compatible by any reasonable definition.

              On the whole, it’s a lot less likely that a bugfix will break backwards compatibility in any meaningful way, only some do. I think a lot of the problems with SemVer are because tools treat it as hard guarantees, instead of probabilities.

          3. 5

            For me, the CockroachLab’s problem seems to be trying to fix a marketing issue with software versioning.

            Semver isn’t about “important enough” things to go on the first number or just little features to go on the second one. It’s about backwards compatibility, features and fixes.

            1. 1

              Yes indeed. Unfortunately, software versions are one of the visible artifacts for the user who may not be technically minded. They user may decide to not upgrade (which may require payment) if they perceive that the software hasn’t changed significantly (Which also means that it can not be decoupled from marketing even if we may wish to). Hence, I am sympathetic to their plight. Which is why I propose to remove the ordering.

              1. 2

                software versions are one of the visible artifacts for the user who may not be technically minded.

                It’s a Database. The kind of person that should make the decision of using this or other database is technically minded. If you’re trying to sell a consumer product, okay, use something like the Teslas’ software versioning for their car firmware (Year of the update.Minor.Fix). But for a database? I would say stay on Semver if you care more the tech people that will manage it instead of the CEOs trying to solve the wrong tasks.

            2. 3

              My main issue with semver is the conflation of security patches (upgrade ASAP!) and bugfixes (you only need to upgrade if you’re affected), and putting them both in the least important-looking section. Perhaps endian-agnostic versioning like this is the answer.

              (Another gripe: the difference between “breaking changes” and “new features” is meaningless, since you’re going to have to change client code in both cases - why would you upgrade to a new-feature-only release without making some changes to take advantage of that feature?)

              1. 6

                I’m not upgrading to a new-feature-only release, but maybe you are and you also depend on my library. It’s useful to you to know that a set of library versions are likely to work together.

                1. 2

                  Ah, of course, I forgot. That does matter in environments where you have to make do with whatever version is available lying around, and/or you can’t depend on more than one version of the same library. Given the choice, I’d rather not find myself in that situation!

              2. 3

                If you ignore the theory of the spec for a second, and just look at what semver does in package mangers, it generally is:

                • minor or patch bump — almost everyone updates immediately.
                • major bump — nobody updates automatically, and it’ll take weeks, months or even years for people to catch up.

                And there are no other options. It’s not about syntax, numbers, or how you call each part. The software can either be updated automatically, or has to wait for a manual intervention.

                1. 2

                  Build metadata can be (ab)used to indicate breaking changes and/or security fixes

                  1. 2

                    You don’t have to expose your development version to customers as your advertised version.

                    1. 1

                      Yes indeed. I agree.

                    2. 1

                      Sounds hilariously hard for software to sort. Presently you can compare software version numbers and know that the new is newer than the old with simple numeric comparison. Even LaTeX has sortable version numbers.

                      By adding text like this and making the order somewhat arbitrary, package managers have to be explicitly aware of your versioning scheme.