Skip to content

Prepare the 2.0.0b1 release with GitHub Actions - #4

Merged
terapyon merged 6 commits into
mainfrom
release-prep
Oct 20, 2026
Merged

terapyon merged 6 commits into
mainfrom
release-prep

Conversation

@terapyon

Copy link
Copy Markdown
Member

Releases are published to PyPI from GitHub Actions with Trusted Publishing when a version tag is pushed.

Changes

  • release.yml: on a version tag, run the tests (plone-package.yml via workflow_call), check the tag against pyproject.toml, build, twine check and check that the wheel has msdoc2txt.jar, publish to PyPI after approval in the pypi environment, then sign with Sigstore and create a GitHub Release with the changelog section
  • The version lives only in pyproject.toml; __version__ comes from importlib.metadata; zest.releaser no longer uploads (release = false)
  • Classifier: Development Status :: 4 - Beta
  • sdist: tests and AGENTS.md left out; check-manifest configured
  • AGENTS.md: "Releasing"; README: Java 11 or later in the installation steps

Tests

All green: 13 tox environments + ruff + mypy (53 passed each, with Java), check-manifest, actionlint, zizmor. fullrelease was run in a throw-away clone (without pushing).

🤖 Generated with Claude Code

terapyon and others added 6 commits October 20, 2026 18:39
The first release of 2.0 goes out as 2.0.0b1, so the classifier says
"4 - Beta" instead of "5 - Production/Stable".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zest.releaser runs check-manifest in prerelease, and it failed: the Java
source, the news fragments, .editorconfig and the test samples are in git
but not in the sdist. setuptools also put tests/test_*.py into the sdist,
without conftest.py and the samples, so those tests could not run, and
"include *.md" took AGENTS.md along.

MANIFEST.in now prunes tests/ and excludes AGENTS.md, so the sdist has the
package, the README, the changelog and the licenses, as before.
[tool.check-manifest] ignores the rest.

RED: check-manifest exited 1 and suggested "recursive-include java ...",
"news ..." and "tests ...". GREEN: "lists of files in version control and
sdist match".
Mutations: dropping ".editorconfig", "java/**" or "news/**" from the
ignore list makes check-manifest fail; without "prune tests" the sdist has
6 files of tests/ again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zest.releaser 9.9.1 changes only python-file-with-version when it is set,
so prerelease left "version" in pyproject.toml at 2.0.0.dev0: the tag
2.0.0b1 would have built 2.0.0.dev0 distributions, and test_version, which
compared __version__ with the literal "2.0.0.dev0", would have failed at
the tag.

python-file-with-version is removed, so zest.releaser changes
pyproject.toml, and __version__ comes from the installed metadata. A
missing distribution raises PackageNotFoundError: the add-on cannot be used
without being installed, and z3c.autoinclude finds it by its metadata too.

[tool.zest-releaser] also gets release = false: fullrelease tags, and a
GitHub Actions workflow uploads to PyPI (next commit).

RED (throwaway clone, before): prerelease to 2.0.0b1 changed CHANGELOG.md,
news/ and __init__.py; pyproject.toml stayed at 2.0.0.dev0.
GREEN (throwaway clone, after): prerelease set pyproject.toml to 2.0.0b1,
release made the tag without uploading, postrelease set 2.0.0b2.dev0; the
tag builds 2.0.0b1 distributions whose __version__ is 2.0.0b1.
Mutation: __version__ = "2.0.0b1" (a literal) fails
test_version_is_the_one_of_the_distribution ('2.0.0b1' == '2.0.0.dev0').

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fullrelease pushes a tag such as 2.0.0b1, and release.yml takes it from
there:

- test: plone-package.yml, now callable with workflow_call.
- build: checks that the tag is the version in pyproject.toml, builds the
  sdist and the wheel with uv, runs twine check and checks that the wheel
  contains msdoc2txt.jar.
- publish: uploads to PyPI with Trusted Publishing, in the "pypi"
  environment (approval), with id-token: write only.
- github-release: signs the distributions with Sigstore and creates the
  GitHub Release with the section of the version from CHANGELOG.md and the
  files and signatures attached; a, b and rc versions are pre-releases.

A manual run (workflow_dispatch) tests and builds only; publish and
github-release run for a pushed tag only. Actions are pinned to the SHA of
a release at least two weeks old, credentials are not persisted, the
default permissions are contents: read, and setup-uv runs without its
cache.

zizmor 1.30.1 asks for the new "$/..." self-repository syntax for the
reusable workflow, but actionlint 1.7.12 (the latest release) rejects it,
so the finding is ignored on that line.

AGENTS.md describes the release steps and the one-time setup on PyPI and
GitHub.

Checks: actionlint 0, zizmor --offline 0 (1 ignored). The tag check and
the CHANGELOG extraction ran locally on a throwaway clone tagged 2.0.0b1
(12 entries; 1.0b6 gives its 1 entry; a version without a section gives
nothing, so the step fails).
Mutations: checkout without persist-credentials: false (zizmor
artipacked), the publish action on @release/v1 (zizmor high), "permissions:
write-all" (zizmor high), ${{ github.ref_name }} in run (zizmor template
injection), "needs: biuld" (actionlint). Turning the setup-uv cache back on
is not caught by either tool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The supported versions list Java 11 or later, but the first installation
step only said "Install Java"; 1.0b6 users may still have Java 8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There is one way to publish: the tag that fullrelease pushes. The manual
run (workflow_dispatch) is removed, and with it the "if" of publish and
github-release and of the tag check, which only a tag can start now.

The jar check reads the file list with "unzip -Z1" and names the missing
file in an error, and the Releasing section of AGENTS.md and the
check-manifest comment use the same words as c2.splitter.icu, so that the
two packages release the same way.

Checks: actionlint 0, zizmor --offline 0 (1 ignored), check-manifest
matches. The jar check passes on the 2.0.0b1 wheel of a throwaway clone
and fails, naming the jar, on that wheel with the jar removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@terapyon
terapyon merged commit 7dd7828 into main Oct 20, 2026
16 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