29

All examples of semantic versioning I've seen show 3 components in use. No more than 2 period characters. At $DAYJOB, we use 4 components in our release numbers:

5.0.1.2

Does Semantic Versioning allow for this?

And as a higher-level and more arguable side question, does it really even matter? I started to think it might be a good idea to enforce semantic versioning, but ultimately entities like PCI override it.

I should have clarified on my PCI comment. The issue is that audits and their cost influence when the major and minor components change, not necessarily a true new feature. For example, if a feature related to payments is introduced, we bump the minor number for PCI. But if we add a brand new feature related to something in the gui, it doesn't. Only the patch changes. So in this case we don't really get a say in the matter as developers since someone else makes those decisions.

8
  • Semantic versioning is a guideline. Where does PCI state anything about how things are to be versioned?
    – user40980
    Oct 1, 2015 at 13:21
  • I should have clarified on my PCI comment. The issue is that audits and their cost influence when the major and minor components change, not necessarily a true new feature. For example, if a feature related to payments is introduced, we bump the minor number for PCI. But if we add a brand new feature related to something in the gui, it doesn't. Only the patch changes. So in this case we don't really get a say in the matter as developers since someone else makes those decisions. Oct 1, 2015 at 13:51
  • @void.pointer can you give an example of why you are using the fourth component then? Are you using it to basically bypass internal cost and accounting structures - letting your team track new features without bumping patch numbers?
    – enderland
    Oct 1, 2015 at 13:58
  • 4
    We also use 4 groups, and not 3. Why? Because C++. C++ has binary backward compatibility and source backward compatibility: the former implies the latter, but the relation is not symmetric. Thus, we use the 4th group for binary compatibility (you can hot-patch the system) and the 3rd for source compatibility (you need to re-compile, but you should not have to modify your own code). And you know what, it works for us! Oct 1, 2015 at 15:12
  • 1
    @papiro: The ABI of a library is defined by the source code of the library and the toolchain it is compiled with, so technically yes you can break the ABI by changing the toolchain and not the code. Since all users need to have a compatible toolchain, though, this is typically tracked of separately, so the same library, with the same version, will be delivered for multiple toolchains. Mar 18, 2022 at 8:26

2 Answers 2

32

It sounds like you are bypassing normal conventions just to avoid process overhead/audits. That... strikes me as concerning.

What you are doing is effectively making an extra version number (your minor PCI digit) somewhat intentionally in order to move your feature/minor version numbers back a place, to no longer trigger your internal audit criteria.


Anyways, getting to your question about semantic versioning, the spec for Semantic Versioning states:

Given a version number MAJOR.MINOR.PATCH, increment the:

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards-compatible manner, and
  • PATCH version when you make backwards-compatible bug fixes.
  • Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

Emphasis mine.

So the question is, are you using the fourth character for pre-release/build metadata? Or is it basically another version indication that you are releasing?

If "yes" then semantic versioning's spec does allow for it. If "no" then you technically are not following semantic versioning.

And as a higher-level and more arguable side question, does it really even matter?

Whether you want to rigidly follow it or not is a decision you and your team have to make. The purpose of semantic versioning is to help with API compatibility:

Bug fixes not affecting the API increment the patch version, backwards compatible API additions/changes increment the minor version, and backwards incompatible API changes increment the major version.

I call this system "Semantic Versioning." Under this scheme, version numbers and the way they change convey meaning about the underlying code and what has been modified from one version to the next.

It's a system that helps make it more clear when versioning affects downstream users of the API.

As long as your API is similarly clear it's not a huge deal which way you choose. Semantic versioning just happens to be straightforward, for example if I'm using 3.4.2 and need to upgrade to 3.4.10 I know I can do so without breaking anything. If the new version is 3.5.1 I know it's backwards compatible. And I know version 4.0.1 would be a breaking change.

That's all part of what the version numbers mean.

@enderland Yes basically. MAJOR(PCI).MINOR(PCI).FEATURE.HOTFIX+BUILD. We're basically only allowed to change the 3rd and 4th component without getting PCI (and subsequently the PCI overlords at the company) involved. To me it feels like this is a bit contrived, I am not sure they are justified in the way they manage the version number, but I do not know enough about PCI and audit process to say otherwise.

Ok, this is fine. You have a system which works for you and meets your needs. That's the point of versioning.

If your API is private (only internally facing) it really doesn't matter how you version as long as it makes sense to you and everyone using it. Where versioning in a standard format matters is when you have many other consumers of your API that need to know "what does this version mean?"

Having an arbitrary versioning system will confuse people who are used to other systems, such as semantic versioning. But if no-one is really using your versioning system except the people creating it - it doesn't really matter.

8
  • 1
    Concerning your edit at the top: Let me play devil's advocate here. PCI audits cost the company money, and not every feature implemented is of concern to them. So why incur cost and other overhead on principles alone? How is this so concerning? I realize the method of determining audits is probably flawed, but separation of concerns seems reasonable. Things not remotely related to card processing are irrelevant to PCI. Oct 1, 2015 at 15:05
  • @void.pointer I'm not in a position to judge why/how your audits are determined. But someone decided that they wanted to audit based on specific criteria. Intentionally bypassing that audit criteria seems concerning (regardless of how much money you save by doing so).
    – enderland
    Oct 1, 2015 at 15:11
  • 1
    @void.pointer, enderland is right. If a terrorist threatens to kill your family if your versions aren't composed entirely of alphabetic letters, the real problem is the terrorist. Feel free to not follow semantic versioning to work around it (in fact, I would strongly suggest it in this case), but it really is that: a workaround necessitated by a different problem. Oct 1, 2015 at 16:16
  • 1
    @PaulDraper When did semver become the One True Way to version?
    – Andy
    Oct 1, 2015 at 16:41
  • 1
    @Andy, it didn't. The OP asked about SemVer. IDK why, but that's what he did. Oct 1, 2015 at 16:45
11

In the current version of Semantic Versioning, which is 2.0.0, no. There is a requirement that defines the version as the form X.Y.Z where X, Y, and Z are non-negative integers that do not contain leading 0s:

A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes. X is the major version, Y is the minor version, and Z is the patch version. Each element MUST increase numerically. For instance: 1.9.0 -> 1.10.0 -> 1.11.0.

However, the ability to add metadata is allowed for:

Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata SHOULD be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85.

Something important to note, though, is that Semantic Versioning is specifically for software that declares a public API:

Software using Semantic Versioning MUST declare a public API. This API could be declared in the code itself or exist strictly in documentation. However it is done, it should be precise and comprehensive.

This tends to support the development of libraries or services and not at an application level.

The important thing to consider is what your version numbers mean, both to internal and external use. Versions are just identifiers that allow you to talk about differences in software at two different points in time. Semantic Versioning is one method of putting rules around this, so if you know that an application is using Semantic Versioning, then you can more easily determine the level of effort required to update your packages. Following a common standard may be good, but if you can't for any reason, documenting the rules for your users should also be sufficient.

1
  • +1 for the public API note. We do not have a public API but we do have the ability to break backward compatibility in other aspects, such as data. It's possible we ship a build that gets installed over old releases but data does not change, and we are no longer able to read in that data (usually we support the old formats though) Oct 1, 2015 at 13:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.