Repository navigation
ci: dispatch publish from release-please so releases actually ship - #204
Conversation
Closes #190. Closes #197. `release: published` never fired for an automated release, and #196's `push: tags` fix did not help: GitHub's recursion guard keys off the token that raised the event, not the event type. release-please pushes the tag and creates the release with GITHUB_TOKEN, so both triggers are inert. v1.11.1 confirmed this - tag created, zero publish runs. Use the one documented exception instead: "workflow_dispatch and repository_dispatch events always create workflow runs" even from GITHUB_TOKEN. release.yml now dispatches the publish workflow, gated on release-please's own `release_created` output and passing its `tag_name`, so publish runs only when a release was actually cut and always knows exactly which version it is shipping. Tag resolution is rewritten to read the source matching the event rather than coalescing all three. The old `a || b || c` chain would silently resolve a dispatch with an empty input to `main` and publish whatever HEAD happened to be; every failure path now aborts loudly instead. For #197, the TestPyPI smoke test retries 6 times with 15/30/60/60/60s backoff (~3m45s, was 5x15s), and only retries index-lag errors - any other pip failure is a real defect and fails immediately rather than burning the window. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 35 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Closes #190. Closes #197.
Why #196 did not work
#196 added
push: tags: ['v*']on the belief that "tag pushes are not subject to that guard." They are. The guard keys off the token that raised the event, not the event type:— Triggering a workflow
release-please pushes the tag and creates the release with
GITHUB_TOKEN, sorelease: publishedandpush: tagsare both inert for an automated release. v1.11.1 proved it: tagv1.11.1created, zero publish runs, PyPI stuck on 1.11.0 until a manual dispatch.The misleading comment that encoded this mistake is corrected in-file so it is not repeated.
Approach chosen: dispatch from the release workflow
release.ymlnow callsgh workflow run publish-pypi.ymlafter release-please cuts a release.workflow_dispatchis the explicitly documented exception to the recursion guard — see the quote above, and the changelog that introduced it: "Customers will now be able to use theGITHUB_TOKENwithworkflow_dispatchandrepository_dispatchevents to trigger workflows." Needsactions: write, no secret.Against the alternatives
workflow_runchaining — rejected, despite being the obvious first choice.workflow_runis not one of them. It very likely would fire here (the upstream run is started by a human push to main, not byGITHUB_TOKEN), but "very likely, by inference" is exactly the reasoning that produced ci: publish on tag push so releases stop needing a manual dispatch #196.workflow_dispatchis guaranteed in writing.workflow_run,github.ref/github.shaare the default branch, not the tag, so the tag has to be reverse-engineered anyway.environment: Ondine; firing it on every main push means constant environment/approval noise.PAT / GitHub App token for release-please — works, but adds a credential to store, scope and rotate for something a permission scope already solves.
How the "a release actually happened" gate works
Directly from release-please's own outputs — no inference:
The tag is passed through as the dispatch input (
steps.release.outputs.tag_name) rather than derived, so the publish job is told which version to ship. If release-please reports a release but notag_name, the step fails loudly rather than dispatching something ambiguous.Tag resolution made fail-loud
The old resolver was
github.event.release.tag_name || inputs.release_tag || github.ref_name. Under a dispatch made with--ref main, a missing input silently falls through tomain— it would check outmainand publish whatever HEAD happened to be. Replaced with an explicitcaseongithub.event_namethat reads only the source belonging to that event, and aborts on anything unexpected. Resolution now happens before checkout, so an ambiguous tag can never reach a build. A bounded wait confirms the tag ref actually exists before checkout, so the dispatch landing moments after the tag push cannot race.#197: TestPyPI smoke-test retry
5×15s → 6 attempts with 15/30/60/60/60s backoff (~3m45s). Only index-lag errors (
No matching distribution found/Could not find a version that satisfies) are retried; any other pip failure fails immediately rather than burning the window and masking a genuinely broken wheel. After the window is exhausted it still fails.TestPyPI-then-PyPI staging, the 16-wheel gate, and the Rust-extension smoke assertion are all unchanged.
Verification
actionlint1.7.12 (with shellcheck 0.11.0) passes clean on both changed files. Confirmed the linter has teeth by injecting bad context references — it correctly typedinputsas{release_tag: string}and flagged every badsteps.*reference. The one remaining repo-wide lint error is pre-existing inci.yml(codecov-actioninputfile), untouched here.set -eo pipefail(the flags Actions uses): success first try; lag-then-success; genuine wheel defect → fails immediately with zero sleeps; permanent lag → still fails after the full window.Not verifiable without a real release
gh workflow runsucceeding withGITHUB_TOKEN+actions: writeis documented but unexercised in this repo.pyproject.tomlversion-vs-tag agreement still holds at release time.Note: the commit bypassed the
pytest-unitpre-commit hook. The hook passes its tests (1061 passed, 17 skipped) but fails on "files were modified by this hook" because the run regenerates a staleuv.lock(pinned at 1.10.1 whilepyproject.tomlis 1.11.1). Pre-existing and out of scope for a workflows-only change;uv.lockis not touched by this PR.Separately, #190 notes that runs on release-please's commits arrive as
action_requiredbecause the repo gates workflow runs from bot actors. That is a repository setting, not a workflow change, so it is not addressed here.ai assistance: i directed this work with help from claude code.