Skip to content

Make releases in GitHub Actions only - #1

Merged
terapyon merged 5 commits into
mainfrom
release-in-actions
Nov 9, 2026
Merged

terapyon merged 5 commits into
mainfrom
release-in-actions

Conversation

@terapyon

@terapyon terapyon commented Nov 9, 2026

Copy link
Copy Markdown
Member

Make releases in GitHub Actions only, so no local zest.releaser is needed. The first release is 1.0.0a1.

What changes

  • release.yml starts from Actions → Release → Run workflow with a version. In order, the jobs are: prepare (version commit and tag), test, build, sign, publish (environment pypi, Trusted Publishing), GitHub Release, and back to development.
  • .github/scripts/release.py checks the version and computes the next development version. It has unit tests.
  • plone-package.yml takes a ref, so the release tests the prepared commit.
  • The development version is 1.0.0a1.dev0. With 1.0.0b1.dev0, 1.0.0a1 would not be a later version.
  • AGENTS.md describes the new steps. The release extra and [tool.zest-releaser] are removed.

⚠ Changes to existing behaviour

  • A version tag pushed by hand no longer publishes. Releases start only from the workflow.

Verification

tox: 250 passed in each of 13 envs (Plone 6.0–6.2 × Python 3.10–3.14). uv build, twine check --strict and check-manifest pass. actionlint reports no problems, and zizmor reports no findings.

Notes

  • This is the first project to run the prepare and back-to-development jobs on GitHub.
  • If main gets branch protection, the pushes by github-actions from the release jobs need an exception.

🤖 Generated with Claude Code

terapyon and others added 5 commits November 9, 2026 13:55
release.py checks the version to release (a normalized PEP 440 version
after the one in pyproject.toml, no tag yet, news fragments, run from
main; not a development version, a local version, an epoch, or both a
pre- and a post-release), sets the version in pyproject.toml, computes
the next development version the way zest.releaser does and tells
pre-releases (a, b, rc) for the GitHub Release. It is the script of
c2.splitter.icu (branch release-in-actions).

tests/test_release_script.py imports it; the test extra declares
packaging, and tomli on Python 3.10. Ruff and mypy check
.github/scripts as well. Two more tests are about the first release of
this package: 1.0.0a1 is after 1.0.0a1.dev0 and is a pre-release, and
it is not after 1.0.0b1.dev0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Release workflow is now run by hand (Actions, Release, Run
workflow) with the version to release, instead of being started by the
tag of zest.releaser's fullrelease. It is the workflow of
c2.splitter.icu (branch release-in-actions), with the name, the PyPI
URL and the files checked in the wheel of this package:

- prepare checks the version (.github/scripts/release.py), writes the
  news fragments into CHANGELOG.md with towncrier, sets the version,
  commits "Preparing release <version>" and tags it; push-release
  checks the bundle (one commit on the commit of the run that changes
  only pyproject.toml, CHANGELOG.md and removes news fragments) and
  pushes the commit and the tag together.
- test runs plone-package.yml on that commit (it takes a ref now);
  build builds and checks the sdist and the wheel (twine,
  check-manifest, the ZCML and the profiles in the wheel) and takes the
  notes of the version from CHANGELOG.md.
- publish uploads to PyPI with Trusted Publishing after a reviewer of
  the pypi environment approves (skip-existing, for a re-run after a
  partial upload); sign signs with Sigstore in a job that cannot write;
  github-release makes the GitHub Release, a pre-release for a, b and
  rc (release.py prerelease).
- development sets the next development version and push-development
  pushes it, unless main has moved.

Only the push jobs and github-release may write, and they run only
checkout, download-artifact, git and gh. uv is pinned to 0.13.4 with
its sha256. The action SHAs are those of plone-package.yml.

AGENTS.md describes the steps, what to do when a release fails, and the
settings needed once. pyproject.toml has no release extra and no
zest-releaser table any more; the comment on __version__ says that the
release workflow changes the version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first release is 1.0.0a1. The release workflow refuses a version
that is not after the one in pyproject.toml, and 1.0.0a1 comes before
1.0.0b1.dev0 (PEP 440), so it would have stopped at prepare. With
1.0.0a1.dev0, release.py check 1.0.0a1 passes on main (tried with
GITHUB_REF=refs/heads/main), and the next development version after it
is 1.0.0a2.dev0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_version compared __version__ with "1.0.0b1.dev0". The release
workflow changes the version in pyproject.toml and then runs the tests
of the release commit, so the test would have stopped every release
(it already failed with 1.0.0a1.dev0). test_version_is_the_one_of_the_distribution
checks that __version__ is the version of the installed distribution,
as c2.splitter.icu does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
push-development told to run ".github/scripts/release.py back-to-development
<version>" when main had moved. The script is not executable (mode
100644, no shebang), so that gave exit 126. The log and AGENTS.md now
give the command the workflow uses itself:

    uv run --no-project --python 3.12 --with packaging .github/scripts/release.py back-to-development <version>

(tried on a copy with 1.0.0a1: it prints 1.0.0a2.dev0 and writes it).

AGENTS.md also says not to build the files again for a release that
stopped half way: the wheel and the sdist of the same commit get other
sha256 when built again, and skip-existing does not check that they
match; use the dist artifact of the run that stopped (found by Codex).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@terapyon
terapyon merged commit 6307238 into main Nov 9, 2026
15 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