fix(tools/git): ci-queue-wait.sh treats 404 branch-absent as queue-clear

gitea_get_branch_head_sha() looked up a branch's head SHA via
`curl -fsSL .../branches/<branch>`. For a branch not yet pushed to the
remote, Gitea returns 404, curl -f fails, stdin is empty, and the
downstream `json.load` raises JSONDecodeError -- crashing the guard.
Since ci-queue-wait.sh is a mandatory pre-push check, every new feature
branch's first push was blocked.

Capture the HTTP status via `curl -sS -w '\n%{http_code}'`:
- 404  -> echo __BRANCH_ABSENT__, return 0 (no in-flight pipeline on a
          branch that doesn't exist yet -- queue is clear).
- non-200 -> return 1 (still fail-closed on a genuine API error).
- 200  -> parse the JSON as before (existing-branch behavior unchanged).

The caller checks for the __BRANCH_ABSENT__ sentinel and exits 0 with a
"branch not yet on remote -- queue clear" message.

ci-queue-wait.ps1 had the same bug (Invoke-RestMethod throws on any
non-2xx, including 404, and the catch block exited 1) -- ported the
equivalent fix there via the caught exception's HTTP status code.

Adds a red-first regression harness (test-ci-queue-wait-branch-absent.sh)
covering: 404 branch-absent -> queue clear; 200 existing branch with a
terminal CI state -> unchanged behavior; 500 genuine API error -> still
fail-closed. Verified failing against the unpatched script (crashes with
JSONDecodeError) and passing after the fix. Wired into
package.json's test:framework-shell alongside the existing git-wrapper
regression tests.

Upstreams Mos host-local tooling-patch kit (2026-07-23), Patch 3.
This commit is contained in:
ms-lead-reviewer
2026-07-23 11:36:10 -05:00
parent b79336a8c1
commit cd67042184
4 changed files with 183 additions and 2 deletions

View File

@@ -137,7 +137,21 @@ gitea_get_branch_head_sha() {
local branch="$3"
local token="$4"
local url="https://${host}/api/v1/repos/${repo}/branches/${branch}"
curl -fsSL -H "User-Agent: curl/8" -H "Authorization: token ${token}" "$url" | python3 -c '
# Capture HTTP status so an absent branch (404) is distinguished from an API
# error. A not-yet-pushed feature branch has no in-flight pipeline, so the
# pre-push queue guard must treat 404 as "queue clear", not crash.
local resp code body
resp=$(curl -sS -H "User-Agent: curl/8" -H "Authorization: token ${token}" -w $'\n%{http_code}' "$url")
code="${resp##*$'\n'}"
body="${resp%$'\n'*}"
if [[ "$code" == "404" ]]; then
echo "__BRANCH_ABSENT__"
return 0
fi
if [[ "$code" != "200" ]]; then
return 1
fi
printf '%s' "$body" | python3 -c '
import json, sys
data = json.load(sys.stdin)
commit = data.get("commit") or {}
@@ -219,6 +233,10 @@ elif [[ "$PLATFORM" == "gitea" ]]; then
exit 1
}
HEAD_SHA=$(gitea_get_branch_head_sha "$HOST" "$OWNER/$REPO" "$BRANCH" "$TOKEN")
if [[ "$HEAD_SHA" == "__BRANCH_ABSENT__" ]]; then
echo "[ci-queue-wait] branch ${BRANCH} not yet on remote — no in-flight pipeline; queue clear."
exit 0
fi
if [[ -z "$HEAD_SHA" ]]; then
echo "Error: Could not resolve ${BRANCH} head SHA." >&2
exit 1