#!/usr/bin/env bash # Regression harness for ci-queue-wait.sh's 404-branch-absent handling. # # gitea_get_branch_head_sha() resolves a branch's head SHA before the # pre-push queue guard runs. A branch that has never been pushed doesn't # exist on the remote yet, so Gitea's branches/ endpoint 404s. # Before the fix, `curl -fsSL` failed on the 404, its empty stdout was piped # into `python3 -c 'json.load(sys.stdin)'`, and the resulting # JSONDecodeError crashed the guard -- blocking every new feature branch's # first push. The fix must treat 404 as "no in-flight pipeline" (queue # clear) while still failing closed on a genuine API error. # # Covers: # (a) 404 branch-absent -> exit 0, "queue clear" message. # (b) 200 existing branch + a terminal CI state -> unchanged behavior. # (c) genuine API error (500) -> still fail-closed (nonzero exit). set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" WORK_DIR="${MOSAIC_TEST_WORK_DIR:-$PWD/.mosaic-test-work/ci-queue-wait-branch-absent}" REPO_DIR="$WORK_DIR/repo" STUB_DIR="$WORK_DIR/stubs" rm -rf "$WORK_DIR" mkdir -p "$REPO_DIR" "$STUB_DIR" git -C "$REPO_DIR" init -q git -C "$REPO_DIR" remote add origin https://git.example.test/acme/widgets.git # Minimal curl stub. Selects a canned response by inspecting which Gitea # endpoint is being hit (branches/ vs commits//status) and # whether -w '%{http_code}' was requested. Only the patched branch-lookup # call passes -w; the unpatched call and the (unchanged) status call both # use plain `curl -fsSL` semantics -- exit nonzero and print nothing on a # non-2xx response. This lets the same stub exercise both the pre-fix and # post-fix branch-lookup code paths faithfully. cat > "$STUB_DIR/curl" <<'SH' #!/usr/bin/env bash set -euo pipefail has_w=0 url="" for arg in "$@"; do case "$arg" in -w) has_w=1 ;; http://*|https://*) url="$arg" ;; esac done case "$url" in */branches/*) mode="${MOSAIC_STUB_BRANCH_MODE:?MOSAIC_STUB_BRANCH_MODE not set}" ;; */status) mode="${MOSAIC_STUB_STATUS_MODE:-terminal-success}" ;; *) echo "curl stub: unrecognized URL: $url" >&2 exit 2 ;; esac case "$mode" in 404) code=404; body="" ;; 200) code=200; body='{"commit":{"id":"deadbeefcafef00d0123456789abcdef01234567"}}' ;; 500) code=500; body='{"message":"internal server error"}' ;; no-status) code=200; body='{}' ;; terminal-success) code=200; body='{"state":"success"}' ;; *) echo "curl stub: unknown mode=$mode" >&2 exit 2 ;; esac if [[ "$has_w" == 1 ]]; then printf '%s\n%s' "$body" "$code" exit 0 fi # Unpatched branch-lookup call / status-endpoint call: real curl -fsSL # exits nonzero and emits nothing on stdout for a non-2xx response. if [[ "$code" != "200" ]]; then exit 22 fi printf '%s' "$body" SH chmod +x "$STUB_DIR/curl" run_ci_queue_wait() { local branch="$1" ( cd "$REPO_DIR" export PATH="$STUB_DIR:$PATH" export MOSAIC_CREDENTIALS_FILE="$WORK_DIR/no-credentials.json" export GITEA_TOKEN="stub-token" export GITEA_URL="https://git.example.test" "$SCRIPT_DIR/ci-queue-wait.sh" -B "$branch" --purpose push -t 5 -i 1 ) } fail=0 # (a) 404 branch-absent -> queue clear, exit 0. set +e out_a=$(MOSAIC_STUB_BRANCH_MODE=404 run_ci_queue_wait "feat/not-pushed-yet" 2>&1) status_a=$? set -e if [[ "$status_a" -ne 0 ]]; then echo "FAIL(a): expected exit 0 for 404 branch-absent, got $status_a" >&2 echo "$out_a" >&2 fail=1 elif [[ "$out_a" != *"queue clear"* ]]; then echo "FAIL(a): expected a queue-clear message, got:" >&2 echo "$out_a" >&2 fail=1 fi # (b) 200 existing branch + terminal CI state -> unchanged behavior, exit 0. set +e out_b=$(MOSAIC_STUB_BRANCH_MODE=200 MOSAIC_STUB_STATUS_MODE=terminal-success run_ci_queue_wait "main" 2>&1) status_b=$? set -e if [[ "$status_b" -ne 0 ]]; then echo "FAIL(b): expected exit 0 for existing branch with terminal status, got $status_b" >&2 echo "$out_b" >&2 fail=1 elif [[ "$out_b" != *"sha=deadbeefcafef00d0123456789abcdef01234567"* ]]; then echo "FAIL(b): expected the resolved HEAD SHA to be logged, got:" >&2 echo "$out_b" >&2 fail=1 elif [[ "$out_b" == *"queue clear"* ]]; then echo "FAIL(b): an existing branch must not take the branch-absent path" >&2 echo "$out_b" >&2 fail=1 fi # (c) genuine API error (500) -> still fail-closed, exit nonzero. set +e out_c=$(MOSAIC_STUB_BRANCH_MODE=500 run_ci_queue_wait "feat/some-branch" 2>&1) status_c=$? set -e if [[ "$status_c" -eq 0 ]]; then echo "FAIL(c): expected a nonzero exit for a genuine 500 API error, got 0" >&2 echo "$out_c" >&2 fail=1 elif [[ "$out_c" == *"queue clear"* ]]; then echo "FAIL(c): a genuine API error must not be reported as queue-clear" >&2 echo "$out_c" >&2 fail=1 fi if [[ "$fail" -eq 0 ]]; then echo "ci-queue-wait branch-absent regression passed (3/3 cases)" fi exit "$fail"