Table of Contents

Summary

Information

Document Information

Author(s) Information

Discussion List

Introduction

Currently, PEAR (and by extension, PEAR2) coding standards forbid breaking backwards compatibility in packages once they reach a stable state. This is due to the difficulty of protecting users from these breaks with the PEAR installer.

This limits innovation by developers and makes their lives harder for the benefit of users. Fortunately, there is a technical solution that can be incoporated into Pyrus that will solve the deficiency of the PEAR Installer.

The setting is called “paranoid.” This would work just like the “verbose” setting in PEAR (and Pyrus), so by passing multiple paranoid options, the paranoia would increase:

  php pyrus.phar -ppp upgrade Blah

would instruct Pyrus to set the paranoia level to 3. Here are the paranoia levels (and what they mean):

  1. don't care (I know what I'm doing, upgrade the dang thing)
  2. no BC breaks (I'm busy, just don't let it break my stuff)
  3. security fixes only (I rely on the API heavily, but I want to keep it secure even if it risks breaking things)
  4. no API changes under any circumstance (I have nightmares terrorists will use my server farm to launch nuclear attacks. I sleep with an uzi under my pillow)

in technical terms:

  1. any X.Y.Z API version is fine
  2. X must not change, Y and Z can change (if installed API version is 1.2.3, any 1.Y.Z can be installed)
  3. X and Y cannot change, Z can change (if installed API version is 1.2.3, any 1.2.Z can be installed)
  4. X, Y and Z cannot change.

By default, pyrus will set paranoia to “2”, so that BC breaking releases are never upgraded to. The user can override this simply through:

  php pyrus.phar -p upgrade Blah

or

  php pyrus.phar set paranoia 1

to change the default paranoia to “1”

Thus in our example above, User X would not be able upgrade to the new release without explicitly requesting it (although Pyrus would notify him that if he were less paranoid, he could upgrade).

Summary

This document describes the versioning standards for the PEAR2 repository that will make the paranoia setting work, and defines the version and api numbering process when backwards compatibility is broken.

Breaking backwards compatibility requires changing the major 'A' in the A.P.I version. Once a package has been released as 'stable' the changing the major 'A' in the A.P.I version requires changing the major version 'X' in the X.Y.Z version in the package version.

Approach & Requirements

Packages that wish to be accepted into the PEAR2 repository must conform to these standards

Definition

All packages must actively manage the API version and stability in addition to the Release version and stability.

First, some framework basics:

  1. The first API version of a new, non-stable package shall be 0.1.0
  2. The API version of any beta/release candidate prior to a stable release shall be the same as the stable release, so for example, version 1.0.0RC1 shall have API version 1.0.0
  3. The API version of the first stable release shall be 1.0.0, independent of the following rules

otherwise, API version shall be set by the following pseudo-code:

 $version = lastAPIversion();
 $version = explode($version);
 $stability = APIStability();
 $X = $version[0];
 $Y = $version[1];
 $Z = $version[2];
 if ($X >= 1 && First release breaking backwards compatibility) {
     $X += 1;
     $Y = 0;
     $Z = 0; // so version 1.2.3 becomes 2.0.0 or 2.0.0a1 for alpha, 2.0.0b1 for beta API, etc.
     if ($X >= 1) {
         if ($stability will be alpha) {
             $Z .= 'a1'; // version 1.2.3 would become 2.0.0a1
         } elseif ($stability will be beta) {
             $Z .= 'b1'; // version 1.2.3 would become 2.0.0b1
         }
     }
 } elseif (adding new features) {
     $Y += 1;
     $Z = 0; // so version 1.2.3 becomes 1.3.0
 } elseif (fixing bugs in API only) {
     $Z += 1; // so version 1.2.3 becomes 1.2.4
 }

An “API bug” is defined as a mismatch between the program's behavior and the documented behavior.

The next section addresses release version.

First, some framework basics:

  1. The first Release version of a new, non-stable package shall be 0.1.0
  2. The first Release version of a release candidate shall be 1.0.0RC1
  3. The first Release version of release candidates for major changes shall have “RC1” appended to the stable release (1.2.0RC1, 2.0.0RC1, etc.)
  4. The Release version of the first stable release shall be 1.0.0, independent of the following rules

otherwise, Release version shall be set by the following pseudo-code:

 $version = lastreleaseversion();
 $version = explode($version);
 $stability = releaseStability;
 $X = $version[0];
 $Y = $version[1];
 $Z = $version[2];
 if ($X >= 1 && (First release (breaking backwards compatibility -or- adding major new features))) {
     $X += 1;
     $Y = 0;
     $Z = 0; // so version 1.2.3 becomes 2.0.0
     if ($X >= 1) {
         if (will be alpha) {
             $Z .= 'a1'; // version 1.2.3 would become 2.0.0a1
         } elseif (will be beta) {
             $Z .= 'b1'; // version 1.2.3 would become 2.0.0b1
         }
     }
 } elseif (adding new features) {
     $Y += 1;
     $Z = 0; // so version 1.2.3 becomes 1.3.0
 } elseif (fixing bugs only) {
     $Z += 1; // so version 1.2.3 becomes 1.2.4
 }

Other Examples

For the next release after version 0.1.0/0.1.0 (API/Release):

 still unstable:
 Breaking BC: API 0.2.0, Release 0.2.0
 Adding major features: API 0.2.0, Release 0.2.0
 Adding minor features: API 0.2.0, Release 0.2.0
 bugfix: API 0.1.0, Release 0.1.1
 API bugfix: API 0.1.1, Release 0.1.1
 moving to beta: API 0.2.0, Release 0.2.0
 moving to release candidate: API 1.0.0, Release 1.0.0RC1
 next release candidate: API 1.0.0, Release 1.0.0RC2
 moving to stable: API 1.0.0, Release 1.0.0

For the next release after version 1.0.0/1.0.0 (API/Release):

 moving to alpha:
 Breaking BC: API 2.0.0a1, Release 2.0.0a1
 Adding major features: API 1.1.0a1, Release 2.0.0a1
 Adding minor features: API 1.1.0a1, Release 1.1.0a1
 bugfix: <not applicable>
 API bugfix: <not applicable>
 moving to beta:
 Breaking BC: API 2.0.0b1, Release 2.0.0b1
 Adding major features: API 1.1.0b1, Release 2.0.0b1
 Adding minor features: API 1.1.0b1, Release 1.1.0b1
 bugfix: <not applicable>
 API bugfix: <not applicable>
 moving to release candidate:
 Breaking BC: API 2.0.0, Release 2.0.0RC1
 Adding major features: API 1.1.0, Release 2.0.0RC1
 Adding minor features: API 1.1.0, Release 1.1.0RC1
 bugfix: <not applicable>
 API bugfix: <not applicable>
 moving to stable:
 Breaking BC: API 2.0.0, Release 2.0.0 <This is *not* recommended ever>
 Adding major features: API 1.1.0, Release 2.0.0
 Adding minor features: API 1.1.0, Release 1.1.0
 bugfix: API 1.0.0, Release 1.0.1
 API bugfix: API 1.0.1, Release 1.0.1

A typical life cycle

 API 0.1.0/alpha,     Release 0.1.0/alpha
 API 0.1.0/alpha,     Release 0.1.1/alpha    <-- bugfix
 API 0.1.1/alpha,     Release 0.1.2/alpha    <-- API bugfix, bugfix
 API 0.2.0/alpha,     Release 0.2.0/alpha    <-- major new features, bugfix
 API 0.3.0/alpha,     Release 0.3.0/alpha    <-- minor new features, bugfix
 API 0.4.0/beta,      Release 0.4.0/beta     <-- bugfix, minor new features
 API 1.0.0/stable,    Release 1.0.0RC1/beta  <-- bugfix, API freeze
 API 1.0.0/stable,    Release 1.0.0RC2/beta  <-- bugfix, API frozen
 API 1.0.1/stable,    Release 1.0.0RC3/beta  <-- API bugfix, bugfix
 API 1.0.1/stable,    Release 1.0.0/stable   <-- ready for production use
 API 1.0.1/stable,    Release 1.0.1/stable   <-- bugfix
 API 1.0.1/stable,    Release 1.0.2/stable   <-- bugfix
 API 1.0.2/stable,    Release 1.0.3/stable   <-- bugfix, API bugfix
 API 1.1.0/stable,    Release 1.1.0/stable   <-- minor feature addition
 API 1.1.0/stable,    Release 1.1.1/stable   <-- bugfix
 API 1.2.0a1/alpha,   Release 1.2.0a1/alpha  <-- major feature addition (note that this could be 2.0.0a1 as well, it is up to the developer)
 API 1.2.0a2/alpha,   Release 1.2.0a2/alpha  <-- bugfix, API bugfix
 API 1.2.0b1/beta,    Release 1.2.0a3/alpha  <-- API stabilizing, code still unstable, bugfix
 API 1.2.0/stable,    Release 1.2.0RC1/beta  <-- API frozen, code stable, bugfix
 API 1.2.0/stable,    Release 1.2.0/stable   <-- ready for production use
 API 2.0.0a1/alpha    Release 2.0.0a1/alpha  <-- Backwards compatibility break
 API 2.0.0b1/beta     Release 2.0.0a2/alpha  <-- API stabilizing, code still unstable, bugfix
 API 2.0.0/stable     Release 2.0.0b1/beta   <-- API stable, frozen, code still unstable, bugfix
 API 2.0.0/stable     Release 2.0.0RC1/beta  <-- code stable, API stable, bugfix
 API 2.0.0/stable     Release 2.0.0/stable   <-- ready for production use

Expiration

This standard will become a part of the PEAR2 standards, and expire at the same time the PEAR2 standards expire.

Security Considerations

None