Improve & update release process to reflect recent changes (#3242)

- Formalise release cadence guidelines
- Overhaul release steps to be easier to follow and more thorough
- Reorder changelog template to something more sensible
- Update release automation docs to reflect recent improvements (notably
  the addition of in-repo mypyc wheel builds)

Co-authored-by: Felix Hildén <felix.hilden@gmail.com>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
Richard Si 2022-08-31 17:46:48 -04:00 committed by GitHub
parent 767604e03f
commit 7757078ecd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 152 additions and 81 deletions

View File

@ -1,40 +1,85 @@
# Release process # Release process
_Black_ has had a lot of work automating its release process. This document sets out to _Black_ has had a lot of work done into standardizing and automating its release
explain what everything does and how to release _Black_ using said automation. process. This document sets out to explain how everything works and how to release
_Black_ using said automation.
## Cutting a Release ## Release cadence
To cut a release, you must be a _Black_ maintainer with `GitHub Release` creation **We aim to release whatever is on `main` every 1-2 months.** This ensures merged
access. Using this access, the release process is: improvements and bugfixes are shipped to users reasonably quickly, while not massively
fracturing the user-base with too many versions. This also keeps the workload on
maintainers consistent and predictable.
1. Cut a new PR editing `CHANGES.md` and the docs to version the latest changes If there's not much new on `main` to justify a release, it's acceptable to skip a
month's release. Ideally January releases should not be skipped because as per our
[stability policy](labels/stability-policy), the first release in a new calendar year
may make changes to the _stable_ style. While the policy applies to the first release
(instead of only January releases), confining changes to the stable style to January
will keep things predictable (and nicer) for users.
Unless there is a serious regression or bug that requires immediate patching, **there
should not be more than one release per month**. While version numbers are cheap,
releases require a maintainer to both commit to do the actual cutting of a release, but
also to be able to deal with the potential fallout post-release. Releasing more
frequently than monthly nets rapidly diminishing returns.
## Cutting a release
**You must have `write` permissions for the _Black_ repository to cut a release.**
The 10,000 foot view of the release process is that you prepare a release PR and then
publish a [GitHub Release]. This triggers [release automation](#release-workflows) that
builds all release artifacts and publishes them to the various platforms we publish to.
To cut a release:
1. Determine the release's version number
- **_Black_ follows the [CalVer] versioning standard using the `YY.M.N` format**
- So unless there already has been a release during this month, `N` should be `0`
- Example: the first release in January, 2022 → `22.1.0`
1. File a PR editing `CHANGES.md` and the docs to version the latest changes
1. Replace the `## Unreleased` header with the version number
1. Remove any empty sections for the current release 1. Remove any empty sections for the current release
2. Add a new empty template for the next release (template below) 1. (_optional_) Read through and copy-edit the changelog (eg. by moving entries,
3. Example PR: [#2616](https://github.com/psf/black/pull/2616) fixing typos, or rephrasing entries)
4. Example title: `Update CHANGES.md for XX.X release` 1. Add a new empty template for the next release above
2. Once the release PR is merged ensure all CI passes ([template below](#changelog-template))
1. If not, ensure there is an Issue open for the cause of failing CI (generally we'd 1. Update references to the latest version in
want this fixed before cutting a release) {doc}`/integrations/source_version_control` and
3. Open `CHANGES.md` and copy the _raw markdown_ of the latest changes to use in the {doc}`/usage_and_configuration/the_basics`
description of the GitHub Release. - Example PR: [GH-3139]
4. Go and [cut a release](https://github.com/psf/black/releases) using the GitHub UI so 1. Once the release PR is merged, wait until all CI passes
that all workflows noted below are triggered. - If CI does not pass, **stop** and investigate the failure(s) as generally we'd want
1. The release version and tag should be the [CalVer](https://calver.org) version to fix failing CI before cutting a release
_Black_ used for the current release e.g. `21.6` / `21.5b1` 1. [Draft a new GitHub Release][new-release]
2. _Black_ uses [setuptools scm](https://pypi.org/project/setuptools-scm/) to pull 1. Click `Choose a tag` and type in the version number, then select the
the current version for the package builds and release. `Create new tag: YY.M.N on publish` option that appears
5. Once the release is cut, you're basically done. It's a good practice to go and watch 1. Verify that the new tag targets the `main` branch
to make sure all the [GitHub Actions](https://github.com/psf/black/actions) pass, 1. You can leave the release title blank, GitHub will default to the tag name
although you should receive an email to your registered GitHub email address should 1. Copy and paste the _raw changelog Markdown_ for the current release into the
one fail. description box
1. You should see all the release workflows and lint/unittests workflows running on 1. Publish the GitHub Release, triggering [release automation](#release-workflows) that
the new tag in the Actions UI will handle the rest
1. At this point, you're basically done. It's good practice to go and [watch and verify
that all the release workflows pass][black-actions], although you will receive a
GitHub notification should something fail.
- If something fails, don't panic. Please go read the respective workflow's logs and
configuration file to reverse-engineer your way to a fix/solution.
If anything fails, please go read the respective action's log output and configuration Congratulations! You've successfully cut a new release of _Black_. Go and stand up and
file to reverse engineer your way to a fix/soluton. take a break, you deserve it.
## Changelog template ```{important}
Once the release artifacts reach PyPI, you may see new issues being filed indicating
regressions. While regressions are not great, they don't automatically mean a hotfix
release is warranted. Unless the regressions are serious and impact many users, a hotfix
release is probably unnecessary.
In the end, use your best judgement and ask other maintainers for their thoughts.
```
### Changelog template
Use the following template for a clean changelog after the release: Use the following template for a clean changelog after the release:
@ -45,7 +90,7 @@ Use the following template for a clean changelog after the release:
<!-- Include any especially major or disruptive changes here --> <!-- Include any especially major or disruptive changes here -->
### Style ### Stable style
<!-- Changes that affect Black's stable style --> <!-- Changes that affect Black's stable style -->
@ -53,27 +98,10 @@ Use the following template for a clean changelog after the release:
<!-- Changes that affect Black's preview style --> <!-- Changes that affect Black's preview style -->
### _Blackd_
<!-- Changes to blackd -->
### Configuration ### Configuration
<!-- Changes to how Black can be configured --> <!-- Changes to how Black can be configured -->
### Documentation
<!-- Major changes to documentation and policies. Small docs changes
don't need a changelog entry. -->
### Integrations
<!-- For example, Docker, GitHub Actions, pre-commit, editors -->
### Output
<!-- Changes to Black's terminal output and error messages -->
### Packaging ### Packaging
<!-- Changes to how Black is packaged, such as dependency requirements --> <!-- Changes to how Black is packaged, such as dependency requirements -->
@ -86,60 +114,99 @@ Use the following template for a clean changelog after the release:
<!-- Changes that improve Black's performance. --> <!-- Changes that improve Black's performance. -->
### Output
<!-- Changes to Black's terminal output and error messages -->
### _Blackd_
<!-- Changes to blackd -->
### Integrations
<!-- For example, Docker, GitHub Actions, pre-commit, editors -->
### Documentation
<!-- Major changes to documentation and policies. Small docs changes
don't need a changelog entry. -->
``` ```
## Release workflows ## Release workflows
All _Blacks_'s automation workflows use GitHub Actions. All workflows are therefore All of _Black_'s release automation uses [GitHub Actions]. All workflows are therefore
configured using `.yml` files in the `.github/workflows` directory of the _Black_ configured using YAML files in the `.github/workflows` directory of the _Black_
repository. repository.
They are triggered by the publication of a [GitHub Release].
Below are descriptions of our release workflows. Below are descriptions of our release workflows.
### Docker ### Publish to PyPI
This workflow uses the QEMU powered `buildx` feature of docker to upload a `arm64` and This is our main workflow. It builds an [sdist] and [wheels] to upload to PyPI where the
`amd64`/`x86_64` build of the official _Black_ docker image™. vast majority of users will download Black from. It's divided into three job groups:
- Currently this workflow uses an API Token associated with @cooperlees account #### sdist + pure wheel
### pypi_upload This single job builds the sdist and pure Python wheel (i.e., a wheel that only contains
Python code) using [build] and then uploads them to PyPI using [twine]. These artifacts
are general-purpose and can be used on basically any platform supported by Python.
This workflow builds a Python #### mypyc wheels (…)
[sdist](https://docs.python.org/3/distutils/sourcedist.html) and
[wheel](https://pythonwheels.com) using the latest
[setuptools](https://pypi.org/project/setuptools/) and
[wheel](https://pypi.org/project/wheel/) modules.
It will then use [twine](https://pypi.org/project/twine/) to upload both release formats We use [mypyc] to compile _Black_ into a CPython C extension for significantly improved
to PyPI for general downloading of the _Black_ Python package. This is where performance. Wheels built with mypyc are platform and Python version specific.
[pip](https://pypi.org/project/pip/) looks by default. [Supported platforms are documented in the FAQ](labels/mypyc-support).
- Currently this workflow uses an API token associated with @ambv's PyPI account These matrix jobs use [cibuildwheel] which handles the complicated task of building C
extensions for many environments for us. Since building these wheels is slow, there are
multiple mypyc wheels jobs (hence the term "matrix") that build for a specific platform
(as noted in the job name in parentheses).
### Upload self-contained binaries Like the previous job group, the built wheels are uploaded to PyPI using [twine].
This workflow builds self-contained binaries for multiple platforms. This allows people #### Update stable branch
to download the executable for their platform and run _Black_ without a
[Python Runtime](https://wiki.python.org/moin/PythonImplementations) installed.
The created binaries are attached/stored on the associated So this job doesn't _really_ belong here, but updating the `stable` branch after the
[GitHub Release](https://github.com/psf/black/releases) for download over _IPv4 only_ other PyPI jobs pass (they must pass for this job to start) makes the most sense. This
(GitHub still does not have IPv6 access 😢). saves us from remembering to update the branch sometime after cutting the release.
## Moving the `stable` tag - _Currently this workflow uses an API token associated with @ambv's PyPI account_
_Black_ provides a stable tag for people who want to move along as _Black_ developers ### Publish executables
deem the newest version reliable. Here the _Black_ developers will move once the release
has been problem free for at least ~24 hours from release. Given the large _Black_
userbase we hear about bad bugs quickly. We do strive to continually improve our CI too.
### Tag moving process This workflow builds native executables for multiple platforms using [PyInstaller]. This
allows people to download the executable for their platform and run _Black_ without a
[Python runtime](https://wiki.python.org/moin/PythonImplementations) installed.
#### stable The created binaries are stored on the associated GitHub Release for download over _IPv4
only_ (GitHub still does not have IPv6 access 😢).
From a rebased `main` checkout: ### docker
1. `git tag -f stable VERSION_TAG` This workflow uses the QEMU powered `buildx` feature of Docker to upload an `arm64` and
1. e.g. `git tag -f stable 21.5b1` `amd64`/`x86_64` build of the official _Black_ Docker image™.
1. `git push --tags -f`
- _Currently this workflow uses an API Token associated with @cooperlees account_
```{note}
This also runs on each push to `main`.
```
[black-actions]: https://github.com/psf/black/actions
[build]: https://pypa-build.readthedocs.io/
[calver]: https://calver.org
[cibuildwheel]: https://cibuildwheel.readthedocs.io/
[gh-3139]: https://github.com/psf/black/pull/3139
[github actions]: https://github.com/features/actions
[github release]: https://github.com/psf/black/releases
[new-release]: https://github.com/psf/black/releases/new
[mypyc]: https://mypyc.readthedocs.io/
[mypyc-platform-support]:
/faq.html#what-is-compiled-yes-no-all-about-in-the-version-output
[pyinstaller]: https://www.pyinstaller.org/
[sdist]:
https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist
[twine]: https://github.com/features/actions
[wheels]: https://packaging.python.org/en/latest/glossary/#term-Wheel

View File

@ -114,6 +114,8 @@ errors is not a goal. It can format all code accepted by CPython (if you find an
where that doesn't hold, please report a bug!), but it may also format some code that where that doesn't hold, please report a bug!), but it may also format some code that
CPython doesn't accept. CPython doesn't accept.
(labels/mypyc-support)=
## What is `compiled: yes/no` all about in the version output? ## What is `compiled: yes/no` all about in the version output?
While _Black_ is indeed a pure Python project, we use [mypyc] to compile _Black_ into a While _Black_ is indeed a pure Python project, we use [mypyc] to compile _Black_ into a

View File

@ -19,6 +19,8 @@ style aspects and details might change according to the stability policy present
below. Ongoing style considerations are tracked on GitHub with the below. Ongoing style considerations are tracked on GitHub with the
[design](https://github.com/psf/black/labels/T%3A%20design) issue label. [design](https://github.com/psf/black/labels/T%3A%20design) issue label.
(labels/stability-policy)=
## Stability Policy ## Stability Policy
The following policy applies for the _Black_ code style, in non pre-release versions of The following policy applies for the _Black_ code style, in non pre-release versions of