Constrained Semantic Versioning v1.0.0-rc.1

CSemVer Playground

CSemVer in action: browse the versions, test your mind!

Explore

Summary

CSemVer is an operational subset of Semantic Versioning 2.0.0 (http://semver.org) that is defined around one strong idea: CSemVer versions are totally ordered, each version corresponds to a unique 64 bits signed integer ranging from 1 (v0.0.0-alpha) to 4000050000000000000 (v99999.49999.9999).

CSemVer-CI is an extension that supports CI builds. Its versions follow SemVer 2.0.0, but are not CSemVer compliant. CSemVer-CI defines 2 kind of CI versions:

ZeroBased
Versions are based on the 0.0.0 very first version and are smaller than it. Any version of this kind has always a lower precedence than any version of actual releases.
LastReleasedBased
Versions are based on a previous release. They are greater than their base version but always lower than any successor of their base.

CSemVer and CSemVer-CI both offer long and short version forms. The short form is compatible with NuGet V2 version handling and are often considered more readable.

Clarification about SemVer 2.0.0 case sensitivity

SemVer does not clearly states whether versions should be considered case sensitive or case insensitive. Current implementations differ: NuGet (Windows ecosystem) uses case insensitive versions and npm (Linux) uses case sensitivity. Case sensitivity leads to surprising version precedence (1.0.0-RC < 1.0.0-alpha) and since Windows must be supported, we, as NuGet does, consider that SemVer versions MUST be considered case insensitive.

Rationales & examples

1 - CSemVer defines a totally ordered set of versions. This is used to generate and/or control versions that guaranty a correct application of precedence rules and coherency of the emitted artifacts. Each CSemVer version is associated to a unique integer that fits into Windows binary version number.

CSemVerShort form(1)Ordered VersionDescription
v0.0.0-alpha 0.0.0-a 1 The very first possible version is the 0.0.0 alpha (this is a MainPrerelease). There are 27 possible first versions (it can be 0.0.0, 0.1.0 and 1.0.0 with their 8 prereleases).
v0.0.0-alpha.1 0.0.0-a01 101 These are NumberedPreReleases. There can be 99 NumberedPreReleases for each MainPreRelease.
v0.0.0-alpha.2 0.0.0-a02 201
v0.0.0-alpha.0.1 0.0.0-a00-01 2 Oops! There was a bug in the very first alpha and someone, for any reason, needs a fix. This is a PatchPreRelease.
v1.0.0 1.0.0 40000500080001 The first Stable Release is a MajorRelease.
v1.0.1 1.0.1 40000500160002 A fix to the first Stable version: as a PatchRelease, it should contain only bug fixes, no breaking changes. (This is a Stable Release.)
v1.1.0 1.1.0 40001300090001 Introduction of new features but no breaking changes: welcome to the MinorRelease. (This is a Stable Release.)
v2.0.0-rc 2.0.0-r 80001000070001 A MainPreRelease that prepares the next MajorRelease.

(1) The origin of this Short form is that NuGet packaging system in its V2 version (2015) did not follow Semantic Versioning (the 'special name' - the prerelease part - was simply ordered lexically in ASCII sort order). Moreover this 'special name' could not exceed 20 characters. The latter is the reason why the Short form uses only the initial of the prerelease name (in order to support CSemVer-CI LastReleasedBased versionning).

2 - CSemVer makes possible to really control the versions that are published. The valid successors (according to Semantic Versioning rules) of any version can be computed (there can be up to 28 successors to a version) and, respectively, one can decide whether a version is a valid predecessor of any other version.

VersionSuccessors
v1.2.3
27 successors
v1.2.4-alpha, v1.2.4-beta, v1.2.4-delta, v1.2.4-epsilon, v1.2.4-gamma, v1.2.4-kappa, v1.2.4-prerelease, v1.2.4-rc, v1.2.4, v1.3.0-alpha ⇒(2) v1.3.0-rc, v1.3.0, v2.0.0-alpha ⇒ v2.0.0-rc, v2.0.0
v1.2.3-alpha
28 successors
v1.2.3-alpha.0.1, v1.2.3-alpha.1, v1.2.3-beta ⇒ v1.2.3-rc, v1.2.3, v1.3.0-alpha ⇒ v1.3.0-rc, v1.3.0, v2.0.0-alpha ⇒ v2.0.0-rc, v2.0.0
v1.2.3-delta.5
26 successors
v1.2.3-delta.5.1, v1.2.3-delta.6, v1.2.3-epsilon ⇒ v1.2.3-rc, v1.2.3, v1.3.0-alpha ⇒ v1.3.0-rc, v1.3.0, v2.0.0-alpha ⇒ v2.0.0-rc, v2.0.0
v1.2.3-prerelease.2.3
22 successors
v1.2.3-prerelease.2.4, v1.2.3-prerelease.3, v1.2.3-rc, v1.2.3, v1.3.0-alpha ⇒ v1.3.0-rc, v1.3.0, v2.0.0-alpha ⇒ v2.0.0-rc, v2.0.0
v1.2.3-rc
21 successors
v1.2.3-rc.0.1, v1.2.3-rc.1, v1.2.3, v1.3.0-alpha ⇒ v1.3.0-rc, v1.3.0, v2.0.0-alpha ⇒ v2.0.0-rc, v2.0.0

(2) The ⇒ replaces the list of the prerelease names from alpha, beta, delta, epsilon, gamma, kappa, prerelease up to rc.

3 - CI builds correspond to productions that are not actual releases: the version has to be automatically created since no real version exist for them. A CI build is defined by: a BuildIndex that is a number or an identifier that gets bigger for each new build (it is usually a simple integer that is provided by the CI process or a timestamp) and a CIBuildName that identifies the source, the nature, or any other constant key of the build (this is usually the name of the 'branch' in a SCM) .

CSemVer-CI enables the support of CI buils into CSemVer versions with the guaranty of a valid precedence order (in order to secure deployments). The two kind of versions offers two different guaranties:

ZeroBased
A ZeroBased version has a lower than precedence than any released package, even the very first possible one (v0.0.0-alpha). Risk that a product issued from the CI pollutes any production is highly improbable. One example is enough to understand it: 0.0.0--ci.15-develop (where BuildIndex is 15 and CIBuildName is 'develop'). The double dash (that is perfectly valid in Semantic Versioning 2.0.0) makes this version lower than any other CSemVer versions.
LastReleasedBased
As its name states, this versioning mode relies on the last release (be it Official or PreRelease). Such semantic versions have higher precedence than their base but lowest precedence than any successor of this base. Risk that a product issued from the CI pollutes any production is highly mitigated.
This implements a "post release" feature (see this issue on github) in Semantic Versionning 2.0.0 that, apparently, supports only a "pre release" feature: there is no 'magic', only a careful use of the precedence order rules (with the help of the double dash trick).

The table below helps understand how CSemVer-CI LastReleasedBased works.

CSemVer-CI LastReleasedBased samples where CIBuildName is 'develop' and BuldIndex is 15
Base VersionCI Version (PostRelease)Immediate successorDescription
v0.4.1-rc.2.1 0.4.1-rc.2.1.ci.15.develop v0.4.1-rc.2.2

PatchPreRelease

This is the simplest one: by appending a dotted part, the CI version has a greater precedence than its base.
"Base Version" < "CI Version" < "Immediate successor" is guaranteed here and for the 3 other cases below.
v3.2.1-rc.1 3.2.1-rc.1.0.ci.15.develop v3.2.1-rc.1.1

NumberedPreRelease

It is the "padding" with the .0 here that does the job.
v3.2.1-beta 3.2.1-beta.0.0.ci.15.develop v3.2.1-beta.0.1

MainPreRelease

The double 0 padding is required for pre release.
v1.2.3 1.2.4--ci.15.develop 1.2.4-alpha

Stable Release
(applies to Major, Minor and PatchRelease)

This uses the double dash trick of the ZeroBased kind, plus another one: the Patch is incremented by one.

Specifications

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

CSemVer

  1. CSemVer versions follow Semantic Versioning 2.0.0 rules but adds some constraints to them.

  2. Syntax of a CSemVer MUST be:

    [v|V]Major.Minor.Patch[-PreReleaseName[.PreReleaseNumber[.PreReleaseFix]]][+BuildMetaData]

  3. CSemVer versions MAY be prefixed with a 'v' or 'V' (GitHub convention). This is the only extension that is not supported by SemVer.

  4. The Major part MUST be defined between 0 and 99999.

  5. The Minor part MUST be defined between 0 and 49999.

  6. The Patch part MUST be defined between 0 and 9999.

  7. The PrereleaseName MAY be denoted by appending a hyphen and a name that MUST be one of the 8 values of the following list (ordered from 0 to 7): alpha, beta, delta, epsilon, gamma, kappa, pre (or prerelease), rc.

    The PrereleaseName's intial MAY be used as a short form: a, b, d, e, g, k, p, r.

    Any other name not listed in this set MUST be considered syntactically invalid.

  8. The PrereleaseNumber MAY be denoted by appending a dot and a number that MUST be defined between 0 and 99.

  9. The PrereleaseFix MAY be denoted by appending a dot and a number that MUST be defined between 1 and 99.

  10. The PrereleaseNumber 0 MUST appear only when a PrereleaseFix is specified to denote a fix of a first prerelease (v4.3.2-rc.0.2 is the second fix of v4.3.2-rc).

CSemVer-CI

  1. CSemVer-CI versions follow Semantic Version 2.0.0 rules.

  2. Syntax of a CSemVer-CI ZeroTimed MUST be:

    0.0.0--ci.BuildIndex.CIBuildName[+BuildMetaData] where the BuildMetaData SHOULD be the base version.

  3. The BuildIndex MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-] and MUST NOT be empty. It can be purely numeric.

  4. The CIBuildName MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-] and MUST NOT be empty.

  5. BuildIndex MUST increase between builds based on the same base version. It MAY be time based with a fixed format (ie. YYYYMMDD-HHMMSS), be an incremented number provided by the CI process or any other numeric or alphanumeric value as long as it is increasing (either numerically or lexically in ASCII sort order) for each build.

    In DSCM like Git or Mercurial this CAN be the maximum number of commits from the commit point up to the parent commit that defines the base version.

  6. Syntax of a CSemVer-CI LastReleasedBased MUST be:

About

The Constrained Semantic Versioning specification is authored by Signature Code.

If you'd like to leave feedback, please open an issue on GitHub.

License

Creative Commons - CC BY 3.0