Release Checklist¶
Use scripts/release.py to prepare and publish MatchPatch releases. The script
keeps the release path intentionally small: pass the new version, let it run the
checks, then decide whether to publish the tag.
MatchPatch releases are tag-driven. A pushed tag named v<version> starts
.github/workflows/release.yml. The workflow verifies that the tag matches
project.version in pyproject.toml, builds and publishes the Python
distributions to PyPI, builds the offline documentation payload, and builds,
smoke-tests, and attaches the Windows installer to the GitHub Release.
Prerequisites¶
You have push access to
noseglasses/MatchPatch.You can publish GitHub Releases for the repository.
The PyPI project is configured for trusted publishing from the GitHub Actions
pypienvironment.gh,git,uv, and the MatchPatch WSL tooling are available.gh auth statussucceeds before publishing.The working tree is clean before starting the release.
The script checks these prerequisites before it edits pyproject.toml. For a
publishing run, it verifies local tools, required MatchPatch helper scripts,
the release workflow publishing configuration, GitHub authentication, repository
permissions, release visibility, the remote release branch, and a dry-run push
to the release branch. PyPI trusted publishing cannot be fully proven from a
local checkout; the script checks that the release workflow is wired for the
pypi environment, OIDC id-token: write, uv publish, and installer upload,
then the GitHub Actions release job proves the PyPI trusted-publisher
configuration when it publishes.
Normal Release¶
From the repository root, run the release script with the package version
without the leading v:
scripts/release.py 0.2.0 --publish
The script will:
check release prerequisites before changing files;
require a clean working tree;
require the release branch, normally
main;fetch tags and fast-forward the branch;
check that
v0.2.0does not already exist locally or onorigin;update
project.versioninpyproject.toml;run
scripts/sync-wsl.sh;run
ruff check .,ruff format --check .,ty check, andpytestfrom the shared WSL environment;run the pre-push hook suite;
build the strict Sphinx docs;
build and smoke-test the wheel and source distribution;
run
git diff --check;commit the version bump as
chore(release): v0.2.0;create the annotated tag
v0.2.0;ask for confirmation before publishing;
push the release commit and tag;
watch the GitHub Actions release workflow;
check that the GitHub Release has
MatchPatch-Setup-0.2.0.exe;check PyPI package versions.
Use --yes when running in a trusted terminal and you do not want the final
publish confirmation prompt:
scripts/release.py 0.2.0 --publish --yes
For a cautious two-step release, prepare everything locally first:
scripts/release.py 0.2.0
If that succeeds, publish the prepared local tag later:
scripts/release.py 0.2.0 --publish
Release Notes¶
Write release notes in a temporary Markdown file before publishing if you do not want the placeholder GitHub Release notes created by the workflow.
scripts/release.py 0.2.0 --publish --notes-file /tmp/matchpatch-0.2.0-notes.md
The script applies that file to the GitHub Release after the release workflow finishes.
Suggested sections:
Highlights
User-visible changes
Installer changes
Documentation changes
Fixes
Known issues
Optional Checks¶
Run the GUI test wrapper as part of the release:
scripts/release.py 0.2.0 --gui-tests
Build and smoke-test the Windows installer locally before tagging:
scripts/release.py 0.2.0 --installer
The installer check uses scripts/test-windows-installer-from-wsl.sh, which
mirrors the checkout to the configured Windows workdir and runs the native
installer smoke tests. This is slower, but useful for releases that touch
packaging, GUI startup, bundled docs, or installer behavior.
Useful Flags¶
--branch <name>releases from a branch other thanmain.--allow-current-branchpermits the current branch instead of enforcing the branch name.--skip-pullskipsgit fetch origin --tagsandgit pull --ff-only.--skip-syncskipsscripts/sync-wsl.sh.--skip-pre-pushskips the pre-push hook suite.--publishpushes the release commit and tag.--yesskips the publish confirmation prompt.
Avoid skip flags for a normal public release. They are intended for recovering from local tooling trouble after you already understand which check was run elsewhere.
Version Rules¶
Pass a PEP 440 package version, for example
0.2.0.Do not include the leading
vwhen calling the script.The Git tag is always
v<version>.Do not reuse a version after PyPI publishing succeeds.
Do not reuse a pushed tag after a partial public release. Prefer a new patch version unless the tag never left your machine.
After Publishing¶
Open the GitHub Release and check the notes:
gh release view v0.2.0 --web
Open PyPI and verify the new version:
gh browse https://pypi.org/project/matchpatch/
Download the installer from the GitHub Release and run a final smoke test on a Windows machine if the release includes installer or GUI changes.
Failure Recovery¶
If the script fails before it creates the commit, fix the reported problem and
run it again. If it changed pyproject.toml, either keep the version change and
continue after fixing the problem, or restore the file manually before choosing
a different version.
If the script fails after creating the local tag but before publishing, inspect the state:
git status --short
git show --stat v0.2.0
Delete an unpublished local tag if you need to redo the local release:
git tag -d v0.2.0
If the tag was pushed and PyPI publishing succeeded, do not reuse the same version. Fix the problem, choose a new patch version, and release again.
Rerun a failed GitHub Actions release job only when the source tag is still correct and the failure was environmental:
gh run rerun <run-id> --failed
If an installer asset must be replaced after a successful rebuild, upload it
with --clobber only when the tag still represents the exact source used to
build that asset:
gh release upload v0.2.0 dist/installer/MatchPatch-Setup-0.2.0.exe --clobber