Release process¶
This page is for maintainers preparing a PyMetaAnalysis release. Releases are
tag-driven: an accepted vX.Y.Z tag builds the distributions, publishes them
to PyPI with short-lived OpenID Connect credentials, and creates a GitHub
Release containing the same artifacts.
One-time repository configuration¶
GitHub Pages¶
In repository Settings > Pages, select GitHub Actions as the publishing
source. The pages.yml workflow then builds the strict MkDocs site from
main and deploys it through the protected github-pages environment.
PyPI trusted publisher¶
Create the PyMetaAnalysis project or a pending publisher on PyPI with these
values:
| Field | Value |
|---|---|
| PyPI project | PyMetaAnalysis |
| GitHub owner | ZhaoboDing |
| Repository | PyMetaAnalysis |
| Workflow | release.yml |
| Environment | pypi |
Create a GitHub environment named pypi and require maintainer approval where
the repository plan supports it. Protect release tags matching v*. The
publishing job receives only id-token: write; no long-lived PyPI token is
stored in GitHub.
See the PyPI documentation for creating a project with a trusted publisher and its GitHub Actions security guidance.
Prepare a release pull request¶
- Confirm the distribution name is still available for the first release.
- Review public API and report-schema changes since the previous release.
- Set the same final version in
src/meta_analyze/_version.pyandCITATION.cff. Hatchling reads the package version dynamically from_version.py. - Move the relevant
CHANGELOG.mdentries fromUnreleasedto a dated heading such as## X.Y.Z - YYYY-MM-DD. - Run the complete validation suite.
The local consistency check is:
python tools/check_release.py
For a proposed tag, add:
python tools/check_release.py --tag vX.Y.Z
The tag check rejects development versions, version mismatches, and releases without a dated changelog heading.
The tag-triggered release workflow independently installs the test extra and
runs the full branch-coverage suite before building distributions. A tag
cannot reach the PyPI environment merely because it belongs to main; the
tagged source must pass this release-time test gate.
Validate the candidate¶
python -m ruff format --check .
python -m ruff check .
actionlint
python -m mypy
python -m pytest --cov=meta_analyze --cov-branch --cov-report=term-missing
python -m mkdocs build --strict
python tools/execute_notebooks.py
python -m build
python tools/inspect_distribution.py dist
python benchmarks/benchmark_core.py
For the 1.0 stabilization cycle, independent external statistical review is a release gate: follow the roadmap acceptance matrix and review checklist. Earlier 0.x releases did not require this gate. Release notes and the validation status must accurately describe the evidence for the released commit and must not imply that a formal audit has occurred when it has not.
The 0.10 foundation batch does not bump the version. Remind the maintainer before changing version metadata in a release PR. RC preparation must also verify prerelease metadata, installation selection, and tag handling; do not assume final-version smoke commands exercise an RC. Creating a development draft PR does not authorize merging, tagging, or PyPI publication.
Statistical release acceptance checks¶
Before preparing any release version commit, confirm that:
- every statistical change has formula documentation, boundary tests, and an independent comparison where an appropriate implementation is available;
- committed R fixtures still reproduce from their adjacent generator scripts, with every intentional cross-software difference explained;
- public API, result, report-schema, methods, limitations, interoperability, and validation documentation agree with the behavior being released;
- example notebooks and performance benchmarks cover new public workflows where appropriate; and
- the complete validation suite above passes with the final release metadata.
Only after these checks pass should the release pull request set the final version and create its dated changelog heading.
Tag and publish¶
After the release pull request is merged, update local main and tag the merge
commit:
git switch main
git pull --ff-only
git tag -a vX.Y.Z -m "PyMetaAnalysis X.Y.Z"
git push origin vX.Y.Z
The release workflow then:
- verifies that the tag commit belongs to
main; - checks version and changelog consistency;
- builds and inspects the wheel and source distribution;
- runs the release performance benchmark against the built wheel;
- publishes the distributions through PyPI Trusted Publishing;
- creates a GitHub Release with distributions and benchmark output.
Never replace an existing release artifact or reuse a published version. If a release is defective, fix it and publish a new version.
Post-release checks¶
In a clean environment:
python -m venv .release-smoke
.release-smoke/Scripts/python -m pip install PyMetaAnalysis
.release-smoke/Scripts/python -c "import meta_analyze as ma; print(ma.__version__)"
Use .release-smoke/bin/python instead on POSIX systems. Confirm the PyPI page,
GitHub Release, documentation site, citation metadata, and installation command
all refer to the same version.