From de9acabf12460e65f8ec816df0700ef7a3c42be0 Mon Sep 17 00:00:00 2001 From: Jacob Kaplan-Moss Date: Fri, 19 Sep 2008 19:44:10 +0000 Subject: [PATCH] Updated contributing documentation to contain the new release process and updated information about branches using DVCSes. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9071 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/internals/contributing.txt | 146 +++++++++++--------- docs/internals/index.txt | 1 + docs/internals/release-process.txt | 205 +++++++++++++++++++++++++++++ 3 files changed, 290 insertions(+), 62 deletions(-) create mode 100644 docs/internals/release-process.txt diff --git a/docs/internals/contributing.txt b/docs/internals/contributing.txt index a9cfdb94bc..b2efc2f684 100644 --- a/docs/internals/contributing.txt +++ b/docs/internals/contributing.txt @@ -184,6 +184,8 @@ Patch style An exception is for code changes that are described more clearly in plain English than in code. Indentation is the most common example; it's hard to read patches when the only difference in code is that it's indented. + + Patches in ``git diff`` format are also acceptable. * When creating patches, always run ``svn diff`` from the top-level ``trunk`` directory -- i.e., the one that contains ``django``, ``docs``, @@ -400,10 +402,10 @@ translated, here's what to do: * Join the `Django i18n mailing list`_ and introduce yourself. - * Create translations using the methods described in the :ref:`i18n - documentation `. For this you will use the ``django-admin.py - makemessages`` tool. In this particular case it should be run from the - top-level ``django`` directory of the Django source tree. + * Create translations using the methods described in the + :ref:`i18n documentation `. For this you will use the + ``django-admin.py makemessages`` tool. In this particular case it should + be run from the top-level ``django`` directory of the Django source tree. The script runs over the entire Django source tree and pulls out all strings marked for translation. It creates (or updates) a message file in @@ -597,11 +599,11 @@ Our policy is: version. Assume documentation readers are using the latest release, not the development version.** -Our prefered way for marking new features is by prefacing the features' +Our preferred way for marking new features is by prefacing the features' documentation with: ".. versionadded:: X.Y", followed by an optional one line comment and a mandatory blank line. -General improvements, or other changes to the APIs that should be emphasised +General improvements, or other changes to the APIs that should be emphasized should use the ".. versionchanged:: X.Y" directive (with the same format as the ``versionadded`` mentioned above. @@ -690,6 +692,11 @@ repository: first commit the change to library Y, then commit feature X in a separate commit. This goes a *long way* in helping all core Django developers follow your changes. + + * Separate bug fixes from feature changes. + + Bug fixes need to be added to the current bugfix branch (e.g. the + ``1.0.X`` branch) as well as the current trunk. * If your commit closes a ticket in the Django `ticket tracker`_, begin your commit message with the text "Fixed #abc", where "abc" is the number @@ -809,7 +816,6 @@ method as above:: ./runtests.py --settings=settings markup - Requesting features =================== @@ -837,23 +843,80 @@ our repository; see below. Branch policy ============= -In general, most development is confined to the trunk, and the trunk -is kept stable. People should be able to run production sites against the -trunk at any time. +In general, the trunk must be kept stable. People should be able to run +production sites against the trunk at any time. Additionally, commits to trunk +ought to be as atomic as possible -- smaller changes are better. Thus, large +feature changes -- that is, changes too large to be encapsulated in a single +patch, or changes that need multiple eyes on them -- must happen on dedicated +branches. -Thus, large architectural changes -- that is, changes too large to be -encapsulated in a single patch, or changes that need multiple eyes on them -- -will have dedicated branches. See, for example, the `i18n branch`_. If you -have a change of this nature that you'd like to work on, ask on -`django-developers`_ for a branch to be created for you. We'll create a branch -for pretty much any kind of experimenting you'd like to do. +This means that if you want to work on a large feature -- anything that would +take more than a single patch, or requires large-scale refactoring -- you need +to do it on a feature branch. Our development process recognizes two options +for feature branches: -We will only branch entire copies of the Django tree, even if work is only -happening on part of that tree. This makes it painless to switch to a branch. + 1. Feature branches using a distributed revision control system like + Git_, Mercurial_, Bazaar_, etc. + + If you're familiar with one of these tools, this is probably your best + option since it doesn't require any support or buy-in from the Django + core developers. + + However, do keep in mind that Django will continue to use Subversion for + the foreseeable future, and this will naturally limit the recognition of + your branch. Further, if your branch becomes eligible for merging to + trunk you'll need to find a core developer familiar with your DVCS of + choice who'll actually perform the merge. + + If you do decided to start a distributed branch of Django and choose to make it + public, please add the branch to the `Django branches`_ wiki page. + + 2. Feature branches using SVN have a higher bar. If you want a branch in SVN + itself, you'll need a "mentor" among the :ref:`core committers + `. This person is responsible for actually creating + the branch, monitoring your process (see below), and ultimately merging + the branch into trunk. + + If you want a feature branch in SVN, you'll need to ask in + `django-developers`_ for a mentor. -Developers working on a branch should periodically merge changes from the trunk -into the branch. Please merge at least once a week. Every time you merge from -the trunk, note the merge and revision numbers in the commit message. +.. _git: http://git.or.cz/ +.. _mercurial: http://www.selenic.com/mercurial/ +.. _bazaar: http://bazaar-vcs.org/ +.. _django branches: http://code.djangoproject.com/wiki/DjangoBranches + +Branch rules +------------ + +We've got a few rules for branches born out of experience with what makes a +successful Django branch. + +DVCS branches are obviously not under central control, so we have no way of +enforcing these rules. However, if you're using a DVCS, following these rules +will give you the best chance of having a successful branch (read: merged back to +trunk). + +Developers with branches in SVN, however, **must** follow these rules. The +branch mentor will keep on eye on the branch and **will delete it** if these +rules are broken. + + * Only branch entire copies of the Django tree, even if work is only + happening on part of that tree. This makes it painless to switch to a + branch. + + * Merge changes from trunk no less than once a week, and preferably every + couple-three days. + + In our experience, doing regular trunk merges is often the difference + between a successful branch and one that fizzles and dies. + + If you're working on an SVN branch, you should be using `svnmerge.py`_ + to track merges from trunk. + + * Keep tests passing and documentation up-to-date. As with patches, + we'll only merge a branch that comes with tests and documentation. + +.. _svnmerge.py: http://www.orcaware.com/svn/wiki/Svnmerge.py Once the branch is stable and ready to be merged into the trunk, alert `django-developers`_. @@ -953,47 +1016,6 @@ file. Then copy the branch's version of the ``django`` directory into .. _path file: http://docs.python.org/lib/module-site.html -.. _official-releases: - -Official releases -================= - -Django's release numbering works as follows: - - * Versions are numbered in the form ``A.B`` or ``A.B.C``. - - * ``A`` is the major version number, which is only incremented for major - changes to Django, and these changes are not necessarily - backwards-compatible. That is, code you wrote for Django 6.0 may break - when we release Django 7.0. - - * ``B`` is the minor version number, which is incremented for large yet - backwards compatible changes. Code written for Django 6.4 will continue - to work under Django 6.5. - - A minor release may deprecate certain features in previous releases. If a - feature in version ``A.B`` is deprecated, it will continue to work in - version ``A.B+1``. In version ``A.B+2``, use of the feature will raise a - ``PendingDeprecationWarning`` but will continue to work. Version - ``A.B+3`` will remove the feature entirely. Major point releases will - always remove deprecated features immediately. - - * ``C`` is the micro version number which, is incremented for bug and - security fixes. A new micro-release will always be 100% - backwards-compatible with the previous micro-release. - - * In some cases, we'll make release candidate releases. These are of the - form ``A.BrcN``, which means the ``Nth`` candidate release of version - ``A.B``. - -An exception to this version numbering scheme is the pre-1.0 Django code. -There's no guarantee of backwards-compatibility until the 1.0 release. - -In Subversion, each Django release will be tagged under `tags/releases`_. If -it's necessary to release a bug fix release or a security release that doesn't -come from the trunk, we'll copy that tag to ``branches/releases`` to make the -bug fix release. - Deciding on features ==================== diff --git a/docs/internals/index.txt b/docs/internals/index.txt index b56b3287d4..0d54948bf5 100644 --- a/docs/internals/index.txt +++ b/docs/internals/index.txt @@ -21,3 +21,4 @@ the hood". contributing documentation committers + release-process diff --git a/docs/internals/release-process.txt b/docs/internals/release-process.txt new file mode 100644 index 0000000000..f1dca7b860 --- /dev/null +++ b/docs/internals/release-process.txt @@ -0,0 +1,205 @@ +.. _internals-release-process: + +======================== +Django's release process +======================== + +.. _official-releases: + +Official releases +================= + +Django's release numbering works as follows: + + * Versions are numbered in the form ``A.B`` or ``A.B.C``. + + * ``A`` is the *major version* number, which is only incremented for major + changes to Django, and these changes are not necessarily + backwards-compatible. That is, code you wrote for Django 6.0 may break + when we release Django 7.0. + + * ``B`` is the *minor version* number, which is incremented for large yet + backwards compatible changes. Code written for Django 6.4 will continue + to work under Django 6.5. + + * ``C`` is the *micro version* number which, is incremented for bug and + security fixes. A new micro-release will always be 100% + backwards-compatible with the previous micro-release. + + * In some cases, we'll make alpha, beta, or release candidate releases. + These are of the form ``A.B alpha/beta/rc N``, which means the ``Nth`` + alpha/beta/release candidate of version ``A.B``. + +An exception to this version numbering scheme is the pre-1.0 Django code. +There's no guarantee of backwards-compatibility until the 1.0 release. + +In Subversion, each Django release will be tagged under ``tags/releases``. If +it's necessary to release a bug fix release or a security release that doesn't +come from the trunk, we'll copy that tag to ``branches/releases`` to make the +bug fix release. + +Major releases +-------------- + +Major releases (1.0, 2.0, etc.) will happen very infrequently (think "years", +not "months"), and will probably represent major, sweeping changes to Django. + +Minor releases +-------------- + +Minor release (1.1, 1.2, etc.) will happen roughly every six months -- see +`release process`_, below for details. + +These releases will contain new features, improvements to existing features, and +such. A minor release may deprecate certain features from previous releases. If a +feature in version ``A.B`` is deprecated, it will continue to work in version +``A.B+1``. In version ``A.B+2``, use of the feature will raise a +``PendingDeprecationWarning`` but will continue to work. Version ``A.B+3`` will +remove the feature entirely. + +So, for example, if we decided to remove a function that existed in Django 1.0: + + * Django 1.1 will contain a backwards-compatible replica of the function + which will raise a ``PendingDeprecationWarning``. This warning is silent + by default; you need to explicitly turn on display of these warnings. + + * Django 1.2 will contain the backwards-compatible replica, but the warning + will be promoted to a full-fledged ``DeprecationWarning``. This warning is + *loud* by default, and will likely be quite annoying. + + * Django 1.3 will remove the feature outright. + +Micro releases +-------------- + +Micro releases (1.0.1, 1.0.2, 1.1.1, etc.) will be issued at least once half-way +between minor releases, and probably more often as needed. + +These releases will always be 100% compatible with the associated minor release +-- the answer to "should I upgrade to the latest micro release?" will always be +"yes." + +Each minor release of Django will have a "release maintainer" appointed. This +person will be responsible for making sure that bug fixes are applied to both +trunk and the maintained micro-release branch. This person will also work with +the release manager to decide when to release the micro releases. + +Supported versions +================== + +At any moment in time, Django's developer team will support a set of releases to +varying levels: + + * The current development trunk will get new features and bug fixes + requiring major refactoring. + + * All bug fixes applied to the trunk will also be applied to the last + minor release, to be released as the next micro release. + + * Security fixes will be applied to the current trunk and the previous two + minor releases. + +As a concrete example, consider a moment in time halfway between the release of +Django 1.3 and 1.4. At this point in time: + + * Features will be added to development trunk, to be released as Django 1.4. + + * Bug fixes will be applied to a ``1.3.X`` branch, and released as 1.3.1, + 1.3.2, etc. + + * Security releases will be applied to trunk, a ``1.3.X`` branch and a + ``1.2.X`` branch. Security fixes will trigger the release of of ``1.3.1``, + ``1.2.1``, etc. + +.. _release-process: + +Release process +=============== + +Django uses a time-based release schedule, with minor (i.e. 1.1, 1.2, etc.) +releases every six months, or more, depending on features. + +After each previous release (and after a suitable cooling-off period of a week +or two), the core development team will examine the landscape and announce a +timeline for the next release. Most releases will be scheduled in the 6-9 month +range, but if we have bigger features to development we might schedule a longer +period to allow for more ambitious work. + +Release cycle +------------- + +Each release cycle will be split into three periods, each lasting roughly +one-third of the cycle: + +Phase one: feature proposal +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The first phase of the release process will be devoted to figuring out what +features to include in the next version. This should include a good deal of +preliminary work on those features -- working code trumps grand design. + +At the end of part one, the core developers will propose a feature list for the +upcoming release. This will be broken into: + +* "Must-have": critical features that will delay the release if not finished +* "Maybe" features: that will be pushed to the next release if not finished +* "Not going to happen": features explicitly deferred to a later release. + +Anything that hasn't got at least some work done by the end of the first third +isn't eligible for the next release; a design alone isn't sufficient. + +Phase two: development +~~~~~~~~~~~~~~~~~~~~~~ + +The second third of the release schedule is the "heads-down" working period. +Using the roadmap produced at the end of phase one, we'll all work very hard to +get everything on it done. + +Longer release schedules will likely spend more than a third of the time in this +phase. + +At the end of phase two, any unfinished "maybe" features will be postponed until +the next release. Though it shouldn't happen, any "must-have" features will +extend phase two, and thus postpone the final release. + +Phase two will culminate with an alpha release. + +Phase three: bugfixes +~~~~~~~~~~~~~~~~~~~~~ + +The last third of a release is spent fixing bugs -- no new features will be +accepted during this time. We'll release a beta release about halfway through, +and an rc complete with string freeze two weeks before the end of the schedule. + +Bug-fix releases +---------------- + +After a minor release (i.e 1.1), the previous release will go into bug-fix mode. + +A branch will be created of the form ``branches/releases/1.0.X`` to track +bug-fixes to the previous release. When possible, bugs fixed on trunk must +*also* be fixed on the bug-fix branch; this means that commits need to cleanly +separate bug fixes from feature additions. Each bug-fix branch will have a +maintainer who will work with the committers to keep them honest on backporting +bug fixes. + +How this all fits together +-------------------------- + +Let's look at a hypothetical example for how this all first together. Imagine, +if you will, a point about halfway between 1.1 and 1.2. At this point, +development will be happening in a bunch of places: + + * On trunk, development towards 1.2 proceeds with small additions, bugs + fixes, etc. being checked in daily. + + * On the branch "branches/releases/1.1.X", bug fixes found in the 1.1 + release are checked in as needed. At some point, this branch will be + released as "1.1.1", "1.1.2", etc. + + * On the branch "branches/releases/1.0.X", security fixes are made if + needed and released as "1.0.2", "1.0.3", etc. + + * On feature branches, development of major features is done. These + branches will be merged into trunk before the end of phase two. +