fix(ci): push detached HEAD to master using HEAD:master refspec #57

Merged
sarman merged 2 commits from fix/auto-tag-push-master into master 2026-05-31 21:43:19 +00:00
Owner

Summary

  • The changelog job checks out $GITHUB_SHA directly, leaving git in detached HEAD state with no local master branch
  • git push origin master fails: error: src refspec master does not match any
  • Fix: git push origin HEAD:master — explicitly maps current HEAD (detached or not) to the remote master branch

Test plan

  • Merge to master triggers auto-tag → Commit CHANGELOG.md to master step succeeds
  • CHANGELOG.md appears updated on master
## Summary - The `changelog` job checks out `$GITHUB_SHA` directly, leaving git in detached HEAD state with no local `master` branch - `git push origin master` fails: `error: src refspec master does not match any` - Fix: `git push origin HEAD:master` — explicitly maps current HEAD (detached or not) to the remote `master` branch ## Test plan - [ ] Merge to master triggers auto-tag → `Commit CHANGELOG.md to master` step succeeds - [ ] CHANGELOG.md appears updated on master
sarman self-assigned this 2026-05-31 21:16:55 +00:00
sarman added 1 commit 2026-05-31 21:16:56 +00:00
fix(ci): push detached HEAD to master using HEAD:master refspec
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 2m59s
PR Review Automation / review (pull_request) Successful in 6m38s
Test / frontend-typecheck (pull_request) Successful in 1m19s
Test / rust-clippy (pull_request) Successful in 6m18s
Test / frontend-tests (pull_request) Successful in 1m8s
Test / rust-tests (pull_request) Has been cancelled
6dbc40ec96
The changelog job checks out a specific SHA (detached HEAD) then
commits CHANGELOG.md and tries to push with 'git push origin master'.
Since there is no local branch named 'master', git rejects the push
with 'src refspec master does not match any'.

Fix: use 'git push origin HEAD:master' which explicitly maps the
current detached HEAD to the remote master branch regardless of
local branch state.
sarman reviewed 2026-05-31 21:23:31 +00:00
sarman left a comment
Author
Owner

Automated PR Review (qwen3-coder-next via liteLLM):\n\nSummary
The PR attempts to fix CI by pushing a detached HEAD to master using the HEAD:master refspec. However, this introduces a critical flaw: in a detached HEAD state (e.g., after git checkout FETCH_HEAD), HEAD points to a commit SHA rather than a branch, and pushing HEAD:master may successfully update the master branch to that SHA. While technically valid, the workflow does not guarantee that the checkout is of a commit that is actually intended for master—it merely checks out $GITHUB_SHA, which may be a tag commit, a PR merge, or another non-master target. This risks overwriting master with an unintended commit, especially since the changelog job runs unconditionally on any workflow trigger. Additionally, removing the tag validation before git-cliff and changing release creation to only update (no create) breaks idempotent or re-run safety, as missing releases will now fail instead of being created.

Findings

  • [BLOCKER] .gitea/workflows/auto-tag.yml:151 - Using git push origin HEAD:master assumes the current detached HEAD commit is a valid, intended tip of master, but $GITHUB_SHA may be arbitrary (e.g., tag annotation commit, PR branch merge) and not intended for master.
    Evidence: git push origin HEAD:master
    Fix: Resolve the ref to an intended branch tip (e.g., compute master commit hash explicitly or ensure workflow only runs in contexts where $GITHUB_SHA is master), or use git fetch origin master:master && git push origin master to synchronize to the known remote master.

  • [BLOCKER] .gitea/workflows/auto-tag.yml:117–123: Removed validation (git rev-parse "refs/tags/...") and release-creation logic, but now fails if release does not exist. The changelog job assumes the release already exists and only attempts to update its body, yet autotag job tags the repo but does not create a Gitea release. This causes the changelog job to fail on first-run (new tag, no release yet).
    Evidence:
    RELEASE_ID=$(curl -sf "$API/releases/tags/$TAG" ... | jq -r '.id')
    if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then echo "ERROR: Could not find release for tag $TAG"; exit 1; fi
    Fix: Restore release-creation logic or ensure autotag job also creates the Gitea release; do not remove required idempotent creation step.

  • [WARNING] .gitea/workflows/auto-tag.yml:140: Removed redundant || echo "No changes to commit" fallback after git commit, but || echo suppresses exit code and may hide failures. Combined with set -euo pipefail, this is contradictory — if git commit fails (e.g., no staged changes), it will exit 0 due to the ||, but set -e could still trigger on failure before the fallback.
    Evidence: git commit -m "..." || echo "No changes to commit"
    Fix: Use git commit -m "..." || { [ $? -eq 1 ] && echo "No changes to commit" || exit 1; } or remove the fallback and rely on set -e, but prefer explicit handling.

Verdict: REQUEST CHANGES

Automated PR Review (qwen3-coder-next via liteLLM):\n\n**Summary** The PR attempts to fix CI by pushing a detached HEAD to master using the `HEAD:master` refspec. However, this introduces a critical flaw: in a detached HEAD state (e.g., after `git checkout FETCH_HEAD`), `HEAD` points to a commit SHA rather than a branch, and pushing `HEAD:master` may successfully update the `master` branch to that SHA. While technically valid, the workflow does **not guarantee** that the checkout is of a commit that is actually intended for `master`—it merely checks out `$GITHUB_SHA`, which may be a tag commit, a PR merge, or another non-master target. This risks overwriting `master` with an unintended commit, especially since the changelog job runs unconditionally on any workflow trigger. Additionally, removing the tag validation before `git-cliff` and changing release creation to only update (no create) breaks idempotent or re-run safety, as missing releases will now fail instead of being created. **Findings** - [BLOCKER] .gitea/workflows/auto-tag.yml:151 - Using `git push origin HEAD:master` assumes the current detached HEAD commit is a valid, intended tip of `master`, but `$GITHUB_SHA` may be arbitrary (e.g., tag annotation commit, PR branch merge) and not intended for `master`. Evidence: `git push origin HEAD:master` Fix: Resolve the ref to an intended branch tip (e.g., compute master commit hash explicitly or ensure workflow only runs in contexts where `$GITHUB_SHA` is master), or use `git fetch origin master:master && git push origin master` to synchronize to the known remote master. - [BLOCKER] .gitea/workflows/auto-tag.yml:117–123: Removed validation (`git rev-parse "refs/tags/..."`) and release-creation logic, but now fails if release does not exist. The changelog job *assumes* the release already exists and only attempts to update its body, yet autotag job tags the repo but does not create a Gitea release. This causes the changelog job to fail on first-run (new tag, no release yet). Evidence: `RELEASE_ID=$(curl -sf "$API/releases/tags/$TAG" ... | jq -r '.id')` `if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then echo "ERROR: Could not find release for tag $TAG"; exit 1; fi` Fix: Restore release-creation logic *or* ensure autotag job also creates the Gitea release; do not remove required idempotent creation step. - [WARNING] .gitea/workflows/auto-tag.yml:140: Removed redundant `|| echo "No changes to commit"` fallback after `git commit`, but `|| echo` suppresses exit code and may hide failures. Combined with `set -euo pipefail`, this is contradictory — if `git commit` fails (e.g., no staged changes), it will exit 0 due to the `||`, but `set -e` could still trigger on failure before the fallback. Evidence: `git commit -m "..." || echo "No changes to commit"` Fix: Use `git commit -m "..." || { [ $? -eq 1 ] && echo "No changes to commit" || exit 1; }` or remove the fallback and rely on `set -e`, but prefer explicit handling. **Verdict**: REQUEST CHANGES
sarman added 1 commit 2026-05-31 21:26:33 +00:00
fix(ci): consolidate all auto-tag changelog fixes
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m50s
Test / rust-clippy (pull_request) Successful in 3m8s
Test / frontend-typecheck (pull_request) Successful in 1m44s
Test / frontend-tests (pull_request) Successful in 1m27s
PR Review Automation / review (pull_request) Successful in 5m32s
Test / rust-tests (pull_request) Successful in 4m47s
6d8263c5b5
Three issues addressed together:

1. Race condition (was PR #56): changelog job now CREATES the Gitea
   release rather than assuming build jobs have already created it.
   Build jobs continue to use create-or-skip + upload unchanged.

2. Detached HEAD push: 'git push origin master' fails when HEAD is
   detached (no local branch named master). Changed to 'HEAD:master'.

3. git-cliff tag guard: verify tag is present locally before running
   git-cliff, to fail fast with a clear message rather than silently
   generating a wrong changelog.

4. git commit idiom: replaced 'git commit || echo' (swallows all
   non-zero exit codes including real failures) with an explicit
   'git diff --staged --quiet' guard so set -euo pipefail is not
   undermined.
sarman reviewed 2026-05-31 21:31:57 +00:00
sarman left a comment
Author
Owner

Automated PR Review (qwen3-coder-next via liteLLM):\n\nSummary
The PR attempts to fix CI by using git push origin HEAD:master instead of git push origin master to push to the master branch in a detached HEAD state. However, this change introduces a critical correctness issue: HEAD:master pushes the current commit as a branch named master, but since the workflow is operating on a detached FETCH_HEAD or specific SHA (not master), it may push an incorrect or unrelated commit as the master branch. This poses a high risk of corrupting the master branch history.

Findings

  • [BLOCKER] .gitea/workflows/auto-tag.yml:177 - Using git push origin HEAD:master is incorrect in detached HEAD state; it pushes the checked-out commit (e.g., a tag reference or arbitrary SHA) as master, potentially overwriting or corrupting the real master branch history.
    Evidence: git push origin HEAD:master
    Fix: Replace with git push origin <branch>:master, where <branch> is explicitly checked out as a local branch named master. E.g., after checkout, run git branch -f master then git push origin master, or use git fetch origin master:master to update master directly.

Verdict: REQUEST CHANGES

Automated PR Review (qwen3-coder-next via liteLLM):\n\n**Summary** The PR attempts to fix CI by using `git push origin HEAD:master` instead of `git push origin master` to push to the master branch in a detached HEAD state. However, this change introduces a critical correctness issue: `HEAD:master` pushes the current commit as a branch named `master`, but since the workflow is operating on a detached `FETCH_HEAD` or specific SHA (not `master`), it may push an incorrect or unrelated commit as the `master` branch. This poses a high risk of corrupting the `master` branch history. **Findings** - [BLOCKER] .gitea/workflows/auto-tag.yml:177 - Using `git push origin HEAD:master` is incorrect in detached HEAD state; it pushes the checked-out commit (e.g., a tag reference or arbitrary SHA) as `master`, potentially overwriting or corrupting the real `master` branch history. Evidence: `git push origin HEAD:master` Fix: Replace with `git push origin <branch>:master`, where `<branch>` is explicitly checked out as a local branch named `master`. E.g., after checkout, run `git branch -f master` then `git push origin master`, or use `git fetch origin master:master` to update master directly. **Verdict**: REQUEST CHANGES
sarman force-pushed fix/auto-tag-push-master from 6d8263c5b5 to 34a69620f5 2026-05-31 21:38:11 +00:00 Compare
sarman reviewed 2026-05-31 21:42:26 +00:00
sarman left a comment
Author
Owner

Automated PR Review (qwen3-coder-next via liteLLM):\n\nSummary
The change modifies the git push operation in the changelog job to use HEAD:master refspec to correctly push from a detached HEAD state. However, a logic flaw exists in the commit handling: it omits the actual commit creation when changes are staged but not committed, potentially leading to uncommitted CHANGELOG.md changes not being pushed despite the push step executing. Additionally, the git push origin HEAD:master command may push to the correct branch but introduces ambiguity since HEAD points to the commit checkout out ($GITHUB_SHA) rather than the updated working tree.

Findings

  • [WARNING] .gitea/workflows/auto-tag.yml:167 - When git diff --staged --quiet returns true (no staged changes), the script skips the commit but still proceeds to git push origin HEAD:master, which will push the original commit (pre-changelog update) instead of the current state. This contradicts the intended behavior of pushing the updated CHANGELOG.md.
    Evidence:

    if git diff --staged --quiet; then
      echo "No CHANGELOG.md changes to commit"
    else
      git commit -m "chore: update CHANGELOG.md for ${TAG} [skip ci]"
    fi
    git push origin HEAD:master
    

    Fix: Wrap the push in the same condition — only push if a commit was made, or use git diff HEAD~ -- CHANGELOG.md post-commit to verify change before pushing.

  • [WARNING] .gitea/workflows/auto-tag.yml:168 - The use of git push origin HEAD:master in a detached HEAD state is technically valid but unsafe: HEAD refers to the commit checked out ($GITHUB_SHA) before the commit step, and if the commit was skipped (due to no diff), the pushed state is stale.
    Evidence:

    git push origin HEAD:master
    

    Fix: Replace with explicit branch-based push: after committing, ensure local master branch points to the new commit, e.g., by updating a local branch reference (or use git push origin HEAD^{tree}:refs/heads/master only if git commit happened). Alternatively, commit to a named branch first and push that branch.

Verdict: REQUEST CHANGES

Automated PR Review (qwen3-coder-next via liteLLM):\n\n**Summary** The change modifies the git push operation in the `changelog` job to use `HEAD:master` refspec to correctly push from a detached HEAD state. However, a logic flaw exists in the commit handling: it omits the actual commit creation when changes are staged but not committed, potentially leading to uncommitted CHANGELOG.md changes not being pushed despite the push step executing. Additionally, the `git push origin HEAD:master` command may push to the correct branch but introduces ambiguity since `HEAD` points to the commit checkout out (`$GITHUB_SHA`) rather than the updated working tree. **Findings** - [WARNING] .gitea/workflows/auto-tag.yml:167 - When `git diff --staged --quiet` returns true (no staged changes), the script skips the commit but still proceeds to `git push origin HEAD:master`, which will push the *original* commit (pre-changelog update) instead of the current state. This contradicts the intended behavior of pushing the updated CHANGELOG.md. Evidence: ```yaml if git diff --staged --quiet; then echo "No CHANGELOG.md changes to commit" else git commit -m "chore: update CHANGELOG.md for ${TAG} [skip ci]" fi git push origin HEAD:master ``` Fix: Wrap the push in the same condition — only push if a commit was made, or use `git diff HEAD~ -- CHANGELOG.md` post-commit to verify change before pushing. - [WARNING] .gitea/workflows/auto-tag.yml:168 - The use of `git push origin HEAD:master` in a detached HEAD state is technically valid but unsafe: `HEAD` refers to the commit checked out (`$GITHUB_SHA`) *before* the commit step, and if the commit was skipped (due to no diff), the pushed state is stale. Evidence: ```yaml git push origin HEAD:master ``` Fix: Replace with explicit branch-based push: after committing, ensure local `master` branch points to the new commit, e.g., by updating a local branch reference (or use `git push origin HEAD^{tree}:refs/heads/master` only if `git commit` happened). Alternatively, commit to a named branch first and push that branch. **Verdict**: REQUEST CHANGES
sarman merged commit 3fe06ce498 into master 2026-05-31 21:43:19 +00:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sarman/tftsr-devops_investigation#57
No description provided.