Jump to: navigation, search

Difference between revisions of "Branch Model"

(Model with intermediary releases)
 
(16 intermediate revisions by 3 users not shown)
Line 1: Line 1:
__NOTOC__
+
OpenStack projects which follow the release cycle use a branching model close to the [http://nvie.com/posts/a-successful-git-branching-model/ NVIE model] that ensures an almost-always-open ''master'' while still allowing to freeze features and select bugfixes in release branches (one per cycle). Some follow a model with development milestones and a final release at the end of the cycle, while some follow an alternative model which allows for multiple intermediary releases in every cycle.
<<[[TableOfContents]]()>>
 
  
= [[OpenStack]] branch model =
+
=== Model with milestones ===
  
Starting with the Diablo cycle, OpenStack core projects use a branching model close to the [http://nvie.com/posts/a-successful-git-branching-model/ NVIE model] that ensures a continuously-open ''trunk'' while still allowing to freeze features and select bugfixes in a release branch (''milestone-proposed''):
+
Here is how it works. Suppose that we are currently in the ''foo'' development cycle, which will lead to the final ''x.0.0'' release. When we hit the '''foo-1''' development milestone, we push a '''x.0.0.0b1''' tag on the master branch. Same for the foo-2 development milestone. When we hit '''foo-3''', we push a '''x.0.0.0b3''' tag, and we start a feature-frozen period, during which the focus switches to fixing release-critical bugs. When all those bugs are fixed, we push a '''x.0.0.0rc1''' tag and publish the first "foo" release candidate for that project. At this point we create a '''stable/foo''' pre-release branch. The master branch is no longer feature-frozen: it is now open for the next cycle (foo+1) development. If further release-critical bugs are found in the release candidate, we backport the release-critical bugfixes to stable/foo, and when we fix all new release-critical bugs, we tag a new RC. On release day, we tag the current RC as the final release ('''x.0.0'''). From that point on '''stable/foo''' is managed by the Stable Team and gets critical bugfixes backported and will regularly tag and publish point releases (the first one being '''x.0.1''') until it reaches end-of-life.
  
{{http://img97.imageshack.us/img97/8242/branchmodel.png}}
+
[[File:branchmodel.png]]
  
At some point before the release of a milestone (called the "branch point"), the current state of ''trunk'' is merged into ''milestone-proposed'', and trunk continues towards the development of the next milestone. The ''milestone-proposed'' branches gets testing and bugfixes (that are also backported to ''trunk''), until the release is tagged.
+
=== Model with intermediary releases ===
  
Here are pointers to the branches:
+
In this model, releases are made at-will during the "foo" development cycle, incrementing a [http://docs.openstack.org/developer/pbr/semver.html SemVer] (major.minor.patch) version number based on the changes in the previous release. When we get to the end of the development cycle, the team proposes a release to be the "final" foo release. At this point we create a '''stable/foo''' branch, managed by the Stable Team, which can get critical bugfixes backported. Future stable point releases will be tagged on that branch, until it reaches end-of-life. Future releases on master must increment at least the 'y' semver component (x.y+1.0) to make room for those point releases.
  
{| border="1" cellpadding="2" cellspacing="0"
+
[[File:branchmodel2.png]]
|<#eeeeee>| Project
 
|<#eeeeee>| ''trunk''
 
|-
 
|  Nova
 
[https://code.launchpad.net/~hudson-openstack/nova/trunk lp:nova]
 
|-
 
|  Glance
 
[https://code.launchpad.net/~hudson-openstack/glance/trunk lp:glance]  
 
|-
 
|  Swift
 
|  [https://code.launchpad.net/~hudson-openstack/swift/trunk lp:swift]  
 
|}
 
 
 
= Version numbers =
 
 
 
Since we have two branches in parallel, we use version numbers that allow to upgrade from one to the other.
 
 
 
For projects with milestones and releases (Nova, Glance):
 
 
 
* The ''trunk'' generates '''VERSION~DEVMILESTONE~DATE.TRUNKREV''' (nova-2011.3~d2~20110531.302)
 
* The ''milestone-proposed'' branch generates '''VERSION~MILESTONE~DATE.rMPREV''' (nova-2011.3~d1~20110531.r301)
 
* This gets copied to the milestone PPA at milestone delivery time as '''VERSION~MILESTONE''' (nova-2011.3~d1)
 
* This gets copied to the release PPA at coordinated release time as '''VERSION''' (nova-2011.3)
 
 
 
For projects where milestones == releases (Swift):
 
 
 
* The ''trunk'' generates '''DEVMILESTONE~DATE.TRUNKREV''' (swift-1.4.1~20110531.302)
 
* The ''milestone-proposed'' branch generates '''MILESTONE~DATE.rMPREV''' (swift-1.4.0~20110531.r301)
 
* This gets copied to the milestone PPA at milestone delivery time as '''MILESTONE''' (swift-1.4.0)
 
* The most recent milestone gets copied to the release PPA at coordinated release time
 
 
 
With:
 
* PROJECT being nova, swift...
 
* VERSION being the version of the project under development (2011.3)
 
* DEVMILESTONE being the short name of milestone under development (d2, 1.4.1...) and MILESTONE being the milestone to release (d1, 1.4.0...)
 
* TRUNKREV is the revision on ''trunk''
 
* MPREV is the revision on ''milestone-proposed''
 
 
 
Those (seemingly complex) version numbers actually ensure that you can smoothly upgrade in all scenarios (from trunk to milestone-proposed and back to trunk and to the final version...)
 

Latest revision as of 19:53, 16 June 2016

OpenStack projects which follow the release cycle use a branching model close to the NVIE model that ensures an almost-always-open master while still allowing to freeze features and select bugfixes in release branches (one per cycle). Some follow a model with development milestones and a final release at the end of the cycle, while some follow an alternative model which allows for multiple intermediary releases in every cycle.

Model with milestones

Here is how it works. Suppose that we are currently in the foo development cycle, which will lead to the final x.0.0 release. When we hit the foo-1 development milestone, we push a x.0.0.0b1 tag on the master branch. Same for the foo-2 development milestone. When we hit foo-3, we push a x.0.0.0b3 tag, and we start a feature-frozen period, during which the focus switches to fixing release-critical bugs. When all those bugs are fixed, we push a x.0.0.0rc1 tag and publish the first "foo" release candidate for that project. At this point we create a stable/foo pre-release branch. The master branch is no longer feature-frozen: it is now open for the next cycle (foo+1) development. If further release-critical bugs are found in the release candidate, we backport the release-critical bugfixes to stable/foo, and when we fix all new release-critical bugs, we tag a new RC. On release day, we tag the current RC as the final release (x.0.0). From that point on stable/foo is managed by the Stable Team and gets critical bugfixes backported and will regularly tag and publish point releases (the first one being x.0.1) until it reaches end-of-life.

Branchmodel.png

Model with intermediary releases

In this model, releases are made at-will during the "foo" development cycle, incrementing a SemVer (major.minor.patch) version number based on the changes in the previous release. When we get to the end of the development cycle, the team proposes a release to be the "final" foo release. At this point we create a stable/foo branch, managed by the Stable Team, which can get critical bugfixes backported. Future stable point releases will be tagged on that branch, until it reaches end-of-life. Future releases on master must increment at least the 'y' semver component (x.y+1.0) to make room for those point releases.

Branchmodel2.png