TrunkVer
135 points by todsacerdoti 7 days ago | 113 comments
  • makifoxgirl 7 days ago |
    I've been using something like this for the Unity game I'm working on where I need regular updates. However, I don't think it let me use 14 numbers in the major field. So I've stuck with something along the lines of <year>.<month>.<date>-<hours*60+minutes> to better saturate. It's nice to know there's a standard for this though.
  • echoangle 7 days ago |
    In what way is this „SemVer-compatible“ when you just ignore the „Major increment <=> breaking changes“ convention? It has 3 numbers separated by dots? This just increments major version every time a build is started, even though there might not be breaking changes.

    Edit: When looking at the SemVer page: https://semver.org/#if-even-the-tiniest-backward-incompatibl...

    The formal spec technically only tells you that you MUST increment Major for breaking changes, and not that you can’t do it every time, but the FAQ makes it clear what the spirit of the rule is. I can’t see how TrunkVer can be called SemVer compatible with this construction method.

    • idle_zealot 7 days ago |
      In semver terms, I believe this translates to "every change might be breaking", which sounds right for trunk-based deployments.
      • wakawaka28 7 days ago |
        It sounds like a disaster. Trunk-based deployment does not imply such an extreme degree of instability, because all development may happen on other branches. I see what you're trying to say though. I think the real keyword is "continuous integration."
        • ahtihn 7 days ago |
          > It sounds like a disaster.

          Why do you think so? It shouldn't be used for something like a library or an external API that other people rely on where communicating about breaking changes is actually important.

          For something like a web application, I don't think it matters much. Do you know which version of Google Docs you're using? Do you care?

          Saying it's semver compatible mostly means that you can use existing tools that work with semver and make assumptions about how version numbers can be sorted.

          • wakawaka28 6 days ago |
            >For something like a web application, I don't think it matters much.

            If the web application is singular and global, then sure. But web applications use libraries, and if people are taught this garbage then all the package managers for those libraries will be useless. If it's a web application that you're selling to customers, those have the same kinds of constraints as other applications. They may need to interoperate with other tools, not drastically change from one update to the next, etc. and this TrunkVer number does nothing to indicate what is happening.

            >Saying it's semver compatible mostly means that you can use existing tools that work with semver and make assumptions about how version numbers can be sorted.

            You can't really sort it because the date of the build is irrelevant to its contents, and the hash is not ordered by its actual authorship date either. You can't tell anything about how compatible anything is, except perhaps by an exact match on the second component. The date is first. So if you built an old version at a later date to fix an issue, that would screw up the ordering from a logical standpoint. Also, which date is actually the important one? The authorship date on the code, the archive date when the code was captured, or the package build date? Do you think the same choice will always be reliably picked?

            With SemVer, the time of the build is ancillary information that is actually irrelevant except to distinguish one package build from another. Therefore, the most common way to handle it is to add a fourth number like x.y.z-n to distinguish old builds from new ones. The TrunkVer page assumes "when it was built" is a singular time that matches the state of the code, which is not the case.

            Again, this is a disaster. Just because you have 3 numbers doesn't mean that sticking those into existing tools makes any sense. It is impossible to write compatibility logic for a package manager to automatically deduce which package should be used. For the purposes of those tools, you might as well make the first one a sequential number that increments every time you build.

      • froh 7 days ago |
        from their FAQ:

        "TrunkVer always defensively implies breaking changes between versions."

    • orf 7 days ago |
      It’s semver compatible because it can be parsed, accepted and compared by any system that expects or requires a semver formatted version?

      The whole point of this is that in trunk-based releases the version isn’t significant, so why not call each one breaking.

      • chungy 7 days ago |
        20241127214906.0.0 will be marked as incompatible with 20241127214907.0.0 by any such system that parses them.
        • orf 7 days ago |
          Sure, but it does parse them and it does rightly understand that one is an newer version.

          That’s… compatibility.

          • wakawaka28 7 days ago |
            Newer is not always compatible. That's why SemVer looks like work to authors. They don't like to think about compatibility.
            • orf 7 days ago |
              You’re misunderstanding, try re-reading the thread or other comments in the chain.
              • wakawaka28 6 days ago |
                I'm not misunderstanding. Again:

                >Sure, but it does parse them and it does rightly understand that one is an newer version. > >That’s… compatibility.

                Again, it isn't compatibility if the new scheme breaks every assumption that the old one had. You can't just say "The package manager wants 3 numbers so I'll stick 3 numbers in there. So it's compatible, see!" as the numbers you're putting in have no meaningful connection to the affordances of the other scheme.

                I've spelled out some more concrete objections (including the fact that the date is arbitrary and that the hashes are not ordered according to authorship) here: https://news.ycombinator.com/item?id=42267051

                • orf 6 days ago |
                  You literally can shove three incrementing numbers into a version and call it compatible, as long as the numbers increment. That’s the only compatibility requirement.
                  • wakawaka28 6 days ago |
                    The git hash is not an incrementing number. The date is not strongly tied to the actual code used in the build either. If I gave you a list of these TrunkVer numbers you couldn't tell me which ones are compatible, and neither can any package manager.

                    Package managers only work well with SemVer. They try to accept other schemes but anything but SemVer is an antipattern because of the inherent difficulties in figuring out what is actually going to satisfy a dependency.

                    • orf 6 days ago |
                      I really don’t get what your obsession is with compatibility and package managers. Stop and actually read what people are telling you before replying.

                      Repeat after me: the use case that fits this does not involve package managers, external distribution or any form of compatibility constraints.

                      Repeat after me: the use case that fits this involves the need a versioning scheme that’s better than a meaningless incrementing integer”

                      Repeat after me: the use case that fits this involves a need to integrate with a deployment system or tooling that expects semver versions.

                      Repeat after me: I want a semver compatible versioning scheme.

                      • wakawaka28 6 days ago |
                        Oh I read the most important thing, the original page.

                        >TrunkVer is a SemVer-compatible versioning scheme for continuously-delivered, trunk-based applications and systems that don't follow a release scheme.

                        It's not compatible with SemVer. I've explained why it isn't compatible in any sense multiple times now in various comments, probably most of them in reply to you.

                        >Repeat after me: the use case that fits this involves a need to integrate with a deployment system or tooling that expects semver versions.

                        Just because it fits doesn't mean it's "compatible". If you apply this TrunkVer scheme to a library, continuously deployed or not, the result is a disaster.

                        >I really don’t get what your obsession is with compatibility and package managers.

                        >the use case that fits this involves a need to integrate with a deployment system or tooling that expects semver versions.

                        A "deployment system" that you need to integrate with is most commonly a package manager.

                        >Repeat after me: the use case that fits this involves the need a versioning scheme that’s better than a meaningless incrementing integer

                        This may be more informative than an incrementing integer, but it is still not compatible with SemVer as the original page claims, and it is neglects many important considerations like variance between the build date, code version, and authorship date.

                        If you're going to reply to me again about this I suggest that you follow your own advice, because I've given fairly definitive objections to this scheme already:

                        >Stop and actually read what people are telling you before replying.

                        • orf 6 days ago |
                          > If you apply this TrunkVer scheme to a library, continuously deployed or not, the result is a disaster.

                          Cool, except those are not systems or an applications are they?

                          > A "deployment system" that you need to integrate with is most commonly a package manager.

                          Completely incorrect for systems and applications.

                          > If you're going to reply to me again about this I suggest that you follow your own advice, because I've given fairly definitive objections to this scheme already

                          You did it again. You didn’t read.

                          > Repeat after me: the use case that fits this does not involve package managers, external distribution or any form of compatibility constraints.

                          • wakawaka28 5 days ago |
                            My mentioning the specific case of a library does not invalidate anything else I said as it applies to applications. As I mentioned in another comment, applications (and "systems" which are often just an application bundled in a docker container or something) involve data, and SemVer communicates which versions are compatible with which.

                            >> A "deployment system" that you need to integrate with is most commonly a package manager.

                            >Completely incorrect for systems and applications.

                            I'm not wrong, but keep hitting the copium bro.

                            >Repeat after me: the use case that fits this does not involve package managers, external distribution or any form of compatibility constraints.

                            As I said, nearly everyone has compatibility concerns, or can develop them at any time. This is a short-sighted scheme. I can't deny that it "works" in some sense for a small number of people who are willing to make bad assumptions like that. But I cannot in good faith recommend it to anyone.

                            • orf 5 days ago |
                              I’ll ask again because you’re just not getting it:

                              - What is the version number of GitHub.com?

                              - Do you think the deployment version is an appropriate format to convey compatibility in a system of that size and complexity?

                              - Do you think it is deployed via a package manager like NPM or Bundle?

                              Once you’re able to read and answer these in an honest fashion, you’ll reach enlightenment.

                              Until then, keep wondering I guess.

                              • wakawaka28 5 days ago |
                                Ha I am not wondering. We are just going in circles now. I've explained why this is a bad idea for many reasons. Take it or leave it.
                                • orf 5 days ago |
                                  I’m wondering what your answers are though, because you’ve done nothing but try and avoid answering.
                                  • wakawaka28 5 days ago |
                                    I'm not sure what you mean but if you're asking for a solution then SemVer is better than this in most cases. It has none of the issues I mentioned caused by TrunkVer.
                                    • orf 5 days ago |
                                      It’s ok, I’ll do it for you

                                      - What is the version number of GitHub.com? = I don’t know

                                      - Do you think the deployment version is an appropriate format to convey compatibility in a system of that size and complexity? = I do not

                                      - Do you think it is deployed via a package manager like NPM or Bundle? = I do not

                                      • wakawaka28 4 days ago |
                                        Even Github has APIs. They're numbered by date: https://docs.github.com/en/rest/about-the-rest-api/api-versi... I think SemVer would be better but they aren't guaranteeing anything so SemVer adds nothing. The date is not informative.

                                        >Do you think the deployment version is an appropriate format to convey compatibility in a system of that size and complexity? = I do not

                                        OK I wonder how GitHub does self-hosting, migrations, etc. I assume they have bespoke upgrade scripts to migrate, and you might have to run them in a sequence. That doesn't mean SemVer is inappropriate. It just isn't going to help much.

                                        >- Do you think it is deployed via a package manager like NPM or Bundle? = I do not

                                        Although the site might not be deployed this way, libraries that interact with it probably are and they probably use SemVer. The only real argument against that is that you can't tell the API version supported from an unrelated SemVer number.

                                        • orf 4 days ago |
                                          > The date is not informative.

                                          It’s not supposed to be informative. It’s not supposed to be parsed. It’s a version identifier. The date is much better than a commit hash or an opaque number for this.

                                          Using semver for an external API is not a good fit at all. Compatibility is binary: it’s compatible or it’s not.

                                          If it’s not compatible, it’s a new version.

                                          Think on this a bit, and consider how this applies to a service as a whole, and you’ll finally understand what everyone has been telling you.

                                          > That doesn't mean SemVer is inappropriate. It just isn't going to help much.

                                          Irrelevant.

                                          > Although the site might not be deployed this way, libraries that interact with it probably are and they probably use SemVer

                                          Totally irrelevant.

                                          • wakawaka28 4 days ago |
                                            >Using semver for an external API is not a good fit at all. Compatibility is binary: it’s compatible or it’s not.

                                            Not true. You can be compatible with all APIs, adding no new features; you can add new features; and you can break existing features. These are the levels that SemVer can communicate. This makes as much sense for a web API as a binary library.

                                            >Think on this a bit, and consider how this applies to a service as a whole, and you’ll finally understand what everyone has been telling you.

                                            What all 3 of them? A vast majority of people prefer SemVer even if they detest the work that it generates. It's like a form of documentation.

                                            • orf 4 days ago |
                                              Assigning semver versions to deployments makes about as much sense as your replies. Which is why nobody does it.

                                              You don’t get it, seemingly by choice at this point. Good luck with that.

                                              • wakawaka28 4 days ago |
                                                You don't version the deployment, you version the thing being deployed.

                                                Lots of people use SemVer for web APIs. I think you clearly don't get why it is superior to TrunkVer. Good luck with that.

        • Kinrany 7 days ago |
          That's (in-)compatibility between versions, not compatibility between versioning schemes.
          • wakawaka28 7 days ago |
            You're not technically wrong but using the 3 numbers this way is in fact going to create problems for people trying to use this info. It means that you can never know if any version is compatible with others, and even if they were you could not easily link it.
            • harrall 7 days ago |
              It’s not creating a new problem that didn’t already exist.

              In many situations at work, trying to follow SemVer would be a technical solution to a non-technical problem.

              You know who your users are. Before you make any breaking change, you already have cross-product team meetings with possible executive buy in.

              In those scenarios, by time you assign a version number, everyone is already on the same page. The actual version number is meaningless and conveys no useful information. Spending any time on deciding the version creates unnecessary toil.

              • wakawaka28 7 days ago |
                It is creating a problem that didn't exist because using this instead of SemVer eliminates the option to communicate meaningful compatibility information.

                >You know who your users are. Before you make any breaking change, you already have cross-product team meetings with possible executive buy in.

                Generally none of these things are true. You don't know your users or how they intend to use your product. The executives certainly don't care about version numbers.

                There are some cases where nobody cares about version numbers, which mainly occur when there is one or a handful of consumers of a product and they are likewise committed to very frequent releases. This is not how most distributable libraries work. Furthermore, people care less about version numbers when the numbers are not correctly assigned in the first place. If you aren't using SemVer then it's just an increasing sequence for the most part.

                • orf 7 days ago |
                  This is not for libraries. This is for internal services that are continually released from the main branch of a repository.

                  I think you’ve deeply misunderstood the problem this is solving.

                  In short: What specific version tag is GitHub.com running right now? Even if you knew, is that version information meaningful?

                  • wakawaka28 6 days ago |
                    I know there are applications where version numbers don't matter. These are mainly singular websites and applications that have constant deployment. As I said, this version scheme is not compatible with SemVer because it uses a totally different concept and does not solve the same problems at all.
                    • orf 6 days ago |
                      My laptop is compatible with USB-C, as is my toothbrush.

                      Stop being needlessly and incorrectly pedantic about a highly context dependent and loosely defined word like “compatible”.

                      • wakawaka28 6 days ago |
                        Well if you're trying to sell me "compatibility" you've got to do better than that. As I said in another thread, TrunkVer is not even guaranteeing a proper order for package versions, much less anything about the relationship between them. Your sales pitch is like trying to sell a USB 1.1 cable to someone who only has USB 4 devices or something. Can it fit? Maybe if you try hard enough. Will it do what you need? Nope.
                        • orf 6 days ago |
                          > Well if you're trying to sell me "compatibility" you've got to do better than that

                          No, I’ve got to sell you what you want. And if you don’t want a compatibility relationship between package versions, then it’s an easy sell.

                          You’ve clearly not worked anywhere where this would be an easy sell. And that’s fine - it’s a specific kind of system that benefits from this, but don’t waste your time writing thousands of words when a simple “I don’t get why this is useful” would be enough.

                          • wakawaka28 6 days ago |
                            >And if you don’t want a compatibility relationship between package versions, then it’s an easy sell.

                            Everyone has to think about compatibility, generally speaking, unless there is exactly one consumer of the product that is always running trunk and all their data is continuously migrated to the newest version. If you commit to using TrunkVer, then that's the only use case you can ever easily support, until you decide to switch to something like SemVer.

                            >You’ve clearly not worked anywhere where this would be an easy sell. And that’s fine - it’s a specific kind of system that benefits from this, but don’t waste your time writing thousands of words when a simple “I don’t get why this is useful” would be enough.

                            Whether or not it's an easy sell for a certain kind of user is a separate issue from the fact that it is unsuitable for most projects and libraries. It's also a separate issue from the fact that this version scheme does not deliver on its prominent claims of "compatibility".

                            I have probably worked at a company or two where TrunkVer could fly. But I would not advocate for it because I consider it a bad idea.

                            • orf 6 days ago |
                              > unless there is exactly one consumer of the product that is always running trunk and all their data is continuously migrated to the newest version

                              Bingo

            • thayne 6 days ago |
              This is intended for use cases where it isn't necessary to communicate compatibility, such as a continuously deployed SaaS application or a user-facing application, where backwards compatibly isn't a concern .
              • wakawaka28 6 days ago |
                So what if this application has library dependencies developed by the same people? Don't you think that they would be tempted to use the same scheme to version those too, thus breaking any package manager?
                • thayne 6 days ago |
                  How would it break the package manager? In that case you would probably do one of the following:

                  - use a monorepo, where dependencies on libraries don't have versions, they are just relative paths

                  - the specified version is exact, if you want an update, you change the version dependency version constraint

                  - you have CI automatically update such dependencies to use the latest version.

                  - you don't use this versioning scheme for libraries

                  • wakawaka28 6 days ago |
                    Different packages demanding overly specific versions is an antipattern. I know you're bound to say, why not build more often? The trouble is that every package build probably needs testing, and there could be hundreds of individual dependencies that interact. Generally you cannot or at least would prefer to not have an application depend on multiple versions of a single package. Without SemVer it is very hard to find a solution.

                    Even if you use CI to do all your builds, this scheme only really works if you're willing to build everything just because one thing updated its dependency. There is no concept of stability or long-term testing with TrunkVer. It's basically only suitable for a specific type of application and environment. It is not suitable for libraries.

                    >use a monorepo, where dependencies on libraries don't have versions, they are just relative paths

                    This is only an answer if there is one consumer of this repo and one major product. When a monorepo contains libraries, it is also the sole consumer of the libraries.

                    • thayne 6 days ago |
                      > It's basically only suitable for a specific type of application and environment.

                      Absolutely. This isn't a replacement for SemVer, it is alternative to be used in cases where SemVer doesn't really make sense.

                      • wakawaka28 6 days ago |
                        I'd argue that SemVer makes sense for just about everything. If we were talking about something like a Linux distro, then sure I guess this is getting more reasonable. But for an app or library, especially one that generates data and/or has a programmatic interface, SemVer is better. SemVer might be a bummer when you have constant demand to immediately add stuff that is incompatible and you never have a stable version. It still works perfectly fine in that case however. That is to say, it communicates that there is no compatibility guaranteed between versions, and maintains the correct order between old and new versions. It probably also tells you approximately how many releases were between any two versions as well.
                        • thayne 5 days ago |
                          > That is to say, it communicates that there is no compatibility guaranteed between versions, and maintains the correct order between old and new versions.

                          Which is exactly what TrunkVer does. Every release increases the major version number. As long as the clock you use for the timestamp is monotonic.

                          > It probably also tells you approximately how many releases were between any two versions as well.

                          TrunkVer os useful in cases where knowing the time the version was created is more useful than knowing how many releases are between two versions. In particular, continuously deployed projects, where you might have multiple releases a day.

                          > But for an app or library, especially one that generates data and/or has a programmatic interface, SemVer is better.

                          For a library, I think it would be pretty rare for TrunkVer to make sense, unless maybe the only consumer of the library was an app that also used TrunkVer. For an app, it often makes sense to version an external API or data format independently of the app itself.

                          • wakawaka28 5 days ago |
                            >Which is exactly what TrunkVer does. Every release increases the major version number. As long as the clock you use for the timestamp is monotonic.

                            Well that and you never need to run old versions of the software, rebuild old versions, deal with customers who have different versions, etc.

                            >TrunkVer os useful in cases where knowing the time the version was created is more useful than knowing how many releases are between two versions. In particular, continuously deployed projects, where you might have multiple releases a day.

                            If you want to know when a build happened then it would be better to put that last. SemVer-based package systems typically do something like that with a fourth number. However, odds are you just want the latest in a series based on one code archive, so it only needs to be a simple sequence. People who need to know the date can consult other metadata to find out.

                            >For a library, I think it would be pretty rare for TrunkVer to make sense, unless maybe the only consumer of the library was an app that also used TrunkVer.

                            I think it's more complicated than this and thus TrunkVer only makes sense at the top level. If you apply it to a library, you better own the library and practically use a monorepo for your one app.

                            >For an app, it often makes sense to version an external API or data format independently of the app itself.

                            This only makes sense if you have multiple apps to deal with. Otherwise, the data format version practically is the app version and it would be pointless extra work for them to deviate.

        • jhanschoo 7 days ago |
          > A TrunkVer is syntactically compatible with SemVer, although it does not respect its semantic interpretation of the version number.

          The document specifically disclaims semantic compatibility.

        • theamk 7 days ago |
          well, yes, this is the only safe thing to do. The build system has no information what has changed since last build - maybe it was a complete interface rewrite - so it does the safe thing.
        • mst 7 days ago |
          This is explicitly for software that's made an active choice to not guarantee 100% compatibility between successive releases, so that outcome is a feature.
    • kbouck 7 days ago |
      It would be somewhat more "compatible" with semver if it placed the timestamp in the MINOR or PATCH segment, rather than in the MAJOR:

          0.20241127214906.0
      
          0.0.20241127214906
      • mst 7 days ago |
        I don't think I agree.

        Part of the point is that this is for "rolling release" type software, so always implying there *could* be breaking changes is a reasonable approach - kind of a versioning equivalent of defensive programming.

        Another comment elsethread notes that they call this out as a deliberate choice in the FAQ.

        • hifromwork 7 days ago |
          And, as we know from Hyrum's law[1], every change might be breaking ;).

          Oh, you added a bar() method to Frobinator? Shame, this other project depends on the fact that Frobinator only has one public method. And that project distinguishes Frobinators and Barinators by checking bar() method existence.

          And you fixed a bug where username returned from API had a space appended at the end? But my frontend developers used that for layout and now my site is broken.

          Written partially in cheek, but it's true that every change is breaking for someone if you have enough users.

          [1]See https://www.hyrumslaw.com, Wikipedia entry, recent discussion on HN, and of course that one xkcd.

    • layer8 6 days ago |
      Due to Hyrum’s Law, almost any change is a breaking change. Certainly, changing the observable version number is a breaking change. ;)

      In slightly different words: What constitutes a breaking change depends on the interface contract. If you have no interface contract, any change can be considered a breaking change.

  • 0xbadcafebee 7 days ago |
    Here's the thing about versions: they are never "complete", Because you never have just one version.

    Whatever you are looking at is most likely an amalgam of many different things, which all have their own versions. Your one perfect holy version number does not tell you those versions, so you have to look them up at some point (you did save the versions of all your dependencies and pack them into a BOM, right?).

    This trunk version similarly does not encode all the information you need. And what is it going to be used for? A python package? Every python package? A docker container? What about all the versions of stuff in that container? What about the helm chart that will ship this container, what's it's version? What about the version of all your helm charts that have been tested as working in stage before shipping them to prod?

    If you're going to have a "generic incremented trunk version", just make it a plain-old continuously incrementing integer (or hex, or whatever) with no semver. Because you're going to have to look up more information about what's inside it later anyway, and everything's going to have its own version as you modify individual items.

    Packing all this extra information in is actually counter-productive, because it's now much longer and more complex (which makes it harder to just compare a list side by side), yet it doesn't give you enough info. Ok, datestamp; where's the timezone? Ok, git sha; which repo (and has history been rewritten, or the files moved to a different repo)? Ok, CI build number; which build system (if you have multiple, or you moved from one to another)?

    Maybe some of it you can intuit, but eventually you'll wish it was different again. Might as well just make it a plain integer you can pass to a script that dumps out everything related to it.

    Semver's primary use case is not identifying what's inside or where it came from. The numbers are little more than a simple incrementor, and the use case is just a user who wants to know how afraid they should be. It's intended solely to communicate how likely this thing is to fuck your shit up. If it's a major version change, here be dragons. If it's minor, be cautious. If it's a patch, it should be harmless. Semver is a threat indicator. And it's easy to work with because it's so simple; comparing versions is easy. Comparing a wall of these TrunkVers will be like staring at The Matrix code.

    (SemVer's supposed to tell you what dependencies it can work with (>major, >major.minor, etc), but you still need the entire dependency DAG to have a pair of package name and version in order to make sense of it; you could do the exact same thing with a list of names and simple integers (foo >= 23456, foo<1234); now imagine with this TrunkVer (foo >= 20241127214906.0.0-g1f8292a-12058740477-1)...)

  • fishtoaster 7 days ago |
    I think this is a nice way to clarify the different use cases for version numbers:

    - SemVer is a communication tool for when an author needs to tell a potential user what to expect from a new version.

    - TrunkVer is an auditing/engineering tool for when you need to give a unique identifier to a version for technical reasons.

    I think this page is a nice codification of a useful practice, but it does itself a disservice by positioning itself against SemVar and claiming to be a "drop-in" replacement.

    • nine_k 7 days ago |
      It's a "drop-in" replacement in the sense that it's compatible with the format and with the rough semantics of SemVer. That is, if your libraries / packages all use SemVer, but the final executable / image uses TrunkVer, the latter does not need to be special-cased. TrunkVer gives a stream of "major versions" that's strictly increasing and all incompatible, and uses non-version fields to convey useful info. All SemVer-based tools will accept a TrunkVer value and do the right thing (that is, always prefer the newest build).
    • spacechild1 7 days ago |
      > but it does itself a disservice by positioning itself against SemVar

      I didn't read it like that at all!

  • codethief 7 days ago |
    > If the source reference is a git commit checksum, it may be truncated to 7 characters (--short)

    Doesn't the length of shortened git hashes depend on the size of the repo (whether or not shortened hashes of a given length collide)?

  • thrance 7 days ago |
    This breaks efficient dependencies resolution. SemVer is called that because versions carry semantic meaning, TrunkVer appears no better than using UUIDs for each version name. You know nothing of the relation between two versions in this scheme, other than which came first.
  • 1shooner 7 days ago |
    I can see using this if what you're building is at the end of the supply chain, and there is really less need to make the claims that SemVer does. Conversely, if you have downstream consumers, I can't imagine taking away the compatibility statements in SemVer.
    • regularfry 7 days ago |
      It depends whether the consumers have any choice about whether to receive the update. If what you're versioning is a web app, they're getting the update no matter whether they think current and next are compatible or not. And if they aren't compatible in a way that's going to cause problems, you need to be communicating richer information to them than a change in a version number anyway.
  • zvr 7 days ago |
    The EBNF in the page does not match the textual description:

        - "ALPHANUMERIC" is only letters, not numbers
        - "BUILD_REF" can contain dashes/hyphens "-"
        - "GIT_COMMIT_REF" is the letter "g" and a single hex character
        - "BUILD_REF" and "SOURCE_REF" may be empty, since they are 0 or more repetitions
        - "TIMESTAMP" is arbitrary numbers, so month or hour may be "99" for example
    • saghm 7 days ago |
      While I understand the point you're making, some of these don't seem like they should _technically_ be an issue in terms of whether a parser following the textual descriptions would work on the actual thing. Any parser written to accept an alphanumeric string should presumably accept a purely alphabetic one, and I'm pretty sure a "ref" in git doesn't just mean a hash but also refers to branches and tags, either of which could have a name in the format you describe. Given that the point of EBNF is to define grammar to a degree of precision and conciseness that textual descriptions can't match, I don't think it's a super big deal. From the perspective of building a parser from EBNF, the names of the tokens don't matter.
      • viraptor 7 days ago |
        > don't seem like they should _technically_ be an issue

        Sure, people can ignore the EBNF. But if you expect that, then why publish it at all? EBNF is specifically used to describe formats and get rid of ambiguities present in text description. Not being careful with it just undermines whole idea.

        • saghm 7 days ago |
          I'm not saying to ignore the EBNF; I'm saying to ignore the identifiers used in the EBNF. It doesn't matter that ALPHANUMERIC is alphabetic only because the identifier is just used as a shorthand for the tokens it represents. You could literally put anything down instead of ALPHANUMERIC and it would work the same, so the fact that the name isn't a perfectly precise description isn't a big deal.
          • zvr 7 days ago |
            No, it's the opposite problem.

            For example the text talks about "ASCII alphanumerics [09-A-Za-z]", the relevant EBNF rule is called "ALPHANUMERIC", but its definition is only letters.

            It's not the problem that it's called "ALPHANUMERIC" -- it's that it should describe alphanumerics and it doesn't.

      • zvr 7 days ago |
        On the git part: the text only mentions "git commit checksum", not "branches and tags" -- and it couldn't, since these are not immutable nor are they restricted to hex characters.

        My point above is that the EBNF defines "GIT_COMMIT_REF" to be the letter "g" and a _single_ hex character. So "GIT_COMMIT_REF" may be "g0", "g1", ... "g9", "gA", ... "gF", "ga", ..., "gf". That's it. Which obviously contradicts the text and the intention.

  • DidYaWipe 7 days ago |
    Is what?
  • montroser 7 days ago |
    A sequential build/release number would suffice in many cases.

    If the thing you're shipping isn't meant to be a dependency for other projects, then semantic versioning doesn't really fit.

    In trunkver though, using the timestamp of the build time is a little weird, since you could inadvertently end up building an earlier version of trunk at a later time.

    Putting an identifier of the job that built the release in the version number also seems heavy for what could just be an entry in a log file for when you need those forensics.

    • PaulKeeble 7 days ago |
      What happens with build number is you end up going back to the CI system and looking up what change it actually built and when it happened. I can see the advantage of having all 3 in the build name, I have done similar in the past for continuously released server software where there is no need for versioning numbers although typically I too have shortened it to just the build number because we have the CI system to go into if we need to.
    • status_quo69 7 days ago |
      Generally agree with your points about how semver isn't really necessary. I suppose the benefit here would be that dep management tools like dependabot could automatically raise pull requests when a new version is released, which would be pretty cool. If only my peer engineers actually paid attention to dependency updates.

      As an aside, instead of an auto incrementing build number I'd suggest the git sha since it's: 1. Already there and points to a specific version of the code in the repo 2. Globally unique 3. Can assist with reproducible builds (i.e. 6afed54 was acting weird, let's build it locally and take a look) 4. Gives you an easy diff target to dump "release notes". Just diff to the previous and dump the merge commit messages.

    • guytv 7 days ago |
      The problem with sequential build/release number is that you have to keep it in git (so you could increment), which results in a number of complications and annoyances.
    • jillesvangurp 7 days ago |
      Time is sequential. Otherwise, sequential build numbers are kind of hard to orchestrate in a distributed architecture. Not impossible. But it introduces complexities if you have many build machines.

      I don't think semver compatibility is that relevant/meaningful here. Normally I'd also want the branch name as part of the version tag. We do that with our docker containers. Adding the timestamp at the beginning is a good idea as it helps sort things by recency. I might copy that. The CI build id is nice, but I typically don't archive these anyway. All this concatenated gets a bit long.

      • rswail 7 days ago |
        git describe gives you what you want.

        It gives you the nearest tag, the number of commits from that tag and the git commit ID.

        • jillesvangurp 7 days ago |
          We don't use git tags for ordinary deploys. Every push to production gets deployed. And a timestamp is useful for sorting lists of container images.
      • hifromwork 7 days ago |
        >Time is sequential. Otherwise, sequential build numbers are kind of hard to orchestrate in a distributed architecture

        Time is sequential, but this means that just building an older version is now a production breaking incident. That's weird to me, but I'm not a CD person.

  • benatkin 7 days ago |
    What if the CI vendor decides to use the same for its ids? Then you have even longer version numbers.

    And if CI vendors aren't expected to adopt this, why expect a lot of devs to?

    On my computer, the CI version ID wraps, because between the other parts of the version and the padding, there isn't enough space. I think that says something about the length of the version identifier.

  • travisgriggs 7 days ago |
    I’ve been happily using date base version numbers in any user facing product (e.g apps) for a while now. It’s been great.

    While semver makes great sense on paper, and even allows nifty little algebras in dependency declarations, it is been my experience that the delineations are not always as easy to decode and different team members can quibble over the exact realization of the boundaries.

    Furthermore, it’s very much been my experience that semver changes, like all code comments, only communicate the intent of the developer and not always the reality. A minor roll may be anticipated as backwards compatible, until an unrealized use case pops up and makes the minor change very breaking.

    • BugsJustFindMe 7 days ago |
      > Furthermore, it’s very much been my experience that semver changes, like all code comments, only communicate the intent of the developer and not always the reality.

      This is the truth and the reason why SemVer is fundamentally wrong for almost all cases that people use it for. Fools with keyboards and big salaries hallucinate a contractual certainty where none exists.

      • rswail 7 days ago |
        If you understand that the "sem" in semver is specifically about semantics and not about anything else, and that an API includes its current semantics in the semver, then it makes sense.

        The issues I've struck with other developers:

        1. Defining the boundaries of the API

        2. Defining the semantics of the API from the perspective of the user

      • jraph 7 days ago |
        Tools like revapi help you get close enough.

        It's not perfect but still useful. Don't let perfect be the enemy of good. In most case, we probably don't need lawyer-level guaranties, but the guidance is helpful.

      • hifromwork 7 days ago |
        I'd like to hear your alternative. What do you propose? That we stop even trying to tackle this problem, and all libraries are sequentially or date-versioned? And you can pin to, for example, library version built from march last year to today?

        That would be a huge mess, IMO. Of course for non-libraries semver is fairly pointless, but for libraries it describes a contract and that contract works well in practice. But maybe there is a better way - hence my question.

    • arp242 7 days ago |
      semver is useful for libraries and other things that have a very clear programmer interface.

      For most applications it's fairly pointless. There are often many "breaking changes" in any significant release, and there is no strong agreement at all on what a "breaking change" even is.

    • layer8 6 days ago |
      > only communicate the intent of the developer and not always the reality.

      It’s nevertheless a very useful heuristics for anything with a programmatic interface. Nothing is a 100% perfect.

  • jiggawatts 7 days ago |
    I much prefer Nerdbank Git Versioning (NBGV): https://github.com/dotnet/Nerdbank.GitVersioning

    It allows repeatable builds because it uses the "git height" as the increment source.

    This is an implicitly updated value that is centrally coordinated, but isn't a separate system. If you have Git, you have a Git commit history, and hence an incrementing counter.

    NBGV can stamp binary outputs such as .NET EXEs and DLLs, generates compile-time sources with version strings, works with Node.js projects as well, and integrates with Azure DevOps pipelines automatically.

    • fuzzzerd 7 days ago |
      I have been using MinVer for dotnet projects, which is similar but a little easier (IMO) to work with since its all based on tags.
    • globular-toast 7 days ago |
      What if you rebase/force push? Seems dangerous to rely on "protected branches" and the like to avoid version clashes.
      • jiggawatts 7 days ago |
        On master/main? What are you, a savage?

        That's the only version that should really matter. Release branches, if used, tend to be pretty stable in terms of git shenanigans.

        The versions of dev branches don't really matter, and if it's a huge concern, you can simply bump the version in the NGBV config file to ensure that versions increase the way you want them to.

        • globular-toast 7 days ago |
          Not intentionally! But actually I think the concern is unwarranted because looking again it seems they don't include the hash for release versions, so if someone did force push master/main the artifact repository should reject it.
  • MrLeap 7 days ago |
    Add a metalayer to turn version names into memorable word phrases imo lol.
  • llIIllIIllIIl 7 days ago |
    Git commit sha produces a good enough version for most software.
    • globular-toast 7 days ago |
      Main problem is it's not ordered. It works if your software is deployed imperatively in a CI pipeline, but doesn't work if some other system is going to pull it later.
  • peterkelly 7 days ago |
    And the best part is you can completely disregard the need to maintain backwards compatibility, because every build implies a breaking change! /s
  • CGamesPlay 7 days ago |
    Another (simpler) versioning "standard" using calendar-based versioning: https://calver.org
    • s4i 7 days ago |
      What kills me with that website is that an example version string is nowhere to be found. The same thing almost plagues the TrunkVer page (unless you realize that you are supposed to ignore the newlines in that gray intro box), except at the very bottom you can see a dogfooded TrunkVer of the spec page itself.

      If you want your thing to be popular, make sure someone dumb like me skimming the marketing blurp can quickly understand what the thing looks like in the wild.

  • zaps 7 days ago |
    Great, now sell this to your marketing department
  • JTyQZSnP3cQGa8B 7 days ago |
    I’m still bitter that PEP 440 didn’t win: https://peps.python.org/pep-0440/

    It’s way better than semver and has all the metadata you may want.

    • Aeolun 7 days ago |
      Undoubtedly because semver has a nice website that immediately makes sense to everyone that reads it.
  • weinzierl 7 days ago |
    Often the version string is baked somehow into the artifact. If it contains volatile data that is not functionally dependent on the source (the when and how) it prevents the build from being reproducible.

    My opinion is that the pure semver should be part of the source and be baked in the artifact. Date and build metadata should be recorded close but separate from the artifact.

    • akpa1 7 days ago |
      If you have to include a date, the best thing to do while keeping builds reproducible is to use the date of the commit you're building. I quite like this approach, especially since it's fairly simple and readily available to get hold of too. Eg:

          git show --no-patch --format=%ci HEAD
      
      or %ct if you want a Unix timestamp.
      • hifromwork 7 days ago |
        Oh, I like that solution! My problem with dates is indeed lack of reproducibility.

        The only issue here is that it's not technically monotonic - both commit and author date are changeable:

            $ git init
            Initialized empty Git repository in /tmp/kk/.git/
            $ echo a > a; git add .; git commit -m a
            $ echo b > b; git add .; git commit --date="Wed Feb 16 14:00 2011 +0100" -m b
            $ echo c > c; git add .; GIT_COMMITTER_DATE="Wed Feb 16 14:00 2011 +0100" git commit -m c
            $ git lg
            * 523aa1a - (2024-11-28) c - user (HEAD -> master)
            * cbdbbbe - (2011-02-16) b - user
            * 1055e1e - (2024-11-28) a - user
            $ git show --no-patch --format=%ci HEAD
            2011-02-16 14:00:00 +0100
        
        But I guess if you use a typical pull-request based workflow this won't happen in practice.
  • rswail 7 days ago |
    This is needed because people misunderstand the purpose of semver (IMNSHO).

    Semver is about the semantics of the software (it's in the name), so it's entirely about that software's interface (whether to the programmer via API, other software, users).

    It's not about the implementation (except perhaps the "patch" component). If you fix a bug that doesn't change the interface, then there's no bump to the semver.

    "Trunkver" is about the implementation, but in a semver compatible format.

  • rswail 7 days ago |
    The funny thing about trunkver being "compatible" with semver is that it is not semantically compatible, only format compatible.

    You could (but not necessarily should) combine them by making the trunkver the "patch" part of semver.

    In our work, the semver is kept separate from the build version. We use a build versioning of vYYYY-MM-DD[.hhh] where hhh is for a "hotfix" of a previously released version.

    The version of the "next" release can be set (either in advance, or based on a sprint or just the current date).

    • nickez 7 days ago |
      It would be semver compatible if they used 0.DATE.0 or 0.0.DATE instead.

      from semver spec:

      4) Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.

  • cies 7 days ago |
    This is pretty much what we do already. Every docker image we push to the registry has a version like trunkVer (with only the first 2 components). The version is also put inside the image (in a file named /TAG) and is put in:

    * first log line

    * last log line

    * response headers

    * on some about page of the web app

    Difference with trunkVer: we do not have the last component (the CI bit), the first bit we use a more semVer-like scheme (major is bumped for marketing reasons, minor is bumped when it requires a new db schema, tiny is bumped for releases that are db schema compatible).

  • eisbaw 7 days ago |
    Versioning could also be determined from: 1. User-centric: Has --help changed? If not, it is minor bump. 2. Developer-centric: Will conflicts occur if a new commit is cherry-picked onto the prior release?

    I like linear Git histories, but image if we could "widen" a linear history maximally - so all non-conflicting commits "branch out" and only merge when needed.

  • hatta123 7 days ago |

      > The timestamp, followed by .0.0-, followed by the source reference, followed by -, followed by the build reference.
    
    but

      > EBNF Definition
      > MAJOR_TRUNKVER = TIMESTAMP, '.0.0-', BUILD_REF, '-', SOURCE_REF;
    
    Where's truth?
  • arwalk 7 days ago |
    > Semver compatible

    Right, just like if I were to write in english while only following the grammar rules, but without making any sense, it would be "english compatible" i guess.

    It's called _semantic_ versioning, and trunkver loses the whole point of it.

    The whole concept would have been better if it didn't even try to mention semver in the first place.

  • tpoacher 6 days ago |
    Meanwhile, the version number in the Trunkver github release is: 1.0.0-20241127214906-g1f8292a-12058740483-1

    (facepalm)

  • IOT_Apprentice 4 days ago |
    All I know is our development team is doing some of this for custom Linux images for a proprietary IIOT platform. We have an arm67 and x64 hardware. The arm hardware is our old platform running a very old OS and the x64 is our new hardware that only runs Linux.

    The version of the image is a timestamp like this.

    20241127214906

    Then in documentation it is sometimes described as 1.1

    Looking at that timestamp tells me nothing other than the time it was built. It gives zero context when deployed to production units and determining what it actually is. Our developers provide no central source of truth about the mapping of a timestamp to a version now that we are converting units to production for customers.

    /etc/release is supposed to indicate the version and it contains a timestamp of 20241127214906. And what is our customer to make of that?

    It is extremely frustrating and I really don’t understand why this is being done. Going forward this is going to be a mess.

    Versions of products built via a devOps platform, should always allow cross references to a version and builds over time till formal gold master release.