Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOC: update "how to release" docs #3806

Merged
merged 2 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ include yt/visualization/mapserver/html/Leaflet.Coordinates-0.1.5.css
include yt/visualization/mapserver/html/Leaflet.Coordinates-0.1.5.src.js
include yt/utilities/tests/cosmology_answers.yml
include yt/utilities/mesh_types.yaml
exclude scripts/pr_backport.py
exclude yt/utilities/lib/cykdtree/c_kdtree.cpp
prune docker
prune tests
Expand Down
12 changes: 6 additions & 6 deletions doc/source/developing/deprecating_features.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. how-to-deprecate::

How to deprecate a feature
--------------------------

Expand All @@ -7,10 +9,10 @@ A functionality can be marked as deprecated using
message and two version numbers, indicating the earliest release deprecating the feature
and the one in which it will be removed completely.

The message should indicate a viable alternative to replace the deprecated feature at
the user level.
``since`` and ``removal`` are required [#]_ keyword-only arguments so as to enforce
readability of the source code.
The message should indicate a viable alternative to replace the deprecated
feature at the user level. ``since`` and ``removal`` arguments should indicate
in which release something was first deprecated, and when it's expected to be
removed. While ``since`` is required, ``removal`` is optional.

Here's an example call.

Expand All @@ -30,8 +32,6 @@ If a whole function or class is marked as deprecated, it should be removed from
``doc/source/reference/api/api.rst``.


.. [#] ``since`` is not required yet as of yt 4.0.0 because existing warnings predate its introduction.

Deprecating Derived Fields
--------------------------

Expand Down
164 changes: 84 additions & 80 deletions doc/source/developing/releasing.rst
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
How to Do a Release
-------------------

Periodically, the yt development community issues new releases. Since yt follows
`semantic versioning <https://semver.org/>`_, the type of release can be read off
Periodically, the yt development community issues new releases. yt loosely follows
`semantic versioning <https://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
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
releases only increment the ``PATCH`` version number. Bugfix releases should
*not* be generated by merging from the ``main`` branch, instead bugfix pull
requests should be manually backported. Version ``3.2.2`` is a bugfix release.
requests should be backported to a dedicated branch.
See :ref:`doing-a-bugfix-release`. Version ``3.2.2`` is a bugfix release.

* Minor releases

Expand All @@ -31,7 +31,7 @@ from the version number used. Version numbers should follow the scheme
* Major releases

These releases happen when the development community decides to make major
backwards-incompatible changes. In principle a major version release could
backwards-incompatible changes intentionally. 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
Expand All @@ -42,36 +42,51 @@ from the version number used. Version numbers should follow the scheme
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:

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 ``main`` branch into
the ``stable`` branch. Instead, we manually cherry-pick bugfixes from the from
``main`` branch onto the ``stable`` branch.

You may find the ``pr_backport.py`` script located in the ``scripts`` folder at
the root of the repository to be helpful. This script uses the github API to
find the list of pull requests made since the last release and prompts the user
to backport each pull request individually. Note that the backport process is
fully manual. The easiest way to do it is to download the diff for the pull
request (the URL for the diff is printed out by the backport script) and then
use ``git apply`` to apply the patch for the pull request to a local copy of yt
with the ``stable`` branch checked out.

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.
the ``stable`` branch. Instead, commits are cherry-picked from the ``main``
branch to a backport branch, which is itself merged into ``stable`` when a release
happens.

Backport branches are named after the minor version then descend from, followed by
an ``x``. For instance, ``yt-4.0.x`` is the backport branch for all releases in the 4.0 series.

Backporting bugfixes can be done automatically using the `MeeseeksBox bot
<https://meeseeksbox.github.io>`_.

This necessitates having a Github milestone dedicated to the release, configured
with a comment in its description such as ``on-merge: backport to yt-4.0.x``.
Then, every PR that was triaged into the milestone will be replicated as a
backport PR by the bot when it's merged into main. Some backports are non-trivial and
require human attention; if conflicts occur, the bot will provide detailed
instructions to perfom the task manually.

In short, a manual backport consist of 4 steps

- checking out the backport branch locally
- create a new branch from there
- cherry-picking the merge commit from the original PR with ``git cherry-pick -m1 <commit sha>``
- opening a PR to the backport branch


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

This is much simpler than a bugfix release. All that needs to happen is the
``main`` branch must get merged into the ``stable`` branch, and any conflicts
that happen must be resolved, almost always in favor of the state of the code on
the ``main`` branch.
This is much simpler than a bugfix release. First, make sure that every
deprecated features targeted for removal in the new release are removed from the
``main`` branch, ideally in a single PR. Such a PR can be issued at any point
between the previous minor or major release and the new one. Then, all that
needs to happen is the ``main`` branch must get merged into the ``stable``
branch, and any conflicts that happen must be resolved, almost always in favor
of the state of the code on the ``main`` branch.


Incrementing Version Numbers and Tagging a Release
Expand Down Expand Up @@ -111,7 +126,7 @@ 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
git push origin --tag

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
Expand Down Expand Up @@ -148,67 +163,49 @@ https://yt-project.org/sdist, like so::
You may find it helpful to set up an ssh config for dickenson to make this
command a bit easier to execute.

Updating conda-forge and building wheels
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Before we finish the release, we need to generate new binary builds by updating
yt's conda-forge feedstock and the yt-wheels repository.

Wheels and ``multibuild``
+++++++++++++++++++++++++

Binary wheels for yt are managed via the ``multibuild`` project. For yt the main
point of access is at https://github.com/yt-project/yt-wheels. Take a look at
the pull requests from the previous few releases to get an idea of what to do,
but briefly you will need to update the multibuild and yt submodules to their
latest state and then commit the changes to the submodules::

$ cd multibuild
$ git pull origin devel
$ cd ../yt
$ git pull origin stable
$ cd ..
$ git commit -am "updating multibuild and yt submodules"

Next you will need to update the ``.travis.yml`` and ``appveyor.yaml`` files to
build the latest tag of yt. You may also need to update elsewhere in the file if
yt's dependencies changed or if yt dropped or added support for a Python
version. To generate new wheels you need to push the changes to GitHub. A good
process to follow is to first submit a pull request to test the changes and make sure
the wheels can be built. Once they pass, you can merge the changes into ``main``
and wait for the wheel files to be uploaded to
https://anaconda.org/multibuild-wheels-staging/yt/files
(note that the wheels will not be uploaded until the changes have been
merged into ``main``). Once the wheels are uploaded, download the
wheel files for the release and copy them to the ``dist`` folder in the yt
repository so that they are sitting next to the source distribution
we created earlier. Here's a
one-liner to download all of the wheels for the yt 3.6.1 release::

$ wget -r -nd -A 'yt-3.6.1-*whl' https://anaconda.org/multibuild-wheels-staging/yt/files

Uploading to PyPI
+++++++++++++++++

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

We distribute yt on two main channels: PyPI.org and conda-forge, in this order.

PyPI
++++

The publication process for PyPI is automated for the most part, via Github
actions, using ``.github/workflows/wheels.yaml``. Specifically, a release is
pushed to PyPI when a new git tag starting with ``yt-`` is pushed to the main
repo. Let's review the details here.

PyPI releases contain the source code (as a tarball), and wheels. Wheels are
compiled distributions of the source code. They are OS specific as well as
Python-version specific. Producing wheels for every supported combination of OS
and Python versions is done with `cibuildwheels
<https://cibuildwheel.readthedocs.org>`_

Upload to PyPI is automated via Github Actions `upload-artifact
<https://github.com/actions/upload-artifact>`_ and `download-artifact
<https://github.com/actions/upload-artifact>`_.

Note that automated uploads are currently perfomed using Matt Turk's
credentials.

If that worked, you can skip to the next section. Otherwise, upload can be
perfomed manually by first downloading the artifacts ``wheels`` and ``tarball``
from the workflow webpage, then at the command line (make sure that the
``dist`` directory doesn't exist or is empty)

.. code-block:: bash

unzip tarball.zip -d dist
unzip wheels.zip -d dist
python -m pip install --upgrade twine
twine upload dist/*

Please ensure that both the source distribution and binary wheels are present in
the ``dist`` folder before doing this. Directions on generating binary wheels
are described in the section immediately preceding this one.

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" or "maintainer"
of the yt package.
Right now the following people have access to upload packages: Matt Turk,
Britton Smith, Nathan Goldbaum, John ZuHone, Kacper Kowalik, and Madicken Munk.
The yt package source distribution should be uploaded along with compiled
binary wheel packages for various platforms that we support.


``conda-forge``
+++++++++++++++
Expand All @@ -217,9 +214,11 @@ Conda-forge packages for yt are managed via the yt feedstock, located at
https://github.com/conda-forge/yt-feedstock. When a release is pushed to PyPI a
bot should detect a new version and issue a PR to the feedstock with the new
version automatically. When this feedstock is updated, make sure that the
SHA256 hash of the tarball matches the one you uploaded to dickenson and that
SHA256 hash of the tarball matches the one you uploaded to PyPI and that
the version number matches the one that is being released.

In case the automated PR fails CI, feedstock maintainers are allowed to push to
the bot's branch with any fixes required.

Should you need to update the feedstock manually, you will
need to update the ``meta.yaml`` file located in the ``recipe`` folder in the
Expand All @@ -237,3 +236,8 @@ After the release is uploaded to `PyPI <https://pypi.org/project/yt/#files>`_ an
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.

Creating a Github release attached to the tag also offers a couple advantages.
Auto-generated release notes can be a good starting point, though it's best to
edit out PRs that not directly affecting users, and these notes can be edited
before (draft mode) and after the release, so errors can be corrected after the fact.
114 changes: 0 additions & 114 deletions scripts/pr_backport.py

This file was deleted.