Monday 29 September 2014

Eclipse Plugin Version Numbering

Eclipse, version numbers are composed of four (4) segments: 3 integers and a string respectively named major.minor.service.qualifier.

Each segment captures a different intent:
  • the major segment indicates breakage in the API
  • the minor segment indicates "externally visible" changes
  • the service segment indicates bug fixes and the change of development stream.
  • the qualifier segment indicates a particular build
When to change the major segment:
The major segment number must be increased when a plug-in makes breaking changes to its API. When the major segment is changed the minor and service segments are reset to 0.
Example: From the version 1.3.6, an incompatible change would lead to 2.0.0. 

When to change the minor segment:
The minor segment number must be incremented when a plug-in changes in an "externally visible" way. Examples of externally visible changes include binary compatible API changes, significant performance changes, major code rework, etc. Another way to know when this version number should be changed is by exclusion: it should indicate changes that are neither bug fixes (indicated by the service segment) nor breaking API changes (indicated by the major segment). When the minor segment is changed, the service segment is reset to 0.
Example: From the version 1.3.6, a minor change would lead to 1.4.0.

When to change the service segment:
The service segment number must be incremented whenever there have been changes to a plug-in between releases that are not visible in its API. For example, a bug has been fixed in the code, the plug-in manifest has changed, documentation has changed, compiler settings have changed. In general, if that change happens in a service (a.k.a. maintenance) release, then 1 is added. If it happens for the next official release, 100 has to be added. As a result, the service segment number for official releases normally ends with a zero (0, 100, 200, etc.). If that is not true for whatever reason, then one must not add 100 but instead set the service segment number to the next number that is divisible by 100, so that the normal numbering scheme is restored. This practice makes it easy to manage one line of descent after a release and still guarantee that plug-ins coming in the next release will have a higher version number than ones from maintenance releases (thus enabling the usage of update manager from maintenance releases to the new releases).
Example: At the end of the development stream N, the version of the plug-in P is 2.4.0. When P makes its first change in the development stream N+1, then the version should be changed to 2.4.100. If P version 2.4.0 needs to receive a bug fix in the maintenance stream started from N, then its version number will be 2.4.1.

First development stream
 - 1.0.0

Second development stream
 - 1.0.100 (indicates a bug fix)
 - 1.1.0 (a new API has been introduced)
 The plug-in ships as 1.1.0

Third development stream
 - 1.1.100 (indicates a bug fix)
 - 2.0.0 (indicates a breaking change)
 The plug-in ships as 2.0.0

Maintenance stream after 1.1.0
 - 1.1.1
 The plug-in ships as 1.1.1


Plug-ins with no API:
There are certain kinds of plug-ins that have no API, and therefore would never evolve more than their service segment according to the above rules. For these plug-ins, the version number can be evolved in sync with another plug-in they are associated with. Note that since these plug-ins do not contain any API, they are generally only explicitly required by plug-ins they are closely associated with anyway.

In particular, a source/test/documentation plug-in that has changes in the current stream should evolve its version number in sync with the plug-in(s) it is providing source/test/documentation for. A fragment with no API should evolve its version number in sync with its host plug-in.

Versioning plug-ins that wrap external libraries:
The version range guidelines above are only effective if the required bundle or feature follows the Eclipse version number evolution guidelines outlined in this document. When specifying a dependency on third party libraries (e.g. those from Orbit), be sure you understand the semantics of that library's version numbers, and specify your version range accordingly. In the absence of any well defined version evolution semantics, you should just specify the version number you require as a lower bound.

Example: JFace requires a third party library wrapped in bundle com.xyz.widgets, and is compiled against version 3.8.1 of that bundle. It should specify its dependency as follows: Require-Bundle: com.xyz.widgets;bundle-version="3.8.1"