From Fedora Project Wiki
(Add minor bumps section back in.)
(Note that caret is merged into upstream RPM.)
 
(14 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{DISPLAYTITLE:Guidelines for Versioning Fedora Packages}}
== Notes for the tilde versioning drafts ==
<div style="float: right; margin-left: 0.5em" class="toclimit-2">__TOC__</div>


{{ admon/note |
There are two drafts:
This is a revised draft, which additionally removes snapshot info from <code>Release:</code>. The previous draft was shown to be unworkable in practice as required the introduction of <code>Epoch:</code> in a relatively common version sequence.}}
* [[User:Tibbs/TildeVersioning1]] allows tilde and moves prerelease snapshot information into the Version: tag.
* [[User:Tibbs/TildeVersioning2]] allows tilde but prohibits its use with prerelease snapshots.
* [[User:Tibbs/TildeCaretVersioning]] allows both tilde and caret versioning to keep Release: completely free of versioning information.  Caret versioning comes from https://github.com/rpm-software-management/rpm/pull/597.


Fedora's package versioning scheme encompasses both the <code>Version:</code> and <code>Release:</code> tags, as well as <code>Epoch:</code>)The overriding goal is to provide sequence of packages which are treated as updates by RPM's version comparison algorithm while accommodating varied and often inconsistent upstream versioning schemes.
Neither of the first two drafts is as simple as the current guidelines but the second is a relatively small additionI don't know if either is more acceptable to anyone in particular.
 
The third draft, on the other hand, is a significant simplification.  It has been merged into upstream RPM, and maybe it will be backported to the live Fedora branches afterwards.  Even if it is, the question of RHEL/EPEL will remain.  We can hope.
== Notes for this draft ==
 
This section isn't part of the main guidelines; I just need a place to put notes.


The fundamental issues I'm trying to solve:
The fundamental issues I'm trying to solve:
Line 18: Line 16:
* Keeping Release: simple is really appealing.
* Keeping Release: simple is really appealing.


With that in mind, here's the problem: these two simple, common cases are hard in general:
With that in mind, here's the problem: these two simple, common cases are at odds with each other if all we have is the tilde operator:
* Moving from a post-release snapshot to a new version.
* Moving between upstream tagged prereleases and git snapshots.
* Moving between upstream tagged prereleases and git snapshots.
* Moving from a post-release snapshot to a new version.
 
=== Moving between post-release snapshots and tagged releases ===
 
Take this version sequence:
* (1.2, git snapshot, 1.2.1)
 
Current guidelines give:
* (1.2-1, 1.2-2.20180101.abcde, 1.2.1-1)
Keeping Release: pristine sounds great, but....
* (1.2-1, 1.2+20180101.abcde-1, 1.2.1-1 + Epoch)
So that won't work.  Pushing snapshot information into release just gives us the current guidelines.
 
You can try to throw a tilde in there:
* (1.2-1, 1.2+0~20180101.abcde-1, 1.2.1-1)
It works in that case but sadly it breaks if 1.2a is released instead of 1.2.1.
 
So  it seems we have no choice but to keep putting post-release snapshot information into Release: or wait until we can use the caret operator.


=== Moving between tagged prereleases and git snapshots ===
=== Moving between tagged prereleases and git snapshots ===
Line 35: Line 50:
Pushing the snapshot information into Release gives:
Pushing the snapshot information into Release gives:
* (1.2~beta1-1, 1.2~beta1-2.20180101.abcde, 1.2~beta2-1, 1.2~beta2-2.20180102.fghij, 1.2-1) (3)
* (1.2~beta1-1, 1.2~beta1-2.20180101.abcde, 1.2~beta2-1, 1.2~beta2-2.20180102.fghij, 1.2-1) (3)
Now, to me none of these look particularly bad but it seems that #1 is the simplest that allows tilde.  I'm calling the third one the "post-prerelease snapshot" option.
Now, to me none of these look absolutely terrible but it seems that #1 is the simplest that allows tilde.  I'm calling the third one the "post-prerelease snapshot" option.


What if you knew upstream was going to put out 1.2 and package a snapshot, but then upstream releases a beta?
What if you knew upstream was going to put out 1.2 and package a snapshot, but then upstream releases a beta?
Line 45: Line 60:
* (1.2~1.20180101.abcde, 1.2~2.beta1)
* (1.2~1.20180101.abcde, 1.2~2.beta1)
Without the requirement for the digit on snapshots it "works" but is less pleasant:
Without the requirement for the digit on snapshots it "works" but is less pleasant:
* (1.2~20180101.abcde, 1.2~3.beta1)
* (1.2~20180101.abcde, 1.2~20180101.1.beta1) (tack a counter onto the date)
With snapshot information in release, you can't add the beta1 tag anywhere.
With snapshot information in release, you can't add the beta1 tag anywhere.
* (1.2-1.20180101.abcde, ???) or (1.2-20180101.abcde, ???)
* (1.2-1.20180101.abcde or 1.2-0.1.20190101.abcde, ???)
 
Unless you use a tilde with nothing (which sort of mirrors what I've done with the full tilde-caret guidelines)
 
* (1.2~-1.20180101.abcde, 1.2~beta1-1)
=== Moving between post-release snapshots and tagged releases ===
 
Take this version sequence:
* (1.2, git snapshot, 1.2.1)
 
Current guidelines give:
* (1.2-1, 1.2-2.20180101.abcde, 1.2.1-1)
Keeping Release: pristine sounds great, but....
* (1.2-1, 1.2+20180101.abcde, 1.2.1-1 + Epoch)
So push snapshot information into Release:
* (1.2-1, 1.2-2.20180101.abcde, 1.2.1-1)
 
So obviously, uh, we have no choice but to keep our current Release: mangling here.
 
If we had some magical operator ':' or something which compared like this: (1.2-1 < 1.2:20180101.abcde < 1.2.1-1) then life would be golden, but I don't think it exists.


=== What to do? ===
=== What to do? ===


I see four options:
I see five options:


# Don't change anything.
# Don't change anything.
# Allow tilde but keep snapshot information in Release:.  Requires the odd "post-prerelease snapshot" thing if you ever go from a snapshot to a prerelease.  Forbid the packaging of tagged prereleases if prerelease snapshots for the same version were packaged.
# Allow tilde and keep snapshot information in Release:.  Requires the odd "post-prerelease snapshot" thing if you ever go from a snapshot to a prerelease.  Forbid the packaging of tagged prereleases if prerelease snapshots for the same version were packaged.
# Allow tilde. Keep post-release snapshot information in Release:.  Keep prerelease snapshot information in Version.
# Allow tilde. Keep post-release snapshot information in Release:.  Keep prerelease snapshot information in Version.
# Allow tilde, with post-release info in Release and prerelease info in a place decided by whether you ever intend to package snapshots.
# Allow tilde, with post-release info in Release and prerelease info in a place decided by whether you ever intend to package snapshots.
# Wait for the implementation of caret to be merged and pushed back to live Fedora branches.


Since people have declared that the first option is simply something they will ignore because they want tilde so much.
Since people have declared that the first option is simply something they will ignore because they want tilde so much.
Line 83: Line 84:
The fourth option is simply insane, but seems to be what the people who want tilde say because it appears they don't ever intend to package prerelease snapshots and don't care about that use case.
The fourth option is simply insane, but seems to be what the people who want tilde say because it appears they don't ever intend to package prerelease snapshots and don't care about that use case.


One thing is clear: allowing tilde does not simplify the guidelines.  It does make some specific versioning cases look nicer.  When you completely ignore the existence of snapshots, tilde certainly makes loads of sense.
The fifth option permits some really clean guidelines, but we have to wait a bit (maybe three weeks) and then EPEL cannot follow.
 
== Some definitions ==
 
Note that upstreams may each have their own terminology and it is in general impossible to define these terms with complete generality.  For some upstreams, every commit is itself considered a version.  Many upstreams never make releases, instead just letting users take whatever is in the code repository at any given time.
 
;release version
: A version of the software which upstream has decided give a version and call "released".  The act of releasing the software can be as simple as adding a git tag.  This includes so-called "point releases" or "patchlevels" which some upstreams make, since those are actually assigned versions and released, but it doesn't include so called "prerelease versions".
 
;prerelease version
: Before a release happens, many upstreams will decide which version that will release will have, and then produce "alphas", "betas", "release candidates", or the like which carry that new version but indicate that the final release of that version has not yet been made.  These we call prerelease versions.  The importance is that upstream is basically "counting down" towards some version number.  Fedora needs to indicate that, but needs to make sure that the ordering is correct so that the Fedora package will properly upgrade to that version when it is actually released.
 
;postrelease version
: Any version which upstream doesn't call a release which happens after a particular release but before upsteam decides to make a "prerelease". The distinction is that with a prerelease, upstream has made some decision about what to call the next version.  With a postrelease they haven't, and Fedora can't pick something for them.  Note that if tags, makes a tarball or even issues a patch file called "patchlevel1" or something like that, it's not considered a postrelease. It's just a release.
 
;snapshot
: An archive taken from upstream's source code control system which is not equivalent to any release version.
 
;non-sorting version sequence
: A sequence of version strings which is not ordered in the same way that RPM's version comparison function would order it.  RPM has a somewhat complicated version comparison function which it will use to determine if a package is "newer".  If upstream's idea of what constitutes a "newer" version differs from RPM's implementation then simply using upstream's versions directly will result in updates which don't actually update any packages because to RPM they look "older".
 
== Examples ==
 
Examples of many possible versioning scenarios and tips on making your own version comparison tests are available from [[Package Versioning Examples]].
 
== Epoch: tag ==
 
The <code>Epoch:</code> tag provides the most significant input to RPM's version comparison function.  If present, it MUST consist of a positive integer.  It SHOULD ONLY be introduced or incremented when necessary to avoid ordering issues.  The <code>Epoch:</code> tag, once introduced to a package, MUST NOT ever remove or be decreased in any way.
 
 
== Simple versioning ==
 
Most upstream versioning schemes are "simple"; they generate versions like "1.2.03.007p1".  They consists of one or more version components, separated by periods.  Each component is a whole number, potentially with leading zeroes.  The rightmost component can also include one or more ASCII letters, upper or lower case.  The value of a component must *never* be reduced (to a value which sorts lower) without a component somewhere to the left increasing.  Note that the version sequence ("1.4a", "1.4b", "1.4") does not meet this criterion, as "4" sorts lower than "4b".  The sequence ("1.4", "1.4a", "1.4b") is, however, simple.
 
This is a very common versioning scheme, and the vast majority of software projects use something which works like this.
 
To package '''release versions''' of software using this versioning scheme:
* Use the upstream in the <code>Version:</code> tag. Don't trim leading zeroes.
* Use a <code>Release:</code> tag that contains a positive integer, beginning with 1.
** Increment it for each change made to the package which does not change <code>Version:</code>.
** Reset to 1 when <code>Version:</code> changes.
 
If upstream uses a version containing dashes it usually suffices to either remove them or convert them to periods or underscores to get a simple versioning scheme.  See [[#Upstream uses invalid characters in the version]] below.
 
== More complex versioning ==
 
There are several ways in which the simple scheme might not work in a particular situation:
 
* Upstream has never chosen a version; only snapshots are available for packaging.
* Upstream simply doesn't use a version scheme which orders properly under RPM's version comparison operation.
* You wish to package a prerelease version (snapshot or otherwise).
* You wish to package a postrelease snapshot.
* Upstream was thought to be following one scheme but then changed in a way that can't be sorted.
* More than one of the above may apply (lucky you).  Follow all of the relevant recommendations below together.
 
The methods for dealing with most of these issues involves tag while imposing additional structure onto the <code>Version:</code> tag.  There are potentially four fields which comprise the structured <code>Version:</code> tag:
 
* Upstream release version (<code><upstreamrel></code>)
* Upstream prerelease identifier (<code><upstreamprerel></code>)
* an integer introduced to impose a sort order when necessary (<code><sort></code>)
* snapshot information (<code><snapinfo></code>)
* an integer incremented for each Fedora release and reset for version changes (<code><fedorarel></code>)
 
Those items which are present are combined to construct the final <code>Version:-Release:</code> combination in one of the following forms.  The usual convention where items in square brackets might not be present applies.
 
* <code><upstreamrel>~[<sort>.]<upsteamprerel>-<fedorarel></code> (for prerelease versions)
* <code><upstreamrel>~[<sort>.]<snapinfo>-<fedorarel></code> (for prerelease snapshots)
* <code><upstreamrel>-<fedorarel>.<snapinfo></code> (for postrelease snapshots)
 
A tilde ('<code>~</code>') indicates a prerelease; RPM will compare a string containing a tilde as being less (or older) than the equivalent string with  tilde and the content following it removed.
 
The actual values to be used for those fields are given in the sections below.
 
=== The <code><sort></code> field ===
 
It can sometimes become necessary to insert an integer into the <code>Version:</code> in one place to ensure that RPM orders things properly.  This can happen if upstream's prerelease versions don't sort, or if you switch between packaging an actual prerelease version and a snapshot.  We want to avoid introducing <code>Epoch:</code> if at all possible, so the <code><sort></code> field is used instead.
 
When you need to "introduce <code><sort></code>", just set it to 1 and start using it as above.  It will always be followed by a period.  <code><sort></code> will generally go away when <code><upstreamrel></code> changes, or (in the case of prereleases) <code><upstreamrel></code> is actually released.
 
=== Upstream has never chosen a version ===
 
When upstream has never chosen a version, you MUST use <code>0</code> for <code><upstreamrel></code> and otherwise follow the guidelines for prerelease snapshots. "<code>0</code>" sorts lower than any other possible value that upstream might choose.  And if upstream does choose to release "version 0" then you can immediately move to using <code>Version: 0</code> and <code>Release: 1%{?dist}</code> with no ordering issues.
 
=== Upstream uses invalid characters in the version ===
 
It's possible that upstream uses characters besides digits, ASCII letters (upper and lower case), periods and underscores in its version.  They must be removed and potentially replaced with valid characters.  Any such alterations MUST be documented in the specfile.  It is not possible to cover all potential situations here, so it is left to the packager to alter the upstream versioning scheme consistently.  It is common, however, to either remove dashes or replace them with underscores or periods (which RPM treats identically).
 
After altering the version to be free of invalid characters, see [[#Unsortable versions]] below if the modifications, when applied to successive releases from upstream, will not order properly.  It is, however, often the case that a simple modification will give a scheme appropriate for [[#Simple versioning]].
 
=== Unsortable versions ===
 
XXX Completely broken in this rewrite.
 
When upstream uses a versioning scheme that does not sort properly, first see if there is any portion which can be removed from the right side of the version string such that the remainder is sortable.  This is often possible if upstream uses a sequence like ("1.2pre1", "1.2pre2", "1.2final"). If so, use the removed portion as <code><snapinfo></code>, introduce <sort>, and
 
, and the remainder as the package version.  If this splitting left a leading or trailing periods from either value, remove them.
 
If this is not possible, use Version: 0 and move the _entire_ version string into "extra version information".
 
=== Snapshots ===
 
All snapshots MUST contain a snapshot information field (<code><snapinfo></code>) in the <code>Version:</code> tag.  That field must at minimum consist of the date in eight-digit "YYYYMMDD" format.  The packager MAY include up to 17 characters of additional information after the date.  The following formats are suggested:
 
* <code>YYYYMMDD.<revision></code>
* <code>YYYYMMDD<scm><revision></code>
 
Where <code><scm></code> is a short string identifying the source code control system upstream uses (e.g. "git", "svn", "hg") or the string "snap".  <code><revision></code> is either a short git commit hash, a subversion revision number, or something else useful in identifying the precise revision in upstream's source code control system.  Obviously if CVS is used, no such revision information exists, so it would be omitted, but otherwise it SHOULD be included.
 
=== Prerelease versions ===
 
{{admon/note|This is where the bulk of the tilde-related changes will be.|Instead of using a simple Version: tag and overloading <pkgrel>, instead pkgrel stays simple and Version: gets the complexity.  There are two options here: one which forces the use of an integer to force sortability of the prerelease information.  The other leaves it optional.  I've gone for the optional route because the general case looks cleaner, but this isn't my proposal so....}}
 
In the <code>Version:</code> tag, use the following construction: <code><nextversion>~<prerelease></code>.  That is a literal tilde ( <code>~</code>) which instructs RPM to sort this <code>Version:</code> immediately before a package with the same version but no tilde.
 
* <code><nextversion></code> should contain the version which upstream has decided this line of development will become once it has been released.
* <code><prerelease></code> should contain a string which upstream has chosen to version the prereleases in this line of development.  Usually this will be something like "alpha3" or "pre2", and may need to be altered such that it includes no invalid characters.  (See [[#Upstream_uses_invalid_characters_in_the_version|above]].)
 
Note that values for <code><prerelease></code> must form a sortable sequence.  If you are not sure that your upstream will maintain sortability, you can form <code><prerelease></code> by prepending a positive integer: <code><integer>.<unsortable></code>.
 
=== Release and post-release versions ===
 
For the <code><pkgrel></code> field of the <code>Release:</code> tag, use an integer beginning with 1 and increasing for each revision of the package.  Release and post-release versions MUST use a <code>Release:</code> tag greater than or equal to 1.
 
=== Upstream makes unsortable changes ===
 
It is possible that upstream simply adopts a different versioning scheme, fails to follow an expected pattern, or even simply resets their version to some lower value.  If none of the above operations can help with giving a version which sorts properly, or give you a version which simply sorts lower than the packages already in Fedora, then you have little recourse but to increment the <code>Epoch:</code> tag, or to begin using it by adding <code>Epoch: 1</code>.  At the same time, try to work with upstream to hopefully minimize the need to involve <code>Epoch:</code> in the future.
 
== Rawhide is allowed to lag temporarily ==
 
A package MAY temporarily have a lower EVR in Rawhide when compared to a release branch of Fedora ONLY in the case where the package fails to build in Rawhide.  This permits important updates to be pushed to existing Fedora releases regardless of the current state of Rawhide.
 
== Making a change an old branch without rebuilding the others ==


Sometimes, you may find yourself in a situation where an older branch needs a fix, but the newer branches are fine. For example, if you have <code>Release: 3%{?dist}</code> in F28 and F29, and only F28 needs a fix. Normally, you would need to bump the release in each of the branches to ensure that F28 < F29, but that is a waste of time and energy for the newer branches which do not need to be touched.
One thing is clear: allowing tilde by itself does not simplify the guidelines. It does make some specific versioning cases look nicer. When you completely ignore the existence of snapshots, tilde certainly makes loads of senseIf we have both tilde and caret then things get significantly simplified.
ple
In this case, you MAY append an integer to the very end of <code>Release:</code>, after the dist tagFor the above example, you would use <code>Release: 3%{?dist}.1</code>.  This integer MUST begin at '1' increase by one for each minor bump you need to do. Remove this integer once you are able to increase the package release normally without introducing ordering issues.

Latest revision as of 16:25, 26 November 2018

Notes for the tilde versioning drafts

There are two drafts:

Neither of the first two drafts is as simple as the current guidelines but the second is a relatively small addition. I don't know if either is more acceptable to anyone in particular. The third draft, on the other hand, is a significant simplification. It has been merged into upstream RPM, and maybe it will be backported to the live Fedora branches afterwards. Even if it is, the question of RHEL/EPEL will remain. We can hope.

The fundamental issues I'm trying to solve:

  • People really want to use tilde because for some (limited but common) cases it makes things simpler.
  • We need something which is relatively simple and "works" for the range of problems generally seen by people.
  • It would be nice to be prescriptive for weirder cases.
  • Keeping Release: simple is really appealing.

With that in mind, here's the problem: these two simple, common cases are at odds with each other if all we have is the tilde operator:

  • Moving from a post-release snapshot to a new version.
  • Moving between upstream tagged prereleases and git snapshots.

Moving between post-release snapshots and tagged releases

Take this version sequence:

  • (1.2, git snapshot, 1.2.1)

Current guidelines give:

  • (1.2-1, 1.2-2.20180101.abcde, 1.2.1-1)

Keeping Release: pristine sounds great, but....

  • (1.2-1, 1.2+20180101.abcde-1, 1.2.1-1 + Epoch)

So that won't work. Pushing snapshot information into release just gives us the current guidelines.

You can try to throw a tilde in there:

  • (1.2-1, 1.2+0~20180101.abcde-1, 1.2.1-1)

It works in that case but sadly it breaks if 1.2a is released instead of 1.2.1.

So it seems we have no choice but to keep putting post-release snapshot information into Release: or wait until we can use the caret operator.

Moving between tagged prereleases and git snapshots

Take this version sequence:

  • (1.2beta1, git snapshot, 1.2beta2, git snapshot, 1.2)

Current guidelines give:

  • (1.2-0.1.beta1, 1.2-0.2.20180101.abcde-1, 1.2-0.3.beta2, 1.2-0.3.20180102.fghij-1, 1.2-1) (0)

With keeping Release: pristine, you have to insert a digit and it's simplest to just start when you introduce a snapshot:

  • (1.2~beta1-1, 1.2~1.20180101.abcde-1, 1.2~2.beta2-1, 1.2~3.20180102.fghij-1, 1.2-1) (1)

Not inserting the digit until necessary does work, but seems easy to get wrong and hard to describe:

  • (1.2~beta1-1, 1.2~20180101.abcde-1, 1.2~3.beta2-1 ???, 1.2~4.20180102.fghij-1, 1.2-1) (2)

Pushing the snapshot information into Release gives:

  • (1.2~beta1-1, 1.2~beta1-2.20180101.abcde, 1.2~beta2-1, 1.2~beta2-2.20180102.fghij, 1.2-1) (3)

Now, to me none of these look absolutely terrible but it seems that #1 is the simplest that allows tilde. I'm calling the third one the "post-prerelease snapshot" option.

What if you knew upstream was going to put out 1.2 and package a snapshot, but then upstream releases a beta?

  • (1.2 git snapshot, 1.2beta1)

Current guidelines of course work fine:

  • (1.2-0.1.20180101.abcde, 1.2-0.2.beta1)

Keeping "pristine Release" with requiring the extra digit on snapshots works:

  • (1.2~1.20180101.abcde, 1.2~2.beta1)

Without the requirement for the digit on snapshots it "works" but is less pleasant:

  • (1.2~20180101.abcde, 1.2~20180101.1.beta1) (tack a counter onto the date)

With snapshot information in release, you can't add the beta1 tag anywhere.

  • (1.2-1.20180101.abcde or 1.2-0.1.20190101.abcde, ???)

Unless you use a tilde with nothing (which sort of mirrors what I've done with the full tilde-caret guidelines)

  • (1.2~-1.20180101.abcde, 1.2~beta1-1)

What to do?

I see five options:

  1. Don't change anything.
  2. Allow tilde and keep snapshot information in Release:. Requires the odd "post-prerelease snapshot" thing if you ever go from a snapshot to a prerelease. Forbid the packaging of tagged prereleases if prerelease snapshots for the same version were packaged.
  3. Allow tilde. Keep post-release snapshot information in Release:. Keep prerelease snapshot information in Version.
  4. Allow tilde, with post-release info in Release and prerelease info in a place decided by whether you ever intend to package snapshots.
  5. Wait for the implementation of caret to be merged and pushed back to live Fedora branches.

Since people have declared that the first option is simply something they will ignore because they want tilde so much.

The second option just seems unreasonable.

The third option seems... inconsistent but at least possible to describe.

The fourth option is simply insane, but seems to be what the people who want tilde say because it appears they don't ever intend to package prerelease snapshots and don't care about that use case.

The fifth option permits some really clean guidelines, but we have to wait a bit (maybe three weeks) and then EPEL cannot follow.

One thing is clear: allowing tilde by itself does not simplify the guidelines. It does make some specific versioning cases look nicer. When you completely ignore the existence of snapshots, tilde certainly makes loads of sense. If we have both tilde and caret then things get significantly simplified.