Skip to content

release.sh: batch preflight, defer push-after-publish, modern build#322

Merged
petemoore merged 1 commit intomainfrom
release-script-preflight
Apr 30, 2026
Merged

release.sh: batch preflight, defer push-after-publish, modern build#322
petemoore merged 1 commit intomainfrom
release-script-preflight

Conversation

@petemoore
Copy link
Copy Markdown
Member

@petemoore petemoore commented Apr 30, 2026

Summary

Restructures release.sh so that:

  • All preflight problems are reported in one batch instead of fail-fast, so a botched environment can be fixed in a single pass instead of N script invocations.
  • git push happens AFTER PyPI and Docker Hub publishes succeed. A publish failure now leaves the remote untouched, making recovery a matter of git reset --hard HEAD~1 && git tag -d v<version> instead of having a half-released tag on GitHub.
  • Build uses python -m build (PEP-517 frontend) instead of the deprecated setup.py sdist / bdist_wheel, with twine check run on the built dists before upload to catch metadata problems (bad README rendering, invalid classifiers, etc.) locally.
  • Drops the misleading --real flag. It only redirected PyPI between test and real; Docker Hub and GitHub were always published to the real registries, so it wasn't a true dry-run. Documented an end-to-end test-PyPI one-liner in RELEASING.md for the rare case it's wanted.

Companion RELEASING.md documents prerequisites, the workflow, pre-publish verification, and the recovery procedure.

New preflight checks

Check Why
docker, pass, gpg, python3 on PATH Catches missing tools before any destructive work
Docker daemon reachable + docker buildx available Avoids "tag pushed, then docker push fails"
GPG secret key present git tag -s would otherwise fail mid-script
pass entries exist (community-tc/secret-values.yml with tc-admin-release-pypi-password: line, plus hub.docker.com/taskclusterbot) Avoids reaching the password prompt with no password to paste
Branch is literally main Old SHA-only check passed on a feature branch sitting at the same commit as main

Existing checks (working tree clean, local HEAD == remote main HEAD, version regex on both old and new, tag-doesn't-exist locally + remotely, not in a virtualenv, signed tag) all preserved.

Comparison and out-of-scope items

This came out of a comparison with json-e/release.sh. Items deliberately not included in this PR:

  • Towncrier-style changelog automation — worth doing separately as it's a process change, not just a script change.
  • Auto-detect git remote — adds the requirement of having a named remote, with no real benefit; the hardcoded SSH URL is fine.
  • Idempotent re-run on partial failure — preflight should make partial failures rare, and reusing a release number after a partial failure has its own correctness problems.
  • Hermetic Docker-based release host — requires shipping pass + GPG key into a container, and docker buildx --push from inside Docker is awkward.

Test plan

  • Read the new release.sh and RELEASING.md for sanity
  • Verify CI passes (pytest + flake8 on the unchanged Python code)
  • On the next real release, the preflight phase exercises end-to-end

🤖 Generated with Claude Code

@petemoore petemoore force-pushed the release-script-preflight branch from fa79141 to d3416d6 Compare April 30, 2026 09:14
Restructure release.sh into a preflight phase that collects all
environment, credential and repo-state problems and reports them
together, plus a release phase that publishes to PyPI and Docker Hub
before pushing the commit and signed tag to GitHub.

New preflight checks:
  - Required binaries: docker, pass, gpg, python3
  - Docker daemon reachable + docker buildx available
  - GPG secret key present (required for git tag -s)
  - pass entries 'community-tc/secret-values.yml' (with the
    'tc-admin-release-pypi-password' line) and
    'hub.docker.com/taskclusterbot' both exist
  - Branch is explicitly 'main' (the prior SHA-only check passed on a
    feature branch sitting at the same commit as main)

Reorder so 'git push' happens AFTER the PyPI upload and Docker Hub
push succeed. A publish failure now leaves the remote untouched,
making recovery a matter of 'git reset --hard HEAD~1 && git tag -d
v<version>' rather than chasing a half-released tag.

Switch the build from the deprecated 'setup.py sdist / bdist_wheel'
to the PEP-517 frontend ('python -m build'), and run 'twine check'
on the built distributions before uploading so common metadata
problems (bad README rendering, invalid classifiers, ...) are caught
locally.

Drop the '--real' / '-r' flag. It only redirected PyPI between the
test and real indexes; Docker Hub and GitHub were always published
to the real registries, so the flag did not provide a true dry-run
mode and was misleading. End-to-end test-PyPI verification can be
done with a manual one-liner outside the release script (documented
in RELEASING.md).

Add RELEASING.md documenting prerequisites, the workflow each phase
executes, how to verify a release before publishing, and how to
recover from a failed run.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@petemoore petemoore force-pushed the release-script-preflight branch from d3416d6 to bc68c4c Compare April 30, 2026 09:25
@petemoore petemoore marked this pull request as ready for review April 30, 2026 09:27
@petemoore petemoore requested a review from a team as a code owner April 30, 2026 09:27
@petemoore petemoore moved this to In review in TC intake board Apr 30, 2026
@petemoore petemoore self-assigned this Apr 30, 2026
@petemoore petemoore merged commit 333f878 into main Apr 30, 2026
3 checks passed
@petemoore petemoore deleted the release-script-preflight branch April 30, 2026 14:37
@github-project-automation github-project-automation Bot moved this from In review to Done in TC intake board Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants