Skip to content

👷 ci(release): drive package tags with a GitHub App token#797

Merged
nstarman merged 4 commits into
GalacticDynamics:mainfrom
nstarman:fix-release-app-token
Jul 24, 2026
Merged

👷 ci(release): drive package tags with a GitHub App token#797
nstarman merged 4 commits into
GalacticDynamics:mainfrom
nstarman:fix-release-app-token

Conversation

@nstarman

Copy link
Copy Markdown
Contributor

Why

Pushing v2.0.0 did not publish anything: the Create Package Tags coordinator ran as startup_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:

  1. The coordinator can't get the token it needs. create-package-tags.yml declares contents: write (push tags) + actions: write (dispatch CD), but this repo's GITHUB_TOKEN is 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.)
  2. paths: + tags: conflict. Every cd-<pkg>.yml has a paths: filter on a push trigger that also lists tags:. 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

  • Coordinator → GitHub App token. create-package-tags.yml now mints a GitHub App token and pushes the package tags with it. Tags pushed with an App token do trigger workflows (tags pushed with GITHUB_TOKEN don't), so the whole actions: write dispatch path is gone: the ten Trigger CD - … steps and the .github/actions/dispatch-package-cd composite action are deleted. The job no longer needs any write scope on GITHUB_TOKEN.
  • CD workflows trigger on tags + dispatch only. Each cd-<pkg>.yml now triggers on workflow_dispatch + its release tag (unxt-v*, unxts-linalg-v*, …), with the paths:/branches: main filter 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 same paths bug.)

Net: −369 lines, and the release path no longer depends on the repo's token-permission setting.

⚠️ Required setup before this works (one-time)

The coordinator needs a GitHub App with Contents: Read and write, installed on this repo, plus two secrets:

Secret Value
RELEASE_APP_ID the App's ID
RELEASE_APP_PRIVATE_KEY a generated private key (PEM)

Without these the coordinator fails at its "Mint a GitHub App token" step. Full steps are in RELEASING.md.

⚠️ Behaviour change

The per-main-push TestPyPI dry-run is removed — publishing a dev version of each changed package to TestPyPI on every main push. That behaviour is what required the paths filter, which is what broke tag triggering, so the two can't coexist cleanly in one workflow. A manual workflow_dispatch still 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

  • All 22 touched/adjacent workflows parse; the repo's Validate GitHub Workflows prek hook passes on every changed file.
  • Action pins: actions/create-github-app-token@v3.2.0, dorny/paths-filter not used in the final design.
  • Not runnable end-to-end until the App + secrets exist; logic reviewed against the current two-stage build→workflow_run→publish flow.

🤖 Generated with Claude Code

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>
@nstarman
nstarman requested a review from a team as a code owner July 24, 2026 18:43
Copilot AI review requested due to automatic review settings July 24, 2026 18:43
@github-actions github-actions Bot added 👷 Add / update CI build system Add or update CI build system. 🧩 unxts-hypothesis Issues/PRs affecting the unxts.hypothesis namespace package 🧩 unxts-interop-gala Issues/PRs affecting the unxts.interop.gala namespace package 🧩 unxts-interop-matplotlib Issues/PRs affecting the unxts.interop.matplotlib namespace package 🧩 unxts-interop-xarray Issues/PRs affecting the unxts.interop.xarray namespace package 🧩 unxts-api Issues/PRs affecting the unxts.api namespace package 🧩 unxts-parametric Issues/PRs affecting the unxts.parametric namespace package 🧩 unxts-linalg Issues/PRs affecting the unxts.linalg namespace package labels Jul 24, 2026
@nstarman nstarman added this to the future milestone Jul 24, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.yml to mint a GitHub App token and use it for checkout + pushing package tags, removing the workflow-dispatch fan-out.
  • Remove paths: / branches: main filters 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).

Comment thread .github/workflows/create-package-tags.yml
@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.96%. Comparing base (26f8c18) to head (596b5b0).

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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>
Copilot AI review requested due to automatic review settings July 24, 2026 19:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/cd-unxt.yml
`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>
Copilot AI review requested due to automatic review settings July 24, 2026 19:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comment thread .github/workflows/create-package-tags.yml Outdated
Comment thread RELEASING.md
…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>
Copilot AI review requested due to automatic review settings July 24, 2026 19:53
@github-actions github-actions Bot added the 📝 Add / update documentation Add or update documentation. label Jul 24, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

@nstarman
nstarman merged commit c9d3955 into GalacticDynamics:main Jul 24, 2026
60 of 61 checks passed
@nstarman
nstarman deleted the fix-release-app-token branch July 24, 2026 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

👷 Add / update CI build system Add or update CI build system. 📝 Add / update documentation Add or update documentation. 🧩 unxts-api Issues/PRs affecting the unxts.api namespace package 🧩 unxts-hypothesis Issues/PRs affecting the unxts.hypothesis namespace package 🧩 unxts-interop-gala Issues/PRs affecting the unxts.interop.gala namespace package 🧩 unxts-interop-matplotlib Issues/PRs affecting the unxts.interop.matplotlib namespace package 🧩 unxts-interop-xarray Issues/PRs affecting the unxts.interop.xarray namespace package 🧩 unxts-linalg Issues/PRs affecting the unxts.linalg namespace package 🧩 unxts-parametric Issues/PRs affecting the unxts.parametric namespace package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants