fix(branch_archive): stop checkout's persisted credential hijacking the push - #284
Merged
Conversation
…he push The first real dispatch failed at the archive step: remote: Permission to PyAutoLabs/PyAutoGut.git denied to github-actions[bot]. fatal: ... The requested URL returned error: 403 Note the identity: github-actions[bot], not the PAT. `actions/checkout` defaults to persist-credentials: true, which writes an `http.https://github.com/.extraheader` auth header into the checkout's local config — and that header takes precedence over credentials embedded in a remote URL. So `git remote set-url origin "https://x-access-token:$PAT@..."` was silently overridden, and the push went out as the workflow identity, which has no access to a sibling repo. Two changes: - persist-credentials: false on the Gut checkout, so nothing is inherited and the PAT in the remote URL is what authenticates. - A check immediately before the push that the clone carries no extraheader at all. The failure mode is silent by nature — the wrong credential still produces a plausible-looking push attempt — so this asserts the identity rather than assuming it. The dry run is why this cost nothing. It was dispatched with delete_after false precisely so the first exercise of an irreversible path could fail safely, and the ordering held: `set -e` aborted at the archive, far from the delete. A first run with deletion enabled would have been fine too — the archive failing means no delete — but only by the design working, not by having tested it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwqicJpMqmcT5RVbyNwdKq
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.
What failed
The first real dispatch of
branch_archive.yml(run 32884038271) reached the archive step and stopped:Note the identity:
github-actions[bot], not the PAT.actions/checkoutdefaults topersist-credentials: true, which writes anhttp.https://github.com/.extraheaderauth header into the checkout's local config — and that header takes precedence over credentials embedded in a remote URL. So this line was silently overridden:git remote set-url origin "https://x-access-token:${PAT}@github.com/${owner}/PyAutoGut.git"and the push went out as the workflow identity, which has no access to a sibling repo.
Fix
persist-credentials: falseon the Gut checkout, so nothing is inherited and the PAT in the remote URL is what authenticates.The dry run is why this cost nothing
It was dispatched with
delete_after: falseprecisely so the first exercise of an irreversible path could fail safely, and the ordering held:set -eaborted at the archive, far from the delete.A first run with deletion enabled would also have been fine — a failed archive means no delete — but only because the design works, not because anyone had watched it work. Those are different things, and the difference is worth one run.
Checks
pytest tests/→ 510 passed ·repos_sync.py --check→ all 12 green.🤖 Generated with Claude Code
https://claude.ai/code/session_01KwqicJpMqmcT5RVbyNwdKq
Generated by Claude Code