diff --git a/docs/internals/howto-release-django.txt b/docs/internals/howto-release-django.txt new file mode 100644 index 0000000000..109583b67f --- /dev/null +++ b/docs/internals/howto-release-django.txt @@ -0,0 +1,280 @@ +===================== +How is Django Formed? +===================== + +This document explains how to release Django. If you're unluky enough to +be driving a release, you should follow these instructions to get the +package out. + +**Please, keep these instructions up-to-date if you make changes!** The point +here is to be descriptive, not proscriptive, so feel free to streamline or +otherwise make changes, but **update this document accordingly!** + +Overview +======== + +There are three types of releases that you might need to make + +* Security releases, disclosing and fixing a vulnerability. This'll + generally involve two or three simultaneous releases -- e.g. + 1.5.X, 1.6.X, and, depending on timing, perhaps a 1.7 alpha/beta/rc. + +* Regular version releases, either a final release (e.g. 1.5) or a + bugfix update (e.g. 1.5.1). + +* Pre-releases, e.g. 1.6 beta or something. + +In general the steps are about the same reguardless, but there are a few +differences noted. The short version is: + +#. If this is a security release, pre-notify the security distribution list + at least one week before the actual release. + +#. Proofread (and create if needed) the release notes, looking for + organiztion, writing errors, deprecation timelines, etc. Draft a blog post + and email announcement. + +#. Update version numbers and create the release package(s)! + +#. Upload the package(s) to the the ``djangoproject.com`` server and creating + some redirects for download/checksum links. + +#. Unless this is a pre-release, add the new version(s) to PyPI. + +#. Update the home page and download page to link to the new version(s). + +#. Post the blog entry and send out the email announcements. + +#. Update version numbers post-release. + +There's a lot of details, so please read on. + +Prerequisites +============= + +You'll need a few things hooked up to make this work: + +* A GPG key. *FIXME: sort out exactly whose keys are acceptable for a + release.* + +* Access to Django's record on PyPI. + +* Access to the ``djangoproject.com`` server to upload files and trigger a + deploy. + +* Access to the admin on ``djangoproject.com``. + +* Access to post to ``django-announe``. + +* If this is a security release, access to the pre-notification distribution + list. + +If this is your first release, you'll need to corrdinate with James and Jacob +to get all these things ready to go. + +Pre-release tasks +================= + +A few items need to be taken care of before even beginning the release process. +This stuff starts about a week before the release; most of it can be done +any time leading up to the actual release: + +#. If this is a security release, send out pre-notification **one week** + before the release. We maintain a list of who gets these pre-notifcation + emails at *FIXME WHERE?*. This email should be signed by the key you'll use + for the release, and should include patches for each issue being fixed. + +#. As the release aproaches, watch Trac to make sure no release blockers + are left for the upcoming release. + +#. Check with the other committers to make sure they don't have any + un-committed changes for the release. + +#. Proofread the release notes, including looking at the online + version to catch any broken links or reST errors, and make sure the + release notes contain the correct date. + +#. Double-check that the release notes mention deprecation timelines + for any APIs noted as deprecated, and that they mention any changes + in Python version support. + +#. Double-check that the release notes index has a link to the notes + for the new release; this will be in ``docs/releases/index.txt``. + +Preparing for release +===================== + +Next, everything needs to be made ready for actually rolling the +release. The following things should be done a few days to a few hours +before release: + +#. Update the djangoproject home page and download page templates to + reflect the new release. There are two templates to change: + ``flatpages/download.html`` and ``homepage.html``; here's + `one example commit for the 1.4.5 / 1.3.7 releases`__ + + __ https://github.com/django/djangoproject.com/commit/772edbc6ac5a2b8e718606b3338f2bcc429fb9b6 + +#. Write the announcement blog post for the release. You can enter it into + the admin at any time and mark it as inactive. Here's a few examples: + `example security release accouncement`__, `example regular release + announcement`__, `example pre-release announcement`__. + + __ https://www.djangoproject.com/weblog/2013/feb/19/security/ + __ https://www.djangoproject.com/weblog/2012/mar/23/14/ + __ https://www.djangoproject.com/weblog/2012/nov/27/15-beta-1/ + +#. Create redirects in the admin for the new downloads. For each release, + we create two redirects that look like:: + + /download//tarball/ -> /m/releases//Django-.tar.gz + /download//checksum/ -> /m/pgp/Django-.checksum.txt + +Actually rolling the release +============================ + +OK, this is the fun part, where we actually push out a release! + +#. Check Jenkins is green for the version(s) you're putting out. You probably + shouldn't issue a release until it's green. + +#. A release always begins from a release branch, so you + should ``git pull`` to make sure you're up-to-date and then + ``git checkout stable/`` (e.g. checkout ``stable/1.5.x`` to issue + a release in the 1.5 series.) + +#. If this is a security release, merge the apropriate patches from + ``django-private``. *FIXME: actual commands here - make sure to --ff- + only right?*. Make sure the commit messages explain that the commit + is a security fix and that an announcement will follow (`example + security commit`__) + + __ https://github.com/django/django/commit/3ef4bbf495cc6c061789132e3d50a8231a89406b + +#. Update version numbers for the release. This has to happen in three + places: ``django/__init__.py``, ``docs/conf.py``, and ``setup.py``. + Please see `notes on setting the VERSION tuple`_ below for details + on ``VERSION``. Here's `an example commit updating version numbers`__ + + __ https://github.com/django/django/commit/18d920ea4839fb54f9d2a5dcb555b6a5666ee469 + + Make sure the ``download_url`` in ``setup.py`` is the actual URL you'll + use for the new release package, not the redirect URL (some tools can't + properly follow redirects). + +#. If this is a pre-release package, update the "Development Status" trove + classifier in ``setup.py`` to reflect this. Otherwise, make sure the + classifier is set to ``Development Status :: 5 - Production/Stable``. + +#. Tag the release by running ``git tag`` *FIXME actual commands*. + +#. ``git push`` your work. + +#. Make sure you have an absolutely clean tree by running ``git clean -dfx``. + +#. Run ``python setup.py sdist`` to generate the release package. + +#. Generate the MD5 and SHA1 hashes of the release package. *FIXME + actual commands for doign this?* + +#. Create a "checksums" file containing the hashes and release information. + You can start with `a previous checksums file`__ and replace the + dates, keys, links, and checksums. *FIXME: make a template file.* + + __ https://www.djangoproject.com/m/pgp/Django-1.5b1.checksum.txt + +#. Sign the checksum file using the release key (``gpg + --clearsign``), then verify the signature (``gpg --verify``). *FIXME: + full, actual commands here*. + +If you're issuing multiple releases, repeat these steps for each release. + +Making the release(s) available to the public +============================================= + +Now you're ready to actually put the release out there. To do this: + +#. Upload the release package(s) to the djangoproject server; releases go + in ``/home/www/djangoproject.com/src/media/releases``, under a + directory for the appropriate version number (e.g. + ``/home/www/djangoproject.com/src/media/releases/1.5`` for a ``1.5.X`` + release.). + +#. Upload the checksum file(s); these go in + ``/home/www/djangoproject.com/src/media/pgp``. + +#. Test that the release packages install correctly using ``easy_install`` + and ``pip``. Here's how I do it (which requires `virtualenvwrapper`__): + + $ mktmpenv + $ easy_install http://www.djangoproject.com/download//tarball/ + $ deactivate + $ mktmpenv + $ pip install http://www.djangoproject.com/download//tarball/ + $ deactivate + + This just tests that the tarballs are available (i.e. redirects are up) and + that they install correctly, but it'll catch silly mistakes. *XXX FIXME: + buildout too?* + + __ https://pypi.python.org/pypi/virtualenvwrapper + +#. Ask a few people on IRC to verify the checksums by visiting the chucksums + file (e.g. https://www.djangoproject.com/m/pgp/Django-1.5b1.checksum.txt) + and following the instructions in it. + +#. If this is a security or regular release, register the new package with + PyPI by uploading the ``PGK-INFO`` file generated in the release package + *FIXME: be more specific about where this is and how to upload it.* + Don't do this for pre-releases. + +#. Deploy the template changes you made a while back by running `fab deploy` + from the ``djangoproject.com`` repo. + +#. Update the ``/download/`` flat page in the djangoproject.com + admin. For alpha/beta/RC releases, we add a temporary third section + to that page listing the preview package; otherwise, just update + the "Get the latest official version" section. + +#. Make up the blog post announcing the release live. + +#. Post the release announcement to the django-announce, + django-developers and django-users mailing lists. This should + include links to both the announcement blog post and the release + notes. *FIXME: make some templates with example text*. + +Post-release +============ + +You're almost done! All that's left to do now is: + +#. Update the ``VERSION`` tuple in ``django/__init__.py`` again, + incrementing to whatever the next expected release will be. For + example, after releasing 1.2.1, update ``VERSION`` to report "1.2.2 + pre-alpha". + +Notes on setting the VERSION tuple +================================== + +Django's version reporting is controlled by the ``VERSION`` tuple in +``django/__init__.py``. This is a five-element tuple, whose elements +are: + +#. Major version. +#. Minor version. +#. Micro version. +#. Status -- can be one of "alpha", "beta", "rc" or "final". +#. Series number, for alpha/beta/RC packages which run in sequence + (allowing, for example, "beta 1", "beta 2", etc.). + +For a final release, the status is always "final" and the series +number is always 0. A series number of 0 with an "alpha" status will +be reported as "pre-alpha". + +Some examples: + +* ``(1, 2, 1, 'final', 0)`` --> "1.2.1" + +* ``(1, 3, 0, 'alpha', 0)`` --> "1.3 pre-alpha" + +* ``(1, 3, 0, 'beta', 2)`` --> "1.3 beta 2" diff --git a/docs/internals/index.txt b/docs/internals/index.txt index 3ff4eb62d0..9a80a90286 100644 --- a/docs/internals/index.txt +++ b/docs/internals/index.txt @@ -22,3 +22,4 @@ the hood". release-process deprecation git + howto-release-django