Release guide#
This document is only relevant for Matplotlib release managers.
A guide for developers who are doing a Matplotlib release.
Versioning Scheme#
Matplotlib follows theIntended Effort Versioning (EffVer)versioning scheme:macro.meso.micro.
- macro
A release that we expect a large effort from our users to upgrade to. The v1 to v2 transitionincluded a complete overhaul of the default styles and the v2 to v3 transition involveddropping support for Python 2.
Future macro versions would include changes of a comparable scale that can not be doneincrementally in meso releases.
- meso
A release that we expect some effort from our users to upgrade to. We target aMeso release every 6 months. These release are primarily intended to releasenew features to our users, however they also contain intentional feature deprecations andremovals perour policy.
- micro
A release that we expect users to require little to no effort to upgrade to. PerourBackport strategy we only backport bug fixes to the maintenance branch.We expect minimal impact on users other than possibly breaking work arounds to afixed bug orbugs being used as features.
These are released as-needed, but typically every 1-2 months between meso releases.
Making the release branch#
Note
This assumes that a read-only remote for the canonical repository isremote and a read/write remote isDANGER
When a new meso release (vX.Y.0) is approaching, a new release branch must be made.When precisely this should happen is up to the release manager, but this point is wheremost new features intended for the meso release are merged and you are entering afeature freeze (i.e. newly implemented features will be going into vX.Y+1).This does not necessarily mean that no further changes will be made prior to release,just that those changes will be made using the backport system.
For an upcomingv3.7.0 release, first create the branch:
gitswitchmaingitpullgitswitch-cv3.7.xgitpushDANGERv3.7.x
Update thev3.7.0 milestone so that the description reads:
NewfeaturesandAPIchangeson-merge:backporttov3.7.x
Micro versions should instead read:
Bugfixesanddocstringchangeson-merge:backporttov3.7.x
Check all active milestones for consistency. Older milestones should also backportto higher meso versions (e.g.v3.6.3 andv3.6-doc should backport to bothv3.6.x andv3.7.x once thev3.7.x branch exists and while PR backports arestill targetingv3.6.x).
Close milestones for versions that are unlikely to be released, e.g. micro versions ofolder meso releases. Remilestone issues/PRs that are now untagged to the appropriatefuture release milestone.
Create the milestone for the next-next meso release (i.e.v3.9.0, asv3.8.0should already exist). While most active items should go in the next meso release,this milestone can help with longer term planning, especially around deprecationcycles.
Testing#
We useGitHub Actionsfor continuous integration. When preparing for a release, the final taggedcommit should be tested locally before it is uploaded:
pytest-n8.In addition the following test should be run and manually inspected:
pythontools/memleak.pyagg1000agg.pdfRun the User Acceptance Tests for the NBAgg and ipympl backends:
jupyternotebooklib/matplotlib/backends/web_backend/nbagg_uat.ipynb
For ipympl, restart the kernel, add a cell for%matplotlibwidget and donot run the cell withmatplotlib.use('nbagg'). Tests which checkconnection_info, usereshow, or test the OO interface are not expectedto work foripympl.
GitHub statistics#
We automatically extract GitHub issue, PRs, and authors from GitHub via the API. Toprepare this list:
Archive the existing GitHub statistics page.
Copy the current
doc/release/github_stats.rsttodoc/release/prev_whats_new/github_stats_X.Y.Z.rst.Change the link target at the top of the file.
Remove the "Previous GitHub Stats" section at the end.
For example, when updating from v3.7.0 to v3.7.1:
cpdoc/release/github_stats.rstdoc/release/prev_whats_new/github_stats_3.7.0.rst$EDITORdoc/release/prev_whats_new/github_stats_3.7.0.rst# Change contents as noted above.gitadddoc/release/prev_whats_new/github_stats_3.7.0.rst
Re-generate the updated stats:
pythontools/github_stats.py--since-tagv3.7.0--milestone=v3.7.1\--project'matplotlib/matplotlib'--links>doc/release/github_stats.rst
Review and commit changes. Some issue/PR titles may not be valid reST (the mostcommon issue is
*which is interpreted as unclosed markup). Also confirm thatcodespelldoes not find any issues.
Note
Make sure you authenticate against the GitHub API. If you do not, you will getblocked by GitHub for going over the API rate limits. You can authenticate in one oftwo ways:
using the
keyringpackage;pipinstallkeyringand then whenrunning the stats script, you will be prompted for user name and password,that will be stored in your system keyring, or,using a personal access token; generate a new tokenon this GitHub page with the
repo:public_reposcope and place the token in~/.ghoauth.
Update and validate the docs#
Merge*-doc branch#
Merge the most recent 'doc' branch (e.g.,v3.7.0-doc) into the branch youare going to tag on and delete the doc branch on GitHub.
Update supported versions in Security Policy#
When making macro or meso releases, update the supported versions in the SecurityPolicy inSECURITY.md.
For meso version release update the table inSECURITY.md to specify that thetwo most recent meso releases in the current macro version series are supported.
For a macro version release update the table inSECURITY.md to specify that thelast meso version in the previous macro version series is still supported. Droppingsupport for the last version of a macro version series will be handled on an ad-hocbasis.
Update release notes#
What's new#
Only needed for macro and meso releases. Bugfix releases should not have newfeatures.
Merge the contents of all the files indoc/release/next_whats_new/ into a singlefiledoc/release/prev_whats_new/whats_new_X.Y.0.rst and delete the individualfiles.
API changes#
Primarily needed for macro and meso releases. We may sometimes have APIchanges in micro releases.
Merge the contents of all the files indoc/api/next_api_changes/ into a singlefiledoc/api/prev_api_changes/api_changes_X.Y.Z.rst and delete theindividual files.
Release notes TOC#
Updatedoc/release/release_notes.rst:
For macro and meso releases add a new section
X.Y===..toctree:::maxdepth: 1 prev_whats_new/whats_new_X.Y.0.rst ../api/prev_api_changes/api_changes_X.Y.0.rst prev_whats_new/github_stats_X.Y.0.rst
For micro releases add the GitHub stats and (if present) the API changes tothe existing X.Y section
../api/prev_api_changes/api_changes_X.Y.Z.rstprev_whats_new/github_stats_X.Y.Z.rst
Update version switcher#
The version switcher is populated fromhttps://matplotlib.org/devdocs/_static/switcher.json.
Since it's always taken from devdocs, update the filedoc/_static/switcher.jsonon the main branch through a regular PR:
If a micro release, update the version from
X.Y.Z-1toX.Y.ZIf a meso release
X.Y.0:update the dev entry to
name:X.Y+1(dev)update the stable entry to
name:X.Y(stable)add a new entry for the previous stable (
name:X.Y-1).
Once that PR is merged, the devdocs site will be updated automatically.
Verify that docs build#
Finally, make sure that the docs build cleanly:
make-CdocO=-j$(nproc)htmllatexpdf
After the docs are built, check that all of the links, internal and external, are stillvalid. We uselinkchecker for this:
pipinstalllinkcheckerpushddoc/build/htmllinkcheckerindex.html--check-externpopd
Address any issues which may arise. The internal links are checked on Circle CI, so thisshould only flag failed external links.
Create release commit and tag#
To create the tag, first create an empty commit with a very terse set of the releasenotes in the commit message:
gitcommit--allow-empty
and then create a signed, annotated tag with the same text in the body message:
gittag-a-sv3.7.0
which will prompt you for your GPG key password and an annotation. For pre-releases itis important to followPEP 440 so that the build artifacts will sort correctly inPyPI.
To prevent issues with any down-stream builders which download the tarball from GitHubit is important to move all branches away from the commit with the tag[1]:
gitcommit--allow-empty
Push the branch to GitHub. This is done prior to pushing the tag as a last step in ensuringthat the branch was fully up to date. If it fails, re-fetch and recreate commits andtag over an up to date branch:
gitpushDANGERv3.7.x
Finally, push the tag to GitHub:
gitpushDANGERv3.7.0
Congratulations, the scariest part is done!This assumes the release branch has already been made.Usually this is done at the time of feature freeze for a meso release (which oftencoincides with the last micro release of the previous meso version)
[1]The tarball that is provided by GitHub is produced usinggit archive.We usesetuptools_scm which uses a format string inlib/matplotlib/_version.py to havegit insert alist of references to exported commit (see.gitattributes for the configuration). This string isthen used bysetuptools_scm to produce the correct version,based on the git tag, when users install from the tarball.However, if there is a branch pointed at the tagged commit,then the branch name will also be included in the tarball.When the branch eventually moves, anyone who checked the hashof the tarball before the branch moved will have an incorrecthash.
To generate the file that GitHub does use:
gitarchivev3.7.0-omatplotlib-3.7.0.tar.gz--prefix=matplotlib-3.7.0/If this is a final release, also create a 'doc' branch (this is notdone for pre-releases):
gitbranchv3.7.0-docgitpushDANGERv3.7.0-doc
Update (or create) thev3.7-doc milestone.The description should include the instruction for meeseeksmachine to backport changeswith thev3.7-doc milestone to both thev3.7.x branch and thev3.7.0-doc branch:
Documentationchanges(.rstfilesandexamples)on-merge:backporttov3.7.xon-merge:backporttov3.7.0-doc
Check all active milestones for consistency. Older doc milestones should also backport tohigher meso versions (e.g.v3.6-doc should backport to bothv3.6.x andv3.7.xif thev3.7.x branch exists)
Release management / DOI#
Via theGitHub UI, turn thenewly pushed tag into a release. If this is a pre-release remember to mark it as such.
For final releases, also get the DOI fromZenodo (which willautomatically produce one once the tag is pushed). Add the DOI post-fix and version tothe dictionary intools/cache_zenodo_svg.py and run the script.
This will download the new SVG todoc/_static/zenodo_cache/postfix.svg andeditdoc/project/citing.rst. Commit the new SVG, the change totools/cache_zenodo_svg.py, and the changes todoc/project/citing.rstto the VER-doc branch and push to GitHub.
gitcheckoutv3.7.0-doc$EDITORtools/cache_zenodo_svg.pypythontools/cache_zenodo_svg.pygitcommit-agitpushDANGERv3.7.0-doc:v3.7.0-docBuilding binaries#
We distribute macOS, Windows, and many Linux wheels as well as a source tarball viaPyPI.
Windows, macOS and manylinux wheels are built on GitHub Actions. Builds are triggeredby the GitHub Action defined in a separaterelease repository, and wheelswill be available as artifacts of the build. Both a source tarball and the wheels willbe automatically uploaded to PyPI once all of them have been built.
To trigger the build for the
matplotlib-releaserepository:If not already created, create a release branch for the meso version (e.g.
v3.10.x)Edit the
SOURCE_REF_TO_BUILDenvironment variable at the top ofwheels.ymlon the release branch to point to the release tag.Run the workflow from the release branch, with "pypi" selected for the pypi environmentusing theWorkflow Dispatch trigger
This will run cibuildwheel and upload to PyPI using the Trusted Publishers GitHub Action.
The auto-tick bot should open a pull request into theconda-forge feedstock. Review and merge (if youhave the power to).
Warning
Because this is automated, it is extremely important to bump all branches away fromthe tag as discussed inCreate release commit and tag.
Manually uploading to PyPI#
Note
As noted above, the GitHub Actions workflow should build and upload source tarballsand wheels automatically. If for some reason, you need to upload these artifactsmanually, then follow the instructions in this section.
Once you have collected all of the wheels (expect this to take a few hours), generatethe tarball:
gitcheckoutv3.7.0gitclean-xfdpython-mbuild--sdist
and copy all of the wheels intodist directory. First, check that the dist filesare OK:
twinecheckdist/*
and then usetwine to upload all of the files to PyPI
twineupload-sdist/matplotlib*tar.gztwineuploaddist/*whl
Congratulations, you have now done the second scariest part!
Build and deploy documentation#
To build the documentation you must have the tagged version installed, butbuild the docs from thever-doc branch. An easy way to arrange this is:
pipinstallmatplotlibpipinstall-rrequirements/doc/doc-requirements.txtgitcheckoutv3.7.0-docgitclean-xfdmake-CdocO="-t release -j$(nproc)"htmllatexpdfLATEXMKOPTS="-silent -f"
which will build both the HTML and PDF version of the documentation.
The built documentation exists in thematplotlib.github.com repository.Pushing changes to main automatically updates the website.
The documentation is organized in subdirectories by version. The latest stable releaseis symlinked from thestable directory. The documentation for current main isbuilt on Circle CI and pushed to thedevdocs repository. These are available atmatplotlib.org/devdocs.
Assuming you have this repository checked out in the same directory asmatplotlib
cd../matplotlib.github.comcp-a../matplotlib/doc/build/html3.7.0rm3.7.0/.buildinfocp../matplotlib/doc/build/latex/Matplotlib.pdf3.7.0
which will copy the built docs over. If this is a final release, link thestable subdirectory to the newest version:
rmstableln-s3.7.0stableYou will also need to editsitemap.xml to includethe newly released version. Now commit and push everything to GitHub
gitadd*gitcommit-a-m'Updating docs for v3.7.0'gitpushDANGERmainCongratulations you have now done the third scariest part!
If you have access, clear the CloudFlare caches.
It typically takes about 5-10 minutes for the website to process the push and update thelive web page (remember to clear your browser cache).
Remember toupdate the version switcher!
Merge up changes to main#
After a release is done, the changes from the release branch should be merged into themain branch. This is primarily done so that the released tag is on the main branchsogitdescribe (and thussetuptools-scm) has the most current tag.Secondarily, changes made during release (including removing individualized releasenotes, fixing broken links, and updating the version switcher) are bubbled up tomain.
Git conflicts are very likely to arise, though aside from changes made directly to therelease branch (mostly as part of the release), they should be relatively-easily resolvedby using the version frommain. This is not a universal rule, and care should betaken to ensure correctness:
gitswitchmaingitpullgitswitch-cmerge_up_v3.7.0gitmergev3.7.x# resolve conflictsgitmerge--continueDue to branch protections for themain branch, this is merged via a standard pullrequest, though the PR cleanliness status check is expected to fail. The PR should notbe squashed because the intent is to merge the branch histories.
Publicize this release#
After the release is published to PyPI and conda, it should be announcedthrough our communication channels:
Send a short version of the release notes and acknowledgments to all theMailing lists
Post highlights and link toWhat's new on theactivesocial media accounts
Add a release announcement to the "News" section ofmatplotlib.org by editing
docs/body.html. Link to the auto-generated announcement discourse post,which is inAnnouncements > matplotlib-announcements.
Conda packages#
The Matplotlib project itself does not release conda packages. In particular,the Matplotlib release manager is not responsible for conda packaging.
For information on the packaging of Matplotlib for conda-forge seeconda-forge/matplotlib-feedstock.