Repository navigation
fix(release): publish the release through the REST API, not the gh CLI - #57
Merged
Merged
Conversation
The Release workflow runs on vars.CI_RUNNER when set, and a self-hosted
runner image cannot be assumed to ship the GitHub CLI. On such a runner
the job pushed the annotated tag and then failed at gh release create
with 'gh: command not found', leaving a tag without a release; a rerun
then refuses, because the commit is already tagged.
The step now POSTs to ${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases
with curl and the same fields (tag name as title, generated notes,
target = the dispatched commit), using the job's GITHUB_TOKEN with
contents: write. That works on GitHub-hosted and self-hosted runners,
public and private repositories alike, and the job needs only git and
curl. gh was used nowhere else in the workflow.
shared:github 3.1.0 -> 3.1.1. New test: the emitted release.yml calls
no gh command and posts to the releases endpoint (fails on the old
template).
- Drop `--fail-with-body` (curl >= 7.76): Ubuntu 20.04 and Debian bullseye
ship older curl and would fail after the tag push. Check the HTTP status
with `-w '%{http_code}'` instead, and print the API's error body on failure
rather than sending it to /dev/null.
- `--retry 3` for transient errors, since any failure here leaves a pushed
tag without a release and a rerun refuses the already-tagged commit.
- Add the `CI_RUNNER_APT_PACKAGES` step from lint-test.yml, before checkout so
it can also provide git.
- Comments: drop the gh tool list from the emitter, and move the incident
narrative out of the source per the comment policy.
- Test: match any `gh` word on command lines, and pin the printf format and
its argument order.
…lure - Pass the Authorization header to curl on stdin (`-H @-`): argv shows in `ps` for every user on a shared self-hosted runner. - `|| status=000` so a transport failure (DNS, refused, TLS) still reaches the error branch instead of `set -e` ending the step silently. - Word the error for a retried POST whose first attempt already created the release: "if the release is missing, create it from the tag". - Docs: `CI_RUNNER_APT_PACKAGES` now applies to both workflows.
- On any non-201, check `GET /releases/tags/$TAG` before failing: a retried POST whose first attempt created the release gets 422 `already_exists`, which used to fail the run and then block the rerun on the existing tag. - `|| true` instead of `|| status=000`: `-w` already prints 000 on a transport failure, and the override could mask a real status.
christian-at-sevenlab
previously approved these changes
Oct 7, 2026
added 5 commits
October 7, 2026 10:47
…h-cli # Conflicts: # packages/preset-nuxt4/src/features/mastra.ts
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
release.ymlruns on${{ vars.CI_RUNNER || 'ubuntu-latest' }}. GitHub-hosted runners ship the GitHub CLI, but a self-hosted runner image cannot be assumed to. On one without it, the job pushes the annotated tag, then fails atgh release createwithgh: command not found. That leaves a tag without a release, and a rerun refuses because the commit is already tagged.What changed
packages/preset-nuxt4/templates/.github/workflows/release.yml: the oneghcall becomes acurlPOST to${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases, with the same fields:tag_nameandname= the tag,target_commitish= the dispatched commit,generate_release_notes: true. It uses the job'sGITHUB_TOKEN(contents: write, unchanged). Nothing else in the workflow usedgh, so the job now needs onlygitandcurl, on GitHub-hosted and self-hosted runners, in public and private repositories alike.shared:github3.1.0 → 3.1.1.packages/preset-nuxt4/test/github.test.ts: the emittedrelease.ymlruns noghcommand and posts to the releases endpoint.Evidence
packages/preset-nuxt4: 25 files, 228 tests pass.pnpm bump:check origin/main: OK.vX.Y.Ztag and a 40-character sha. Both are restricted character sets, which is whyprintfis enough here.gh release create; with this change, the run is green, the annotated tag points at the dispatched commit, and the release is published bygithub-actions[bot]with generated notes.