Semantic Versioning: Difference between revisions
(27 intermediate revisions by the same user not shown) | |||
Line 5: | Line 5: | ||
=Internal= | =Internal= | ||
* [[Software Development#Semantic_Versioning|Software Development]] | * [[Software Development#Semantic_Versioning|Software Development]] | ||
* [[Changelog]] | |||
* [[Gitflow]] | |||
=Overview= | =Overview= | ||
Line 19: | Line 21: | ||
The public API may be a formal code API or simply just documentation that describes how the software works. It is important that the API be clear and precise. Once the public API is declared, changes to it are declared by incrementing the version numbers: [[#Major_Version|major]], [[#Minor_Version|minor]] and [[#Patch_Version|patch]]. | The public API may be a formal code API or simply just documentation that describes how the software works. It is important that the API be clear and precise. Once the public API is declared, changes to it are declared by incrementing the version numbers: [[#Major_Version|major]], [[#Minor_Version|minor]] and [[#Patch_Version|patch]]. | ||
== | ==<span id='Normal_Version'></span><span id='Core_Version'></span>Normal (Core) Version== | ||
{{External|https://semver.org/#spec-item-2}} | |||
'''Normal''' version, or version '''core''', as designated by [[#Grammar|grammar]], consists in dot-separated [[#Major_Version|major version]], [[#Minor_Version|minor version]] and [[#Patch|patch]]. | |||
===Major Version=== | |||
The major version is | The major version component is used to indicate backward incompatible [[#Public_API|public API]] changes. | ||
When the major version is incremented, the [[#Minor_Version|minor version]] and the [[#Patch_Version|patch version]] are both reset to 0. | When the major version is incremented, the [[#Minor_Version|minor version]] and the [[#Patch_Version|patch version]] are both reset to 0. | ||
Line 31: | Line 34: | ||
Major version numbers are non-negative integers, must not contain extra leading zeroes and it always must increase numerically. | Major version numbers are non-negative integers, must not contain extra leading zeroes and it always must increase numerically. | ||
==Minor Version== | Incompatible changes (major version upgrades) should not be introduced lightly to software that has a lot of dependent code. The cost that must be incurred to upgrade can be significant. Having to increment major versions to release incompatible changes means that thought must be given to the impact of the changes, and evaluate the cost/benefit ratio involved. | ||
If a backward incompatible release is published as a minor version upgrade, a new minor version that corrects the problem should be released as soon as the problem is identified. It is not acceptable to modify versioned releases. | |||
====Major Version in the Initial Development Phase==== | |||
The major versions start at 0, which means that the software is in development phase and no guarantees can be made about the stability and the backward compatibility of of the [[#Public_API|public API]]. Anything may change at any time, and the public API should not be considered stable. At this stage, the simplest thing to do is to start the initial development release at 0.1.0 and then increment the minor version for each subsequent release. | |||
The major version is set to 1 (and consequently minor and patch versions to 0.0) when the software is first released publicly. Version 1.0.0 define the first public API. From that moment on, the major version is incremented when the a version that comes with backward-incompatible [[#Public_API|public API]] changes is released. | |||
===Minor Version=== | |||
The minor version component is used to indicate backward compatibly functionality additions or changes. To qualify for a minor (and not major) version increase, the change MUST be backward compatible: clients that worked with X.1.10 also work with X.2.0 without noticing. Minor version must be incremented if any public API functionality is marked as deprecated. Minor version may be incremented if substantial new functionality or improvements are introduced in the private code, without affecting the public API. | The minor version component is used to indicate backward compatibly functionality additions or changes. To qualify for a minor (and not major) version increase, the change MUST be backward compatible: clients that worked with X.1.10 also work with X.2.0 without noticing. Minor version must be incremented if any public API functionality is marked as [[#Deprecated_Functionality|deprecated]]. Minor version may be incremented if substantial new functionality or improvements are introduced in the private code, without affecting the public API. | ||
When the minor version is incremented, the [[#Patch_Version|patch version]] is reset to 0. | When the minor version is incremented, the [[#Patch_Version|patch version]] is reset to 0. | ||
Line 39: | Line 52: | ||
Minor version numbers are non-negative integers, must not contain extra leading zeroes and it always must increase numerically. | Minor version numbers are non-negative integers, must not contain extra leading zeroes and it always must increase numerically. | ||
==Patch== | ===Patch=== | ||
The patch version component is used to indicate backward compatibly bug fixes that only affect implementation and do not change the public API in any way. A bug fix is defined as an internal change that fixes incorrect behavior. | The patch version component is used to indicate backward compatibly bug fixes that only affect implementation and do not change the public API in any way. A bug fix is defined as an internal change that fixes incorrect behavior. | ||
Line 51: | Line 64: | ||
==Pre-Release Version== | ==Pre-Release Version== | ||
{{External|https://semver.org/#spec-item-9}} | |||
A pre-release version is denoted by appending a hyphen and a series of dot-separated identifiers, immediately following the [[#Patch_Version|patch version]]: | |||
<syntaxhighlight lang='text'> | |||
<version core> "-" <pre-release> | |||
<version core> "-" <pre-release> "+" <build> | |||
</syntaxhighlight> | |||
where: | |||
<syntaxhighlight lang='text'> | |||
<pre-release> ::= <dot-separated pre-release identifiers> | |||
<dot-separated pre-release identifiers> ::= <pre-release identifier> | |||
| <pre-release identifier> "." <dot-separated pre-release identifiers> | |||
<pre-release identifier> ::= <alphanumeric identifier> | |||
| <numeric identifier> | |||
</syntaxhighlight> | |||
<syntaxhighlight lang='text'> | |||
1.0.0-CR.1, 1.0.0-Alpha | |||
</syntaxhighlight> | |||
Pre-releases have a [[#Version_Precedence|lower precedence]] than the associated dot version | Pre-releases have a [[#Version_Precedence|lower precedence]] than the associated dot version. They indicate that the version is unstable and they might not satisfy the intended compatibility requirements. Two different pre-releases associated with the same release have a precedence relationship. For more details, see [[#Pre-Release_Precedence|Pre-Release Precedence]] section. | ||
Identifiers must include only ASCII alphanumerics and hyphen [0-9A-Za-z-], must not include leading zeroes and must not be empty. | Identifiers must include only ASCII alphanumerics and hyphen [0-9A-Za-z-], must not include leading zeroes and must not be empty. | ||
==Build Metadata== | ==Build Metadata== | ||
{{External|https://semver.org/#spec-item-10}} | |||
Build metadata is denoted by appending a plus sign and a series of dot-separated identifiers immediately following the [[#Patch_Version|patch]] or [[#Pre-Release_Version|pre-release]] version. Build metadata must be ignored when determining the [[#Version_Precedence|version precedence]]: two versions that differ only by build metadata have the same precedence. | Build metadata is denoted by appending a plus sign and a series of dot-separated identifiers immediately following the [[#Patch_Version|patch]] or [[#Pre-Release_Version|pre-release]] version. Build metadata must be ignored when determining the [[#Version_Precedence|version precedence]]: two versions that differ only by build metadata have the same precedence. For more details see [[#Build_Metadata_Precedence|Build Metadata Precedence]] section. | ||
Identifiers must comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-] and must not be empty. | Identifiers must comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-] and must not be empty. | ||
<syntaxhighlight lang='text'> | |||
<version core> "+" <build> | |||
<version core> "-" <pre-release> "+" <build> | |||
</syntaxhighlight> | |||
<syntaxhighlight lang='text'> | |||
<build> ::= <dot-separated build identifiers> | |||
<dot-separated build identifiers> ::= <build identifier> | |||
| <build identifier> "." <dot-separated build identifiers> | |||
<build identifier> ::= <alphanumeric identifier> | |||
| <digits> | |||
</syntaxhighlight> | |||
==Version Lock== | ==Version Lock== | ||
Line 77: | Line 120: | ||
Precedence refers to how versions are compared to each other when ordered. Version precedence is calculated by separating the version into [[#Major_Version|major]], [[#Minor_Version|minor]], [[#Patch_Version|patch]] and [[#Pre-Release_Version|pre-release]] identifiers, in this order, and comparing the same classes of components. The first difference from left to right determines precedence. Major, minor and patch components are always compared numerically. | Precedence refers to how versions are compared to each other when ordered. Version precedence is calculated by separating the version into [[#Major_Version|major]], [[#Minor_Version|minor]], [[#Patch_Version|patch]] and [[#Pre-Release_Version|pre-release]] identifiers, in this order, and comparing the same classes of components. The first difference from left to right determines precedence. Major, minor and patch components are always compared numerically. | ||
<syntaxhighlight lang='text'> | |||
1.0.0 < 2.0.0 < 2.1.0 < 2.1.1 | |||
</syntaxhighlight> | |||
===Pre-Release Precedence=== | |||
[[#Pre-Release_Version|Pre-release versions]] have a lower precedence than their associated normal (dot) version. Precedence for two pre-release versions with the same major, minor, and patch version is determined by comparing each dot separated identifier from left to right until a difference is found as follows: identifiers consisting of only digits are compared numerically and identifiers with letters or hyphens are compared lexically in ASCII sort order. Numeric identifiers always have lower precedence than non-numeric identifiers. A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal. | [[#Pre-Release_Version|Pre-release versions]] have a lower precedence than their associated normal (dot) version. Precedence for two pre-release versions with the same major, minor, and patch version is determined by comparing each dot separated identifier from left to right until a difference is found as follows: identifiers consisting of only digits are compared numerically and identifiers with letters or hyphens are compared lexically in ASCII sort order. Numeric identifiers always have lower precedence than non-numeric identifiers. A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal. | ||
<syntaxhighlight lang='text'> | |||
2.1.1-1 < 2.1.1 | |||
</syntaxhighlight> | |||
===Build Metadata Precedence=== | |||
[[#Build_Metadata|Build metadata]] is ignored when determining the version precedence: two versions that differ only by build metadata have the same precedence. | [[#Build_Metadata|Build metadata]] is ignored when determining the version precedence: two versions that differ only by build metadata have the same precedence. | ||
==<span id='Deprecated_Functionality'></span>Deprecating Functionality== | |||
Deprecating functionality is a normal part of software development. When functionality is deprecated, a new [[#Minor_Version|minor version]] with the deprecated API in place should be released, along with documentation describing the deprecation. The functionality can then be removed in one of the subsequent major releases. | |||
=Regular Expressions= | |||
* https://regex101.com/r/Ly7O1x/3/ | |||
* https://regex101.com/r/vkijKf/1/ | |||
=Grammar= | =Grammar= | ||
Line 149: | Line 206: | ||
| "y" | "z" | | "y" | "z" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=Programming Languages Support= | |||
==Semantic Versioning in Go== | |||
{{Internal|Semantic_Versioning_in_Go#Overview|Semantic Versioning in Go}} | |||
==Semantic Versioning in Python== | |||
{{Internal|Semantic_Versioning_in_Python#Overview|Semantic Versioning in Python}} |
Latest revision as of 18:26, 18 March 2024
External
Internal
Overview
Semantic versioning is attaching meaning to a version label. The version label is used to communicate how the piece of software it is attached to changed in relation to other versions of the same piece of software. The semantic versioning specification comes with a set of rules that dictate how version numbers are assigned and incremented. The essential components of a semantic versioning-compliant version label are:
<major>.<minor>.<patch>[-pre-release-label][+build-metadata]
Concepts
Public API
The semantic versioning-compliant version labels carry meaning about the public API of the piece of software they are attached to. The public API describes how the software is consumed by its clients.
Semantic versioning only works if there is a public API to describe and track by versions - software using semantic versioning MUST declare a public API.
The public API may be a formal code API or simply just documentation that describes how the software works. It is important that the API be clear and precise. Once the public API is declared, changes to it are declared by incrementing the version numbers: major, minor and patch.
Normal (Core) Version
Normal version, or version core, as designated by grammar, consists in dot-separated major version, minor version and patch.
Major Version
The major version component is used to indicate backward incompatible public API changes.
When the major version is incremented, the minor version and the patch version are both reset to 0.
Major version numbers are non-negative integers, must not contain extra leading zeroes and it always must increase numerically.
Incompatible changes (major version upgrades) should not be introduced lightly to software that has a lot of dependent code. The cost that must be incurred to upgrade can be significant. Having to increment major versions to release incompatible changes means that thought must be given to the impact of the changes, and evaluate the cost/benefit ratio involved.
If a backward incompatible release is published as a minor version upgrade, a new minor version that corrects the problem should be released as soon as the problem is identified. It is not acceptable to modify versioned releases.
Major Version in the Initial Development Phase
The major versions start at 0, which means that the software is in development phase and no guarantees can be made about the stability and the backward compatibility of of the public API. Anything may change at any time, and the public API should not be considered stable. At this stage, the simplest thing to do is to start the initial development release at 0.1.0 and then increment the minor version for each subsequent release.
The major version is set to 1 (and consequently minor and patch versions to 0.0) when the software is first released publicly. Version 1.0.0 define the first public API. From that moment on, the major version is incremented when the a version that comes with backward-incompatible public API changes is released.
Minor Version
The minor version component is used to indicate backward compatibly functionality additions or changes. To qualify for a minor (and not major) version increase, the change MUST be backward compatible: clients that worked with X.1.10 also work with X.2.0 without noticing. Minor version must be incremented if any public API functionality is marked as deprecated. Minor version may be incremented if substantial new functionality or improvements are introduced in the private code, without affecting the public API.
When the minor version is incremented, the patch version is reset to 0.
Minor version numbers are non-negative integers, must not contain extra leading zeroes and it always must increase numerically.
Patch
The patch version component is used to indicate backward compatibly bug fixes that only affect implementation and do not change the public API in any way. A bug fix is defined as an internal change that fixes incorrect behavior.
Patch version numbers are non-negative integers, must not contain extra leading zeroes and it always must increase numerically.
Versioned Artifact Immutability
Once a versioned package has been released, the contents of that version must not be modified. Any modification must be released as a new version.
Pre-Release Version
A pre-release version is denoted by appending a hyphen and a series of dot-separated identifiers, immediately following the patch version:
<version core> "-" <pre-release>
<version core> "-" <pre-release> "+" <build>
where:
<pre-release> ::= <dot-separated pre-release identifiers>
<dot-separated pre-release identifiers> ::= <pre-release identifier>
| <pre-release identifier> "." <dot-separated pre-release identifiers>
<pre-release identifier> ::= <alphanumeric identifier>
| <numeric identifier>
1.0.0-CR.1, 1.0.0-Alpha
Pre-releases have a lower precedence than the associated dot version. They indicate that the version is unstable and they might not satisfy the intended compatibility requirements. Two different pre-releases associated with the same release have a precedence relationship. For more details, see Pre-Release Precedence section.
Identifiers must include only ASCII alphanumerics and hyphen [0-9A-Za-z-], must not include leading zeroes and must not be empty.
Build Metadata
Build metadata is denoted by appending a plus sign and a series of dot-separated identifiers immediately following the patch or pre-release version. Build metadata must be ignored when determining the version precedence: two versions that differ only by build metadata have the same precedence. For more details see Build Metadata Precedence section.
Identifiers must comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-] and must not be empty.
<version core> "+" <build>
<version core> "-" <pre-release> "+" <build>
<build> ::= <dot-separated build identifiers>
<dot-separated build identifiers> ::= <build identifier>
| <build identifier> "." <dot-separated build identifiers>
<build identifier> ::= <alphanumeric identifier>
| <digits>
Version Lock
Version lock is a situation that occurs in software development when the specification of the dependencies' version is too tight, so any upgrade of a dependency must be followed by an upgrade release of the dependent package.
Version Promiscuity
Version lock is a situation that occurs in software development when the specification of the dependencies' version is too loose, so an upgrade that introduces a significant, potentially backward incompatible change of a dependency is not reflected by a corresponding upgrade release of the dependent package. Version promiscuity is assuming compatibility with more future versions than is reasonable.
Version Precedence
Precedence refers to how versions are compared to each other when ordered. Version precedence is calculated by separating the version into major, minor, patch and pre-release identifiers, in this order, and comparing the same classes of components. The first difference from left to right determines precedence. Major, minor and patch components are always compared numerically.
1.0.0 < 2.0.0 < 2.1.0 < 2.1.1
Pre-Release Precedence
Pre-release versions have a lower precedence than their associated normal (dot) version. Precedence for two pre-release versions with the same major, minor, and patch version is determined by comparing each dot separated identifier from left to right until a difference is found as follows: identifiers consisting of only digits are compared numerically and identifiers with letters or hyphens are compared lexically in ASCII sort order. Numeric identifiers always have lower precedence than non-numeric identifiers. A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal.
2.1.1-1 < 2.1.1
Build Metadata Precedence
Build metadata is ignored when determining the version precedence: two versions that differ only by build metadata have the same precedence.
Deprecating Functionality
Deprecating functionality is a normal part of software development. When functionality is deprecated, a new minor version with the deprecated API in place should be released, along with documentation describing the deprecation. The functionality can then be removed in one of the subsequent major releases.
Regular Expressions
Grammar
<valid semver> ::= <version core>
| <version core> "-" <pre-release>
| <version core> "+" <build>
| <version core> "-" <pre-release> "+" <build>
<version core> ::= <major> "." <minor> "." <patch>
<major> ::= <numeric identifier>
<minor> ::= <numeric identifier>
<patch> ::= <numeric identifier>
<pre-release> ::= <dot-separated pre-release identifiers>
<dot-separated pre-release identifiers> ::= <pre-release identifier>
| <pre-release identifier> "." <dot-separated pre-release identifiers>
<build> ::= <dot-separated build identifiers>
<dot-separated build identifiers> ::= <build identifier>
| <build identifier> "." <dot-separated build identifiers>
<pre-release identifier> ::= <alphanumeric identifier>
| <numeric identifier>
<build identifier> ::= <alphanumeric identifier>
| <digits>
<alphanumeric identifier> ::= <non-digit>
| <non-digit> <identifier characters>
| <identifier characters> <non-digit>
| <identifier characters> <non-digit> <identifier characters>
<numeric identifier> ::= "0"
| <positive digit>
| <positive digit> <digits>
<identifier characters> ::= <identifier character>
| <identifier character> <identifier characters>
<identifier character> ::= <digit>
| <non-digit>
<non-digit> ::= <letter>
| "-"
<digits> ::= <digit>
| <digit> <digits>
<digit> ::= "0"
| <positive digit>
<positive digit> ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<letter> ::= "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J"
| "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T"
| "U" | "V" | "W" | "X" | "Y" | "Z" | "a" | "b" | "c" | "d"
| "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n"
| "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x"
| "y" | "z"