How to Do a Release
-------------------

Periodically, the yt development community issues new releases. Since yt follows
`semantic versioning <http://semver.org/>`_, the type of release can be read off
from the version number used. Version numbers should follow the scheme
``MAJOR.MINOR.PATCH``. There are three kinds of possible releases:

* Bugfix releases

  These releases are regularly scheduled and will optimally happen approximately
  once a month. These releases should contain only fixes for bugs discovered in
  earlier releases and should not contain new features or API changes. Bugfix
  releases should increment the ``PATCH`` version number. Bugfix releases should
  *not* be generated by merging from the ``master`` branch, instead bugfix pull
  requests should be manually backported. Version ``3.2.2`` is a bugfix release.

* Minor releases

  These releases happen when new features are deemed ready to be merged into the
  ``stable`` branch and should not happen on a regular schedule. Minor releases
  can also include fixes for bugs if the fix is determined to be too invasive
  for a bugfix release. Minor releases should *not* include
  backwards-incompatible changes and should not change APIs.  If an API change
  is deemed to be necessary, the old API should continue to function but might
  trigger deprecation warnings. Minor releases should happen by merging the
  ``master`` branch into the ``stable`` branch. Minor releases should increment the
  ``MINOR`` version number and reset the ``PATCH`` version number to zero.
  Version ``3.3.0`` is a minor release.

* Major releases

  These releases happen when the development community decides to make major
  backwards-incompatible changes. In principle a major version release could
  include arbitrary changes to the library. Major version releases should only
  happen after extensive discussion and vetting among the developer and user
  community. Like minor releases, a major release should happen by merging the
  ``master`` branch into the ``stable`` branch. Major releases should increment the
  ``MAJOR`` version number and reset the ``MINOR`` and ``PATCH`` version numbers
  to zero. If it ever happens, version ``4.0.0`` will be a major release.

The job of doing a release differs depending on the kind of release. Below, we
describe the necessary steps for each kind of release in detail.

Doing a Bugfix Release
~~~~~~~~~~~~~~~~~~~~~~

As described above, bugfix releases are regularly scheduled updates for minor
releases to ensure fixes for bugs make their way out to users in a timely
manner. Since bugfix releases should not include new features, we do not issue
bugfix releases by simply merging from the development ``master`` branch into
the ``stable`` branch.  Instead, we manually cherry-pick bugfixes from the from
``master`` branch onto the ``stable`` branch.

If the pull request contains merge commits, you must take care to *not* backport
commits that merge with the main line of development on the ``master`` branch. Doing
so may bring unrelated changes, including new features, into a bugfix
release.

Once you've finished backporting push your work to Github. Once you've pushed to
your fork, you will be able to issue a pull request containing the backported
fixes just like any other yt pull request.

Doing a Minor or Major Release
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This is much simpler than a bugfix release.  All that needs to happen is the
``master`` branch must get merged into the ``stable`` branch, and any conflicts
that happen must be resolved.


Incrementing Version Numbers and Tagging a Release
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Before creating the tag for the release, you must increment the version numbers
that are hard-coded in a few files in the yt source so that version metadata
for the code is generated correctly. This includes things like ``yt.__version__``
and the version that gets read by the Python Package Index (PyPI) infrastructure.

The paths relative to the root of the repository for the three files that need
to be edited are:

* ``doc/source/conf.py``

  The ``version`` and ``release`` variables need to be updated.

* ``setup.py``

  The ``VERSION`` variable needs to be updated

* ``yt/__init__.py``

  The ``__version__`` variable must be updated.

Once these files have been updated, commit these updates. This is the commit we
will tag for the release.

To actually create the tag, issue the following command:

.. code-block:: bash

   git tag <tag-name>

Where ``<tag-name>`` follows the project's naming scheme for tags
(e.g. ``yt-3.2.1``). Once you are done, you will need to push the
tag to github::

  git push origin --tags

This assumes that you have configured the remote ``origin`` to point at the main
yt git repository. If you are doing a minor or major version number release, you
will also need to update back to the development branch and update the
development version numbers in the same files.


Uploading to PyPI
~~~~~~~~~~~~~~~~~

To actually upload the release to the Python Package Index, you just need to
issue the following commands:

.. code-block:: bash

   python setup.py sdist
   twine upload dist/*

You will be prompted for your PyPI credentials and then the package should
upload. Note that for this to complete successfully, you will need an account on
PyPI and that account will need to be registered as an "owner" of the yt
package. Right now there are five owners: Matt Turk, Britton Smith, Nathan
Goldbaum, John ZuHone, and Kacper Kowalik. In addition, you should attempt to
upload the yt package along with compiled binary wheel packages for various
platforms that we support.  You should contact John ZuHone about uploading
binary wheels to PyPI for Windows and OS X users, Kacper Kowalik for Linux
wheels, and contact Nathan Goldbaum about getting the Anaconda packages updated.


After the release is uploaded to PyPI, you should send out an announcement
e-mail to the yt mailing lists as well as other possibly interested mailing
lists for all but bugfix releases.
