Difference between revisions of "Versioning"

From ProgClub
Jump to: navigation, search
(note about constants...)
 
(16 intermediate revisions by the same user not shown)
Line 1: Line 1:
OK, here's the spec for how version numbers should be managed across ProgClub projects (from now on).
+
OK, here's the spec for how version numbers should be managed across [[ProgClub]] [[projects]]. It is highly recommended that you use [[svnman]] to help manage version numbers for ProgClub projects.
  
We will endeavour to be compatible with [http://semver.org/ Semantic Versioning] (v2.0.0 at time of writing).
+
= Semantic versioning =
  
So our semantic versioning is: <nowiki>MAJOR.MINOR.PATCH[-BUILD.REVISION]</nowiki>
+
We will endeavour to be compatible with [http://semver.org/ Semantic Versioning] (v2.0.0 at time of writing). Thus, this specification is a superset of the SemVer spec.
  
Our MAJOR.MINOR component will be resident in the Subversion path, e.g. project/branches/3.0 for MAJOR.MINOR version 3.0. The MAJOR and MINOR version numbers will also be in [[#Software_constants|software constants]] (see below).
+
= Specification =
  
Our PATCH version will not be in the Subversion path, but will be in a [[#Software_constants|software constant]] (see below).
+
So our semantic versioning format is: <nowiki>MAJOR.MINOR.PATCH[-BUILD.REVISION]</nowiki>
  
Our BUILD is one of, e.g. 'dev', 'alpha', 'beta', 'test', 'prod', etc. The BUILD is specified in the config file, not in the software. If the BUILD is unspecified the BUILD.REVISION component of the version number is omitted.
+
For information about how to model/store version information in your code see [[#Software_constants|software constants]] below.
 +
 
 +
== MAJOR version ==
 +
 
 +
The first MAJOR version number is zero (0). Version zero is a development version and breaking changes are allowed. The first release version has major version one (1). Version one is the first generally available version and breaking changes are allowed. The first stable version has major version two (2). After version two any breaking changes require that the MAJOR version number increments. So major versions are: 0, 1, 2, 3, and so on.
 +
 
 +
== MINOR version ==
 +
 
 +
The first MINOR version number is one (1). So 0.1 is the first version. There is no 0.0 version.
 +
 
 +
When the MAJOR version is incremented the MINOR version is reset to 0, so the new version would be e.g. 1.0, and so on.
 +
 
 +
Please don't use leading zeros on the MINOR version.
 +
 
 +
== PATCH number ==
 +
 
 +
Our PATCH number begins at one (1) and increments by two (2) upon each commit. The PATCH number is not reset after MAJOR or MINOR version bumps, its value is inherited from the value it was immediately prior to the version bump. Before a project is released the PATCH is incremented by one (1), and after a release it is again incremented by one (1). This means that the PATCH version number has the property of being odd for development builds and even for release builds (also called production builds).
 +
 
 +
== BUILD indicator ==
 +
 
 +
Our BUILD is one of, e.g. 'dev', 'test', 'alpha', 'beta', 'prod', etc. The BUILD is specified in the config file, not in the software. If the BUILD is unspecified the BUILD.REVISION component of the version number is omitted. When there is no BUILD.REVISION the software is an officially released version.
 +
 
 +
=== Build codes ===
 +
 
 +
OK, so at the moment supported build codes are:
 +
 
 +
{|class="wikitable"
 +
! dev
 +
| software is under development
 +
|-
 +
! test
 +
| software is running unit tests
 +
|-
 +
! alpha
 +
| pre-release software (never actually used it!)
 +
|-
 +
! beta
 +
| initial release for testing
 +
|-
 +
! rc-1
 +
| release candidate one
 +
|-
 +
! rc-2
 +
| release candidate two (and so on)
 +
|-
 +
! prod
 +
| software is running in production but interface might not be stable
 +
|-
 +
! N/A
 +
| when there is no build type the software is released at the indicated version
 +
|}
 +
 
 +
== REVISION number ==
  
 
Our REVISION is the Subversion revision number of the software. The REVISION is calculated by running 'svn info' and retrieving the 'Revision:' value. The 'svn info' command can be run at install time with the REVISION stored in the config file, or if there is no setting in the config file then 'svn info' can be run at runtime. If the REVISION cannot be determined it is zero.
 
Our REVISION is the Subversion revision number of the software. The REVISION is calculated by running 'svn info' and retrieving the 'Revision:' value. The 'svn info' command can be run at install time with the REVISION stored in the config file, or if there is no setting in the config file then 'svn info' can be run at runtime. If the REVISION cannot be determined it is zero.
  
= Software constants =
+
= Implementation =
 +
 
 +
== Subversion integration ==
 +
 
 +
Our MAJOR.MINOR component will be resident in the Subversion path, e.g. project/branches/3.0 for MAJOR.MINOR version 3.0. For a release we will indicate a PATCH number for the release script.
 +
 
 +
So the MAJOR, MINOR, and PATCH numbers are in Subversion. BUILD and RELEASE numbers are not in Subversion, they must be provided in configuration files shipped with a release (or not, in which case it becomes the responsibility of the system administrator to make sure the software is properly configured to indicate its BUILD/REVISION). Note: if the BUILD/REVISION are not specified they are assumed to be irrelevant, and for production/stable releases this is what we want. So only development and testing versions need to configure BUILD and REVISION...
 +
 
 +
== Software constants ==
  
 
So minimally we'd have:
 
So minimally we'd have:
Line 39: Line 99:
 
   
 
   
 
     // note: parse_svn_info_revision() returns zero on error
 
     // note: parse_svn_info_revision() returns zero on error
     define( 'VERSION_REVISION', parse_svn_info_revision() );
+
     define( 'VERSION_REVISION', [https://www.progclub.org/pcrepo/phpbom/branches/0.1/src/util/version.php?revision=3306&sortby=date#l110 parse_svn_info_revision()] );
 
   
 
   
 
   }
 
   }
Line 51: Line 111:
 
   
 
   
 
  }
 
  }
 +
 +
= Conclusion =
  
 
Happy days!
 
Happy days!

Latest revision as of 13:40, 5 March 2020

OK, here's the spec for how version numbers should be managed across ProgClub projects. It is highly recommended that you use svnman to help manage version numbers for ProgClub projects.

Semantic versioning

We will endeavour to be compatible with Semantic Versioning (v2.0.0 at time of writing). Thus, this specification is a superset of the SemVer spec.

Specification

So our semantic versioning format is: MAJOR.MINOR.PATCH[-BUILD.REVISION]

For information about how to model/store version information in your code see software constants below.

MAJOR version

The first MAJOR version number is zero (0). Version zero is a development version and breaking changes are allowed. The first release version has major version one (1). Version one is the first generally available version and breaking changes are allowed. The first stable version has major version two (2). After version two any breaking changes require that the MAJOR version number increments. So major versions are: 0, 1, 2, 3, and so on.

MINOR version

The first MINOR version number is one (1). So 0.1 is the first version. There is no 0.0 version.

When the MAJOR version is incremented the MINOR version is reset to 0, so the new version would be e.g. 1.0, and so on.

Please don't use leading zeros on the MINOR version.

PATCH number

Our PATCH number begins at one (1) and increments by two (2) upon each commit. The PATCH number is not reset after MAJOR or MINOR version bumps, its value is inherited from the value it was immediately prior to the version bump. Before a project is released the PATCH is incremented by one (1), and after a release it is again incremented by one (1). This means that the PATCH version number has the property of being odd for development builds and even for release builds (also called production builds).

BUILD indicator

Our BUILD is one of, e.g. 'dev', 'test', 'alpha', 'beta', 'prod', etc. The BUILD is specified in the config file, not in the software. If the BUILD is unspecified the BUILD.REVISION component of the version number is omitted. When there is no BUILD.REVISION the software is an officially released version.

Build codes

OK, so at the moment supported build codes are:

dev software is under development
test software is running unit tests
alpha pre-release software (never actually used it!)
beta initial release for testing
rc-1 release candidate one
rc-2 release candidate two (and so on)
prod software is running in production but interface might not be stable
N/A when there is no build type the software is released at the indicated version

REVISION number

Our REVISION is the Subversion revision number of the software. The REVISION is calculated by running 'svn info' and retrieving the 'Revision:' value. The 'svn info' command can be run at install time with the REVISION stored in the config file, or if there is no setting in the config file then 'svn info' can be run at runtime. If the REVISION cannot be determined it is zero.

Implementation

Subversion integration

Our MAJOR.MINOR component will be resident in the Subversion path, e.g. project/branches/3.0 for MAJOR.MINOR version 3.0. For a release we will indicate a PATCH number for the release script.

So the MAJOR, MINOR, and PATCH numbers are in Subversion. BUILD and RELEASE numbers are not in Subversion, they must be provided in configuration files shipped with a release (or not, in which case it becomes the responsibility of the system administrator to make sure the software is properly configured to indicate its BUILD/REVISION). Note: if the BUILD/REVISION are not specified they are assumed to be irrelevant, and for production/stable releases this is what we want. So only development and testing versions need to configure BUILD and REVISION...

Software constants

So minimally we'd have:

define( 'VERSION_MAJOR', 3 );
define( 'VERSION_MINOR', 0 );
define( 'VERSION_PATCH', 0 );
define( 'VERSION_BASE', VERSION_MAJOR . '.' . VERSION_MINOR . '.' . VERSION_PATCH );

The above four constants are "hard coded" into the software by the developer. It's the developer's responsibility to ensure that the values are correct and in sync with the project branch name in the repository.

Then we'd need to load our config file, which may have a BUILD type, e.g.:

define( 'VERSION_BUILD', 'dev' );

There might also be a REVISION in the config file, e.g.:

define( 'VERSION_REVISION', 1234 );

After loading the config file the full version must be calculated. E.g.:

if ( defined( 'VERSION_BUILD' ) ) {

  if ( ! defined( 'VERSION_REVISION' ) ) {

    // note: parse_svn_info_revision() returns zero on error
    define( 'VERSION_REVISION', parse_svn_info_revision() );

  }

  define( 'VERSION', VERSION_BASE . '-' . VERSION_BUILD . '.' . VERSION_REVISION );

}
else {

  define( 'VERSION', VERSION_BASE );

}

Conclusion

Happy days!

p.s. If your program is just an application you can use constants such as VERSION_MAJOR, VERSION, etc. If your program is a library you should scope your constants, e.g. PHPBOM_VERSION_MAJOR, PHPBOM_VERSION, etc.

p.p.s. If your programming language doesn't allow for generation of constants at runtime, you will need to model the BUILD and REVISION values some other way. E.g. as global variables, static variables in accessor functions, etc.