👷 ci(release): drive package tags with a GitHub App token#797
Merged
Conversation
The `create-package-tags` coordinator ran as `startup_failure` on the v2.0.0
release, so no package tags (and no PyPI publishes) were created.
Root causes:
1. The coordinator declares `contents: write` + `actions: write`, but this
repo's GITHUB_TOKEN is read-only, so GitHub refused to start the run.
2. Every `cd-<pkg>.yml` had a `paths:` filter on a `push` trigger that also
lists `tags:`. Path filters suppress tag pushes, so package tags never
triggered their build (this also broke direct bug-fix tag pushes).
Fix:
- The coordinator mints a GitHub App token and pushes the package tags with
it. App-token pushes trigger workflows (GITHUB_TOKEN pushes do not), so the
entire `actions: write` dispatch path — the ten `Trigger CD` steps and the
`dispatch-package-cd` composite action — is deleted.
- `cd-<pkg>.yml` now trigger on `workflow_dispatch` + their release tag only,
so a tag push (coordinator- or human-created) starts the build.
Behaviour change: the per-main-push TestPyPI dry-run is removed (it was the
`paths` filter that conflicted with tag triggering). Manual `workflow_dispatch`
still builds a package to verify it.
Requires two repository secrets for a GitHub App with contents:write —
RELEASE_APP_ID and RELEASE_APP_PRIVATE_KEY (documented in RELEASING.md).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the automated release pipeline by switching the “Create Package Tags” coordinator to push per-package release tags using a GitHub App token (so tag pushes can trigger downstream workflows), and by updating each package’s CD workflow to trigger on tags (and manual dispatch) without incompatible paths: filters.
Changes:
- Update
create-package-tags.ymlto mint a GitHub App token and use it for checkout + pushing package tags, removing the workflow-dispatch fan-out. - Remove
paths:/branches: mainfilters from package CD workflows so tag pushes reliably trigger builds. - Document the one-time GitHub App setup and clarify the new release flow in
RELEASING.md.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| RELEASING.md | Documents the GitHub App prerequisite and updates the end-to-end release flow description to match tag-driven CD. |
| .github/workflows/create-package-tags.yml | Mints a GitHub App token and pushes per-package tags directly (no workflow dispatch fan-out). |
| .github/workflows/cd-unxt.yml | CD build now triggers on release tags + workflow_dispatch only (removes paths/main gating). |
| .github/workflows/cd-unxt-api.yml | Same: tag + manual dispatch triggers only. |
| .github/workflows/cd-unxt-hypothesis.yml | Same: tag + manual dispatch triggers only. |
| .github/workflows/cd-unxts-api.yml | Same: tag + manual dispatch triggers only. |
| .github/workflows/cd-unxts-hypothesis.yml | Same: tag + manual dispatch triggers only. |
| .github/workflows/cd-unxts-interop-gala.yml | Same: tag + manual dispatch triggers only. |
| .github/workflows/cd-unxts-interop-matplotlib.yml | Same: tag + manual dispatch triggers only. |
| .github/workflows/cd-unxts-interop-xarray.yml | Same: tag + manual dispatch triggers only. |
| .github/workflows/cd-unxts-parametric.yml | Same: tag + manual dispatch triggers only. |
| .github/workflows/cd-unxts-linalg.yml | Same: tag + manual dispatch triggers only. |
| .github/actions/dispatch-package-cd/action.yml | Removes the composite action used for workflow dispatch fan-out (now unnecessary with App-token tag pushes). |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #797 +/- ##
==========================================
- Coverage 91.98% 91.96% -0.02%
==========================================
Files 83 81 -2
Lines 3766 3760 -6
Branches 313 313
==========================================
- Hits 3464 3458 -6
Misses 227 227
Partials 75 75 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
When the coordinator is re-run and every package tag already exists, it pushes nothing -- and a tag push is what starts each CD workflow -- so the run triggers no build. Emit a notice + the `gh workflow run cd-<pkg>.yml --ref <pkg>-vX.Y.Z` recovery command instead of exiting silently, so a re-run does not look like it did nothing when a package needs restarting. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`cd-<pkg>.yml` now also runs via `workflow_dispatch` on a tag ref (the documented manual-recovery path). The `Validate git tag` step in cd-unxt.yml was gated to `event_name == 'push'`, so a dispatch run skipped `scripts/validate_tag.py` (including the ".0 needs a coordinator tag" rule) yet still emitted verified release metadata the publish workflow acts on. Gate the step on `startsWith(github.ref, 'refs/tags/')` in all ten CD workflows so any tag ref is validated regardless of event, and unify the three pre-existing guard variants into one form. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…control - The GitHub App permission is "Contents: Read and write" (there is no write-only); fix the coordinator header comment to match RELEASING.md. - Document that pushing a `v*` / `<package>-v*` tag is itself a release trigger, so tag creation should be restricted (tag rulesets, and optional required reviewers on the pypi/testpypi environments). Note the App token is short-lived and scoped to this repo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Pushing
v2.0.0did not publish anything: theCreate Package Tagscoordinator ran asstartup_failure(0 jobs), so the per-package tags — and therefore every build/publish — were never created. The v2.0.0 release ultimately went out by pushing the 10 package tags and dispatching CD by hand.Two root causes, both fixed here:
create-package-tags.ymldeclarescontents: write(push tags) +actions: write(dispatch CD), but this repo'sGITHUB_TOKENis read-only (default_workflow_permissions: read), so GitHub refuses to start the run. (It worked at v1.11.0 when the setting was read/write.)paths:+tags:conflict. Everycd-<pkg>.ymlhas apaths:filter on apushtrigger that also liststags:. GitHub cannot satisfy a path filter for a tag push, so tag pushes never trigger these workflows — which is exactly why the hand-pushed package tags didn't start CD.What
create-package-tags.ymlnow mints a GitHub App token and pushes the package tags with it. Tags pushed with an App token do trigger workflows (tags pushed withGITHUB_TOKENdon't), so the wholeactions: writedispatch path is gone: the tenTrigger CD - …steps and the.github/actions/dispatch-package-cdcomposite action are deleted. The job no longer needs any write scope onGITHUB_TOKEN.cd-<pkg>.ymlnow triggers onworkflow_dispatch+ its release tag (unxt-v*,unxts-linalg-v*, …), with thepaths:/branches: mainfilter removed. A tag push — from the coordinator or a direct bug-fix tag — now starts the build. (Direct bug-fix tags were broken by the samepathsbug.)Net: −369 lines, and the release path no longer depends on the repo's token-permission setting.
The coordinator needs a GitHub App with Contents: Read and write, installed on this repo, plus two secrets:
RELEASE_APP_IDRELEASE_APP_PRIVATE_KEYWithout these the coordinator fails at its "Mint a GitHub App token" step. Full steps are in
RELEASING.md.The per-main-push TestPyPI dry-run is removed — publishing a dev version of each changed package to TestPyPI on every
mainpush. That behaviour is what required thepathsfilter, which is what broke tag triggering, so the two can't coexist cleanly in one workflow. A manualworkflow_dispatchstill builds a package to verify it (it doesn't publish). If you'd rather keep the dry-run, the alternative is to keep the dispatch mechanism but authenticate it with the App token instead — happy to switch to that.Testing
Validate GitHub Workflowsprek hook passes on every changed file.actions/create-github-app-token@v3.2.0,dorny/paths-filternot used in the final design.workflow_run→publish flow.🤖 Generated with Claude Code