fix(tag-release): push the tag with git instead of gh --target - #193
Conversation
`gh release create --target <sha>` returns HTTP 403 "Resource not accessible by integration" (or "...by personal access token") for GitHub Actions tokens and fine-grained PATs even when contents: write is granted — cli/cli#9514. The same command succeeds under personal auth, which is why this only showed up once the release moved into a workflow: 1.0.49 through 1.0.51 were tagged from the owner's machine. Create and push the tag with git, then create the release against the tag that now exists, with no --target. Plain git push is not affected, and the result is identical: an annotated ref at the verified sha with a release attached. Re-running after a partial failure is now handled explicitly. The tag lands before the release, so a failure between the two used to leave a state the old "tag already exists" check would refuse forever. A tag at the SAME sha with no release is now recognized as resumable; a tag at a different sha is still a hard stop.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.
Reviewed by Cursor Bugbot for commit 5f5cc28. Configure here.
| if ($taggedSha -ne $Sha) { | ||
| Write-Error "Tag $Version already exists and points at $taggedSha, not $Sha. Bump the version or delete the stale tag first." | ||
| exit 1 | ||
| } |
There was a problem hiding this comment.
Resume rejects equivalent commit SHAs
Medium Severity
The new resume check compares the existing tag's commit from git rev-list to -Sha as raw strings. git rev-list always prints a full hash, so an abbreviated -Sha that every earlier git check already accepted looks like a different commit and aborts the resume.
Reviewed by Cursor Bugbot for commit 5f5cc28. Configure here.
| if ($LASTEXITCODE -ne 0) { Write-Error "Could not create the tag $Version locally."; exit 1 } | ||
| git push origin "refs/tags/$Version" | ||
| if ($LASTEXITCODE -ne 0) { Write-Error "Could not push the tag $Version. The local tag remains; delete it with ``git tag -d $Version`` if you are not retrying."; exit 1 } | ||
| } |
There was a problem hiding this comment.
Retry skips pushing a local-only tag
Medium Severity
When a local tag already exists at -Sha, the script skips git push and treats that tag as already published. A leftover local tag after a failed push is not on origin, so gh release create without --target has no remote tag to attach to.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 5f5cc28. Configure here.


Root cause of the three failed
tag.ymlruns, and it isn't this repo's configuration.cli/cli#9514:
gh release create <tag> --target <sha>returns HTTP 403 for GitHub Actions tokens and fine-grained PATs even withcontents: writeorwrite-all, while the identical command succeeds under personal auth. Dropping--targetmakes it work.Every piece of evidence lines up:
GITHUB_TOKENrefused: "not accessible by integration"Contents: writegrantedIt stayed hidden until now because 1.0.49–1.0.51 were all tagged by hand. The bug is only reachable by a token, and no token had ever cut a tag here before this week.
The fix
Create and push the tag with
git, then create the release against the tag that now exists — no--target. Plaingit pushof a tag ref isn't affected by the bug. The end state is identical.Resumability, which the new order made necessary
The tag now lands before the release, so a failure between the two leaves a pushed tag with nothing attached — and the old "tag already exists" check would have refused that state forever. Now:
1.0.52
Already tagged and released from Steven's machine at 14:51, and live on Play. This changes nothing about it — it's for 1.0.53 onward. Both final checks pass:
openloop-1.0.52-52.aabwas confirmed present andjar verifiedduring the tag run, and the release resolves at1.0.52.🤖 Generated with Claude Code
https://claude.ai/code/session_01Miqsf1M14nY5TKiZHzyjNY
Note
Low Risk
Release automation script only; behavior is more resilient for CI tokens and idempotent re-runs after partial failure.
Overview
Fixes failed automated release tagging in CI by stopping use of
gh release create --target <sha>, which returns HTTP 403 for GitHub Actions and fine-grained PATs despitecontents: write(cli/cli#9514).The script now creates and pushes the version tag with
git, then runsgh release createagainst that tag (no--target). Docs in the script header explain why.Because the tag is pushed before the GitHub release, a partial failure can leave a tag with no release. The “tag already exists” logic is updated: same SHA and no release → resume and create the release; same SHA with release → exit; different SHA → still a hard error.
gh release createfailures now tell you the tag is already on the remote and to re-run the script.Reviewed by Cursor Bugbot for commit 5f5cc28. Bugbot is set up for automated code reviews on this repo. Configure here.