Closes #872 Mos (id-11) Gate-16 merge: independent review APPROVE @23cbdaf8, author jason.woltje(id2) != approver Mos(id11), CI green wp1974. Co-authored-by: jason.woltje <jason@diversecanvas.com> Co-committed-by: jason.woltje <jason@diversecanvas.com>
154 lines
4.9 KiB
Bash
154 lines
4.9 KiB
Bash
#!/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/<branch> 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/<branch> vs commits/<sha>/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"
|