Development Process
This document serves as the touchstone for the development process that is used by the Maven project to manage branches and the trunk during the development leading up to releases.
In particular the following will be addressed:
- Where new features are developed
- Releases
- Creating a release branch
- Working on a release branch
- Creating release candidates (RCs) from a release branch
- Soak period for RCs
- How to integrate bug fixes into an RC
- Generating an official release
- How to integrate bug fixes into a release branch
- Experimental, complex bug fix, and high-risk change branches
The terminology used here is somewhat SVN specific as that is the tool the Maven project uses. At some point we would like to generalize these strategies for all SCMs and integrate these strategies into general tools where Maven SCM can deal with the operations outlined here in an SCM independent fashion.
Where new features are developed
New development
How new development starts
The discussion of what to resolve will happen on the list or in irc but then get populated in JIRA so that what's up for discussion gets captured. JIRA can ping the list with unresolved issues and as we are discussing the issues I think someone needs to act as secretary and capture the salient ideas in the wiki. So for the dev process stuff I created a document and steward that document to completion. I think the same would go with the integration tests where this is something that Vincent is keen to resolve so he can be the secretary for that issue. So I think the flow becomes:
- everyone pushes issues they want resolved into JIRA
- we prioritize a short list to work on in a particular week (or whatever), we can use votes or just decide amongst ourselves
with that short list we:
- pick the issue at hand
- burst of discussion on the list
- secretary captures the salient points
- offers up the document for review
- go back to discussion/capture/review until complete
- a final document then accompanies the resolution and the issue is closed
Things that can be done to make the process easier to track:
- A filter can be created to send all unresolved issues for a release to the dev list.
- Might be able to setup custom workflow that can help streamline the process once an issue has been earmarked for a release.
- Tagging issues with multiple components so that an issue is marked with its real category but can also be marked with a meta category like design or best practices which would allow us to group them in a view and be able to report on them.
- Find a way to sync all the bits and pieces in jira and confluence so we have a cohesive view of the work that needs to be done and planned for.
One person might start a discussion but it can be picked up by anyone who has the energy/motivation/time/whatever to finish it. I think what happened with the dev process works just fine. The issue was in JIRA with me assigned, but you had time to post some initial thoughts and I tried to follow up with a document. The issue needs a champion but anyone should be able to carry it to completion because all the information should be clearly visible.
Once an issue is in JIRA then any developer with the motivation can run with it.
Where new development starts
All new development, whether new features or general improvements, All new features should be integrated into the latest revision or the trunk. Once a new feature is implemented and integrated into the trunk it can then be decided which branches the new features development should be applied to. There may be rare cases where a new feature development only applies to a particular branch but in general all new features go to the trunk first and disseminated from there. The important thing is that all changes go into the trunk first, then get merged into the release branch as needed, so no changes ever get dropped by mistake. New features or improvements should never originate from a branch.
Changes should be kept in sync at all times where possible and this is the responsbility of the developer. The fix for on JIRA should be set to where it has landed, not where it is targeted, particularly if there is a delay in merging. For example, if a change is committed only to trunk, the issue must either be closed with fix for "2.1", or kept open and commented as "committed to trunk revXXX, branch merge pending" with fix for set to "2.0.x". Ideally, the change is committed to the branch immediately so the issue can be closed with fix for "2.0.x" without the additional comment.
If issues closed on the trunk should go into the branch, the release manager or other developers may choose to reopen them with the new fix for, merge and commit then close on the new target version.
Releases
Current release process
- Declare your intention to do a release through the mailing list
- Show reports on issues fixed and new features added
- Identify issues that needs to be fixed prior to the release and those that should be rescheduled
- All unit and integration tests should pass
- Use maven-docck-plugin to check for documentation standards compliance
- Deploy a snapshot for voting reference
- Call for a vote
Creating a release branch
- A release branch should be made in advance of the release to allow for stabilzation of the release and the preparation of RCs. This branch should be created at the point that it is agreed that all the new feature development is complete and only bugfix issues are targetted to the branch. A release branch is a long-lived branch from which all the releases for a non-API breaking versions are made. So you would release 2.0, 2.0.1, 2.0.2 of a project from a 2.0.x branch and likewise you would release 2.1, 2.1.1, 2.1.2 from a 2.1.x branch.
- Make sure that all developers Make sure that everyone has checked in their local modifications before the branch is created.
- Copy using URLs as everything will occur on the server and be faster.
To create a release branch to prepare in preparation for a release us use the following command:
No Format |
---|
svn copy -m "Create RB-1Maven 2.0.x branch" \ svn://svn.apache.org/repos/asf/maven/XXXcomponents/trunk \ svn://svn.apache.org/repos/asf/maven/XXXcomponents/branches/RBmaven-12.0.x |
...
- TODO we need to set up multiple CI processes
Working on a release branch
To work on a release branch you can either checkout the branch or switch and existing working copy to the branch. It is probably easier to checkout the branch in a different directory so that you can work on the trunk and branch at the same time.
No Format |
---|
svn co svn://svn.apache.org/repos/asf/maven/XXXcomponents/branches/branch1maven-2.0.x |
Creating release candidates (RCs) from a release branch
Soak period for RCs
How to integrate bug fixes into an RC
Generating an official release
When you are ready to create a release you need to create a tag
No Format |
---|
svn copy -m "Tag release 1.0.0" svn://svn.apache.org/repos/asf/maven/XXX/branches/branch1 svn://svn.apache.org/repos/asf/maven/XXX/tags/REL-1.0.0
|
How to integrate bug fixes into a release branch
/----------/
This page serves as the touchstone for the development process that is used by Maven to manage branches and the trunk during the development leading up to releases.
This thread never really got rounded up, so I thought I'd summarise some points we seemed to be in agreeance on. Please vote +1 for all, or +1/+0/-1 for every item.
- use of the flying fish technique (ie bugfix only release goes over to /branches/2.0.x)
- we should merge at each point release (2.0.1, 2.0.2) back to trunk
- can do interim merges if there are long time lines on those releases
- we need to set up multiple CI processes
- no alphas or betas on 2.0.x releases
- current version is always <final release>-SNAPSHOT, eg 2.1-SNAPSHOT
- 2.1 cycle will have betas (maybe alphas), which are labelled at release time (release plugin to accommodate)
- RC's are the actual build. It will report version "2.0", and is differentiated from the actual final release (if different), by the build timestamp. If the RC is not suitable for any reason, we remove the old tag, and redo the release
- we will setup one new JIRA project per plugin (prefix with just M, won't be reusing the m1 projects, and we'll move all existing issues to there even if closed - based on component)
The same should also apply to Continuum.
If we agree on this, then the first step is:
svn cp https://svn.apache.org/repos/asf/maven/components/trunk https://svn.apache.org/repos/asf/maven/components/branches/2.0.x
and everyone svn switches to that if they are doing core bugfixes. John - can you do this?
-----------------
some things I have written (jesse) general notes on subversion, branching and tagging, dumped here at the behest of jason...cut and copy up as needed..
A little bit about subversion. Tags and branches are functionally the same, and are merely symbolic. making a branch or a tag is not earmarking the file in the repository with a little indicator like it is in cvs, it is logically a copy of the file at that particular revision. with that in mind, tagging is no longer a seperate process from merging...they are no different. The act of tagging doesn't exist. Instead you merge a given changeset from one location to another. svn maintains some amount of knowledge of the file that it was copied from, but not what given changeset was merged into it when.
Common development will take place on the trunk. Work that embody any kind of size or impacts a large array of objects should be done on a special development branch pulled by the developer/s. A note on these branches, I really don't think they should be worked out outside of a couple of weeks...the longer that people spend working on and committing on a branch and not merging that work back onto the trunk the more annoying it will get to finally do the merge. Especially in the infancy of people actually working with branching and merging....it is critical to not let development branches like this get out of hand. If something is going to take over two weeks of development I would consider breaking that development up into multiple phases which each phase being something that can be merged back to the trunk. If API's are going to change, get them changed sooner then later.
There are a number of fundamental things that we need to manage ourselves as developers.
1. my work tramples your previous work
2. my work is getting pushed up the release chain before yours
3. your in a heap of trouble if promoting your changes carries sometime along with it that it shouldn't
first off, work is getting done on the trunk, my commits for project X are getting committed as we go along as I development it on my personal development instance. I feel (or am told perhaps) that it is time to get my stuff moved to QA. Like a good developer I have maintained a list of the changesets that embody my project X, say r100, r105, r106, r109, and r140.
I checkout the release branch and begin merging the changesets from the trunk...all the change sets get shoved into my release branch instance at the same time. I now commit these change sets to the release branch and get me a new r#, say r200 for this instance. I have now aggregated the 5 commits I had made on the trunk into 1 changeset on the release branch. I edit a file called MERGE on the release branch and note that changeset number, the project, and hopefully the jira issue that relates to it. The work is then built and snapshotted and tested... perhaps I have a bugfix or 2 or 3...that get merged to the release branch and added to the MERGE file as changesets representing that Project X of work.
This approach has benefits since it really represents the aggregation of work into larger changesets to deployment. The only side effect it really has is that it doesn't solve the 'my work effects yours, but mine is going first'...but nothing so far addresses that, and if the MERGE file is consistently up to date it can be mined by an external process to protect us I believe. an external process be told what changesets are wanted to be moved from qa to staging and interrogate svn to determine if the changeset for project X masks any files from another changeset being monitored in that same file....this lets us monitor subproject dependencies programattically which would rock.
Pros:
- potential merging of changed code only between developer branches and the trunk
- merging is between trunk and release branches, never between release branch to release branch
- jira tasks for things like javadoc additions and maintanence tasks can be grep'd out of these files, piped through cut, sort and diff to automagically give you changesets to merge to a release tag using xargs
- SIMPLE! if developers keep to the process then releases should be quite simple, just a matter of applying a set of changesets
Cons:
- someone might forget to mark a changeset in the MERGE file, beatings can minimize this though
- same con as everything else, you if changeset X touchs things that changeset Y did...Y has to go forward first, or both have to go...but no system addresses that
another potential mechanism...or naming convention, kicked around a couple of weeks ago.
-SNAPSHOT development suffix for version tags.
-STABLE bugfix suffix for released versions
-RELEASE tag suffix for a released versions
so 2.0-RELEASE is a svn tag that is immutable, it is set once for a set of code, 2.0-STABLE becomes the bugfix branch for the 2.0-RELEASE...and people can track that -STABLE release for something they are assured to be solid and stable...2.1-SNAPSHOT would be development code, released periodically as per whatever rules govern development code release, as needed perhaps
Notes from Garrett Rooney (an svn committer)
<jason_> any svn users who are familiar with the fly fishing technique?
<jason_> just looking for a little advice on working with branches
<chipig> fly fishing and branches?
<rooneg> i can give advice on working with branches, but i have no clue what you mean by "fly fishing technique" in that context
<jason_> http://cvsbook.red-bean.com/cvsbook.html#Going%20Out%20On%20A%20Limb%20(How%20To%20Work%20With%20Branches%20And%20Survive)
<jason_> rooneg, do you typically work on trunk and merge into the branch periodically or right away?
<rooneg> well, it depends what kind of branch you're talking about. is it a release branch? a maintenance branch? a feature branch?
<jason_> in this case a release branch
<jason_> well, we release from this branch
<rooneg> well, for subversion itself we use a technique like this. when we're ready to start preparing for a release we branch off of the trunk.
<jason_> http://svn.apache.org/viewcvs.cgi/maven/components/branches/maven-2.0.x/
<rooneg> any last minute modifications to the branch happen there (updating change lists, version numbers, etc), then we cut a release candidate.
<rooneg> at this point trunk development continues as usual
<rooneg> there is now a soak period, where the RC is tested. if bugs are found they are fixed on the trunk and then proposed for merging back to the branch.
<rooneg> when we've got enough fixes merged in that a new RC is justified we roll a new RC off the release branch
<rooneg> (rolling an RC means tagging it as well, FWIW)
--> jesse (n=jesse@216-161-72-109.omah.qwest.net) has joined #asf
<rooneg> eventualy one of our RCs is declared final, and we roll the final release with only a version number change relative to the last RC
<rooneg> the release branch (i.e. branches/1.2.x or branches/1.3.x) sticks around and we do basically the same thing for the next release.
<rooneg> the important thing is that all changes go into the trunk first, then get merged into the release branch as needed, so no changes ever get dropped by mistake
<jason_> cool, that's what i wanted to hear
<jason_> thx for the advice
<jason_> what's your name btw? just so i remember
<rooneg> no problem
<rooneg> Garrett Rooney
More notes from Garrett and Paul Querna
Calling a vote for a release
- A developer posts a message asking the list whether there are any objections to locking down for a release.
- If agreed, at this point no more issues can be assigned a fix version corresponding to the release.
- When the count goes to zero the voting for the release starts
- All external snapshots need to be resolved in advance of calling the vote and creating an RC.
- The proposal may include scope to release another dependent component, but it is highly recommended that the components be voted on separately and released in advance of the dependee.
- There should be plenty of opportunity for people to request rescheduling of issues before the vote begins. No rescheduling should be discussed in the vote unless it is exceptional circumstances.
- An RC is created and is used for people to vote on (see below)
- The vote must last at least 72 hours to give everyone a chance to give feedback.
- If there is a regression or other problem with the release, the vote is suspended until it is fixed. Other issues may be brought up during that period. Once those are resolved, the vote starts over (another 72 hours, new RC, new vote thread).
At some point we might even be able to automate this will a little voter app, or use the one we use for board elections. Still visible but much better audit trail.
Creating release candidates (RCs) from a release branch
RCs should be made available in succession until the community is satisfied that the RC in question is of release quality. RCs should be circulated for no less then three days so that we can accurately determine if there are any defects present.
The RC that finally makes the cut as the release should be used as it was originally built so the RCs will be named as if they were the final release. This means that we have a few technical issues to resolve:
- TODO We need a staging artifact repository where the RCs can be placed so that failed RC attempts don't pollute a release artifact repository
- TODO We need a reliable way of moving the successful RC from the staging repository to the release repository. This is an intended feature for the Repository Manager but we may need a stop-gap solution until the Repository Manager is ready for production use.
- TODO We need to ensure that the RC that gets promoted as the release is not rebuilt. At the same time we need to provide a way to identify what version a user is running (be it a RC1, RC2, etc). One solution is to use a build# so that a maven2 version is always made of both a Version a build number. For example you would have "Maven 2.1 Build # 1353" which would be RC1 and then "Maven 2.1 Build # 1450" which would be RC2 which gets promoted as the 2.1 release.
In the interim, we use timestamped builds from CI for distributions, and timestamped snapshots for plugins.
- TODO When these are resolved, the release should be done with release:prepare/perform instead.
- TODO We need to figure out the process of how we tag the RCs, probably don't need to keep them. Maybe just roll over the previous one until the RC is good enough to release. One issue with moving the tag is that it will affect the POM, effectively requiring a rebuild. We probably need to prepare as if it were the final one, and recreate the tag if required.
How to integrate bug fixes into an RC
If bugs are found in the RCs, then the fixes should be applied to the trunk and then to the branch as is usually the case. However, this activity needs to be limited to important issues to avoid making the RC less stable and requiring longer testing periods.
Generating an official release
- TODO: Follow the Apache guidelines, which need to be finalised.
Experimental, complex bug fix, and high-risk change branches
These work like a new trunk. They are created from their intended final destination (trunk for most experimental features, the branch for complex bug fixes). It is the responsibility of the branch creator to merge changes from the original source to the experimental branch as they occur. This may well be at the end of experimental development as one big batch.
As stability is returned, the experimental branch is copied back over the original trunk after confirming all of the changes have been ported to it.
Using svnmerge to manage revisions to merge from the trunk into the release branch
The use of the svnmerge script is optional to help pick off the revisions to merge.
The bottom of this link some example usage of the svnmerge.py script
http://gcc.gnu.org/wiki/SvnBranch
The svnmerge script is a wonderful little tool. In a nutshell, you can take any branch and 'svnmerge init' it against any other branch (or the trunk by default) and then by typing 'svnmerge avail' obtain a list of changesets that are available to merge over from that branch/trunk to your working copy. 'svnmerge merge -rN will merge a particular version over and let you commit it to the branch. Once committed, the svnmerge avail command will no longer list that changeset as available to merge over. This can work either in either a star pattern where each branch can merge changes over from the trunk selectively, or in a chained pattern where branches follow a release process of development->staging->production. In the chained approach checking the available patchs will only give you the changeset available from the source branch allowing for a clean structured code tagging/release process.
You can find the svnmerge.py script here: http://svn.collab.net/viewvc/svn/trunk/contrib/client-side/
If you know that a particular revision is already in sync between the trunk and the branch in question then you need to do the following so that the svnmerge script will ignore the revision when compiling a list of candidate revisions:
No Format |
---|
cd <the-branch>
svn propedit svnmerge-integrated
<start-edit>
/maven/components/trunk:1-368287,368989,369304,<your-revision>
<end-edit>
svn commit
|
Keep in mind the revisions are revisions on the trunk. So if you started in the branch and merged to the trunk then make sure it's the id of the revision on the trunk!<jason_> rooneg, do you use anything like that svnmerge.py script?
<jason_> is that a useful script, i just saw it in the svn contrib section
<rooneg> jason_: personally, no, i've never used it, but some svn developers do
<rooneg> it's really more useful for things like feature branches, where you intend to merge all changes from one branch into another.
<rooneg> so if i created a branch to work on a new feature, and i want to periodically merge the changes from trunk into it, to keep me up to date, svnmerge.py would help a lot
<rooneg> not sure how well it deals with cherry picking individual revisions though, like we do for release branches.
<jason_> are there many cases where changes would originate in a branch?
<jason_> does that ever happen much?
<chipig> not for release branches
<chipig> only if for whatever reason, the code in the release branch, doesn't exist in the trunk. IE with a depricated module.
<jason_> so from trunk to branch is the general rule, cool
<jason_> chipig: what's your name?
<rooneg> yeah, that's the general idea, it simplifies things, and ensures that you never accidentally fix a bug in an older version but not in a newer one
<rooneg> of course, development branches (like a branch to implement a particular feature) are diffeent, the whole point there is to implement some new feature, then merge it back to trunk later.
<quasi> jason_: there's this cool feature in irc clients - /whois
<jason_> well, you learn something new every day!
<jason_> well, i might guess it's mads toftum because your name has popped up on mailing lists but that result returned still isn't all that clear
<chipig> jason_: paul querna...
<jason_> chipig's came up with a full name
<quasi> jason_: correct
<jason_> cool, thanks for the advice. will go directly into maven development process doco.
Useful links
http://www.asterisk.org/developers/svn-branching-merging
http://www.reactos.org/wiki/index.php/Best_practices_for_working_with_branches
http://svn.apache.org/repos/asf/httpd/httpd/trunk/VERSIONING
http://svn.collab.net/viewcvs/svn/trunk/contrib/client-side/
http://www.freebsd.org/doc/en_US.ISO8859-1/articles/releng/index.html