Skip to content

Add a release process note - #70

Merged
gyli merged 1 commit into
masterfrom
docs/releasing-note
Sep 17, 2026
Merged

gyli merged 1 commit into
masterfrom
docs/releasing-note

Conversation

@gyli

@gyli gyli commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Nothing wrote down how a release is cut. The steps lived in release.sh's closing echo, a comment at the top of publish.yml, and nowhere else. That is enough to follow once and not enough to follow again a year later, which is roughly the gap between the last two releases.

RELEASING.md at the repository root covers:

  • One-time setup: the PyPI trusted-publishing configuration and the pypi environment the publish job declares. Without both, the workflow runs and fails at the upload step.
  • Before releasing: what ./release.sh covers, plus the two checks it does not.
  • Releasing: version, changelog, tag, GitHub release, watching the run.
  • After: downloading from PyPI to confirm the upload rather than assuming it.
  • Notes: the handful of things that are easy to learn the hard way.

Two things it records deliberately

The suite cannot catch a packaging mistake. It imports the working tree, so a missing file or a wrong dependency is invisible to it. The note gives a loop that installs each built artifact into a throwaway venv and draws a chart, in both install modes — a plain install must draw rectangles and refuse icons= with a message naming the extra, an [icons] install must draw icons. That combination is only observable from a clean environment.

A version can never be replaced on PyPI. A file uploaded under a version number is permanent even after deletion, so a mistake means releasing the next patch version. That is the reason the artifact checks belong before the tag is pushed rather than after.

On the content

Written with X.Y.Z placeholders and no concrete version numbers, so it does not go stale the way a worked example would. No account names or contact details.

Every command in it was run verbatim before committing, including the four-way artifact loop, which passed for wheel and sdist in both modes.

test_documentation.py collects docs/*.md, docs/examples/*.md and README.md, so a root-level RELEASING.md is not executed by the suite. Confirmed rather than assumed. MANIFEST.in has include *.md, so it will ship in the sdist alongside CHANGELOG.md; say the word if you would rather exclude it.

Nothing wrote down how a release is cut. The steps lived in release.sh's closing echo,
a comment at the top of publish.yml, and nowhere else, which is enough to follow once
and not enough to follow again a year later.

RELEASING.md covers the one-time PyPI trusted-publishing setup, the checks worth doing
by hand before tagging, the tag and release steps, and what to verify afterwards.

Two things it records that are easy to learn the hard way: a version can never be
replaced on PyPI, so the artifacts are exercised from a clean environment before the tag
is pushed rather than after; and the suite imports the working tree, so it cannot catch a
packaging mistake, which is why the built artifacts are installed into throwaway venvs in
both install modes.

Written without version numbers so it does not go stale.
@gyli
gyli merged commit 0e40bc4 into master Sep 17, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant