ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: code-be-01 <[email protected]>
324 lines
12 KiB
Bash
Executable File
324 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Regression harness for ci-queue-wait.sh's --no-ci-expected assertion:
|
|
# the sanctioned merge path for a repository with no CI configured at all.
|
|
#
|
|
# Zero status contexts ("no-status") stays fail-closed for --purpose merge
|
|
# by default, because at merge time no-status can also mean "CI has not
|
|
# reported yet". --no-ci-expected reclassifies ONLY that zero-context case
|
|
# as queue-clear, and only for a caller whose acting token holds repository
|
|
# admin. This harness pins:
|
|
# (a) merge + no-status + flag + admin -> exit 0, audit line + JSONL.
|
|
# (b) merge + no-status, no flag -> exit 3, existing text (unchanged).
|
|
# (c) merge + no-status + flag + non-admin -> exit 77 ASSERTION_REFUSED
|
|
# (distinct text, exit code NOT 3) + JSONL refusal record.
|
|
# (c2) flag + admin payload without the admin field -> fail closed as (c).
|
|
# (d) flag + --require-status -> usage error, before any network.
|
|
# (e) flag + a real pending context -> still holds (timeout 124),
|
|
# and the admin endpoint is never consulted.
|
|
# (f) push + no-status, with and without the flag -> push queue-clear
|
|
# unchanged; no admin consultation on push.
|
|
# (g) flag + admin lookup unreachable -> CANNOT_ASSERT hold (75),
|
|
# not a silent pass and not a refusal.
|
|
# (h) flag + admin stub + NO MOSAIC_GIT_IDENTITY -> refusal BEFORE
|
|
# queue-clear and BEFORE the admin lookup: exit 78, no queue-clear
|
|
# line, an ASSERTION_UNATTRIBUTABLE JSONL record, no repos/ call.
|
|
|
|
set -u
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
WORK_DIR="${MOSAIC_TEST_WORK_DIR:-$PWD/.mosaic-test-work/ci-queue-wait-no-ci-expected}"
|
|
REPO_DIR="$WORK_DIR/repo"
|
|
STUB_DIR="$WORK_DIR/stubs"
|
|
URL_LOG="$WORK_DIR/urls.log"
|
|
|
|
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
|
|
|
|
# Same stub conventions as test-ci-queue-wait-no-status.sh; adds the
|
|
# repository-object endpoint (admin state) selected by MOSAIC_STUB_ADMIN_MODE.
|
|
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
|
|
printf '%s\n' "$url" >> "${MOSAIC_STUB_URL_LOG:?}"
|
|
|
|
case "$url" in
|
|
*/branches/*)
|
|
body='{"commit":{"id":"deadbeefcafef00d0123456789abcdef01234567"}}'
|
|
if [[ "$has_w" == 1 ]]; then
|
|
printf '%s\n200' "$body"
|
|
else
|
|
printf '%s' "$body"
|
|
fi
|
|
exit 0
|
|
;;
|
|
*/status)
|
|
mode="${MOSAIC_STUB_STATUS_MODE:?MOSAIC_STUB_STATUS_MODE not set}"
|
|
case "$mode" in
|
|
no-status) body='{"state":"","statuses":[]}' ;;
|
|
real-pending) body='{"state":"pending","statuses":[{"context":"ci/woodpecker","status":"running","target_url":""}]}' ;;
|
|
*) echo "curl stub: unknown status mode=$mode" >&2; exit 2 ;;
|
|
esac
|
|
printf '%s' "$body"
|
|
exit 0
|
|
;;
|
|
*/repos/*)
|
|
mode="${MOSAIC_STUB_ADMIN_MODE:?MOSAIC_STUB_ADMIN_MODE not set}"
|
|
case "$mode" in
|
|
admin) body='{"permissions":{"admin":true,"push":true,"pull":true}}' ;;
|
|
non-admin) body='{"permissions":{"admin":false,"push":true,"pull":true}}' ;;
|
|
no-admin-field) body='{"permissions":{}}' ;;
|
|
unreachable) exit 7 ;;
|
|
*) echo "curl stub: unknown admin mode=$mode" >&2; exit 2 ;;
|
|
esac
|
|
if [[ "$has_w" == 1 ]]; then
|
|
printf '%s\n200' "$body"
|
|
else
|
|
printf '%s' "$body"
|
|
fi
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "curl stub: unrecognized URL: $url" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
SH
|
|
chmod +x "$STUB_DIR/curl"
|
|
|
|
failures=0
|
|
|
|
run_guard() {
|
|
local name="$1"; shift
|
|
(
|
|
cd "$REPO_DIR" || exit
|
|
export PATH="$STUB_DIR:$PATH"
|
|
export MOSAIC_CREDENTIALS_FILE="$WORK_DIR/no-credentials.json"
|
|
export MOSAIC_CI_QUEUE_AUDIT_LOG="$WORK_DIR/audit-$name.jsonl"
|
|
export MOSAIC_STUB_URL_LOG="$URL_LOG"
|
|
export GITEA_TOKEN="stub-token"
|
|
export GITEA_URL="https://git.example.test"
|
|
export MOSAIC_GIT_IDENTITY="test-identity"
|
|
"$SCRIPT_DIR/ci-queue-wait.sh" -B main -t 3 -i 1 "$@"
|
|
)
|
|
}
|
|
|
|
# The suite exports test-identity globally, so the unattributable-caller
|
|
# case must strip it from the child environment at invocation with env -u,
|
|
# not rely on the export order.
|
|
run_guard_no_identity() {
|
|
local name="$1"; shift
|
|
(
|
|
cd "$REPO_DIR" || exit
|
|
export PATH="$STUB_DIR:$PATH"
|
|
export MOSAIC_CREDENTIALS_FILE="$WORK_DIR/no-credentials.json"
|
|
export MOSAIC_CI_QUEUE_AUDIT_LOG="$WORK_DIR/audit-$name.jsonl"
|
|
export MOSAIC_STUB_URL_LOG="$URL_LOG"
|
|
export GITEA_TOKEN="stub-token"
|
|
export GITEA_URL="https://git.example.test"
|
|
export MOSAIC_GIT_IDENTITY="test-identity"
|
|
env -u MOSAIC_GIT_IDENTITY \
|
|
"$SCRIPT_DIR/ci-queue-wait.sh" -B main -t 3 -i 1 "$@"
|
|
)
|
|
}
|
|
|
|
expect_rc() {
|
|
local name="$1" want="$2" got="$3"
|
|
if [[ "$want" == "not3" ]]; then
|
|
if [[ "$got" -eq 0 || "$got" -eq 3 ]]; then
|
|
echo "FAIL $name: expected a refusal rc (nonzero, not 3), got $got" >&2
|
|
failures=$((failures + 1))
|
|
return 1
|
|
fi
|
|
elif [[ "$got" -ne "$want" ]]; then
|
|
echo "FAIL $name: expected rc=$want, got rc=$got" >&2
|
|
failures=$((failures + 1))
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
expect_text() {
|
|
local name="$1" want="$2" output="$3" polarity="${4:-present}"
|
|
if [[ "$polarity" == "present" && "$output" != *"$want"* ]]; then
|
|
echo "FAIL $name: output missing '$want'" >&2
|
|
printf '%s\n' "$output" >&2
|
|
failures=$((failures + 1))
|
|
elif [[ "$polarity" == "absent" && "$output" == *"$want"* ]]; then
|
|
echo "FAIL $name: output unexpectedly contains '$want'" >&2
|
|
printf '%s\n' "$output" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
}
|
|
|
|
repo_root_fetched() {
|
|
grep -q 'repos/acme/widgets$' "$URL_LOG"
|
|
}
|
|
|
|
# (a) merge + no-status + flag + admin -> exit 0, assertion line, JSONL record.
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_a=$(MOSAIC_STUB_STATUS_MODE=no-status MOSAIC_STUB_ADMIN_MODE=admin run_guard a --purpose merge --no-ci-expected 2>&1)
|
|
rc_a=$?
|
|
set -u
|
|
if expect_rc a 0 "$rc_a"; then
|
|
expect_text a "queue-clear state=no-status purpose=merge asserted-by=test-identity reason=no-ci-expected branch=main" "$out_a"
|
|
expect_text a "ASSERTED_NOT_READY" "$out_a" absent
|
|
if ! grep -q '"outcome":"NO_CI_ASSERTED"' "$WORK_DIR/audit-a.jsonl" 2>/dev/null; then
|
|
echo "FAIL a: expected a NO_CI_ASSERTED JSONL audit record" >&2
|
|
failures=$((failures + 1))
|
|
elif ! grep -q '"asserted_by":"test-identity"' "$WORK_DIR/audit-a.jsonl"; then
|
|
echo "FAIL a: audit record does not name the asserting identity" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
fi
|
|
|
|
# (b) merge + no-status, no flag -> exit 3, existing error text unchanged.
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_b=$(MOSAIC_STUB_STATUS_MODE=no-status run_guard b --purpose merge 2>&1)
|
|
rc_b=$?
|
|
set -u
|
|
if expect_rc b 3 "$rc_b"; then
|
|
expect_text b "Error: ASSERTED_NOT_READY state=no-status purpose=merge branch=main." "$out_b"
|
|
expect_text b "asserted-by" "$out_b" absent
|
|
fi
|
|
if repo_root_fetched; then
|
|
echo "FAIL b: admin endpoint consulted without the flag" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
|
|
# (c) merge + no-status + flag + non-admin -> distinct refusal, rc NOT 3.
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_c=$(MOSAIC_STUB_STATUS_MODE=no-status MOSAIC_STUB_ADMIN_MODE=non-admin run_guard c --purpose merge --no-ci-expected 2>&1)
|
|
rc_c=$?
|
|
set -u
|
|
if expect_rc c not3 "$rc_c"; then
|
|
if [[ "$rc_c" -ne 77 ]]; then
|
|
echo "FAIL c: expected the documented refusal rc=77, got $rc_c" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
expect_text c "ASSERTION_REFUSED state=no-status purpose=merge asserted-by=test-identity reason=no-ci-expected branch=main" "$out_c"
|
|
expect_text c "ASSERTED_NOT_READY" "$out_c" absent
|
|
if ! grep -q '"outcome":"ASSERTION_REFUSED"' "$WORK_DIR/audit-c.jsonl" 2>/dev/null; then
|
|
echo "FAIL c: expected an ASSERTION_REFUSED JSONL audit record" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
fi
|
|
|
|
# (c2) admin payload with no admin field -> fail closed as non-admin.
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_c2=$(MOSAIC_STUB_STATUS_MODE=no-status MOSAIC_STUB_ADMIN_MODE=no-admin-field run_guard c2 --purpose merge --no-ci-expected 2>&1)
|
|
rc_c2=$?
|
|
set -u
|
|
if expect_rc c2 77 "$rc_c2"; then
|
|
expect_text c2 "ASSERTION_REFUSED" "$out_c2"
|
|
fi
|
|
|
|
# (d) flag + --require-status -> usage error before any network I/O.
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_d=$(MOSAIC_STUB_STATUS_MODE=no-status MOSAIC_STUB_ADMIN_MODE=admin run_guard d --purpose merge --no-ci-expected --require-status 2>&1)
|
|
rc_d=$?
|
|
set -u
|
|
if expect_rc d 1 "$rc_d"; then
|
|
expect_text d "--no-ci-expected and --require-status contradict" "$out_d"
|
|
fi
|
|
if [[ -s "$URL_LOG" ]]; then
|
|
echo "FAIL d: usage error must precede every network call" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
|
|
# (e) flag + a real pending context -> still holds; admin endpoint never asked.
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_e=$(MOSAIC_STUB_STATUS_MODE=real-pending MOSAIC_STUB_ADMIN_MODE=admin run_guard e --purpose merge --no-ci-expected 2>&1)
|
|
rc_e=$?
|
|
set -u
|
|
if expect_rc e 124 "$rc_e"; then
|
|
expect_text e "ASSERTED_NOT_READY" "$out_e"
|
|
expect_text e "ci/woodpecker=running" "$out_e"
|
|
fi
|
|
if repo_root_fetched; then
|
|
echo "FAIL e: a pending context must not trigger the admin assertion" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
|
|
# (f) push + no-status stays queue-clear, with and without the flag.
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_f=$(MOSAIC_STUB_STATUS_MODE=no-status MOSAIC_STUB_ADMIN_MODE=non-admin run_guard f --purpose push 2>&1)
|
|
rc_f=$?
|
|
set -u
|
|
if expect_rc f 0 "$rc_f"; then
|
|
expect_text f "queue-clear state=no-status purpose=push branch=main; no queued or running CI." "$out_f"
|
|
fi
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_f2=$(MOSAIC_STUB_STATUS_MODE=no-status MOSAIC_STUB_ADMIN_MODE=non-admin run_guard f2 --purpose push --no-ci-expected 2>&1)
|
|
rc_f2=$?
|
|
set -u
|
|
if expect_rc f2 0 "$rc_f2"; then
|
|
expect_text f2 "queue-clear state=no-status purpose=push branch=main; no queued or running CI." "$out_f2"
|
|
expect_text f2 "asserted-by" "$out_f2" absent
|
|
fi
|
|
if repo_root_fetched; then
|
|
echo "FAIL f: push must not consult the admin endpoint" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
|
|
# (g) flag + admin lookup unreachable -> CANNOT_ASSERT hold (75), not a pass.
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_g=$(MOSAIC_STUB_STATUS_MODE=no-status MOSAIC_STUB_ADMIN_MODE=unreachable run_guard g --purpose merge --no-ci-expected 2>&1)
|
|
rc_g=$?
|
|
set -u
|
|
if expect_rc g 75 "$rc_g"; then
|
|
expect_text g "CANNOT_ASSERT reason=repo-permissions-unavailable" "$out_g"
|
|
fi
|
|
if ! grep -q '"outcome":"CANNOT_ASSERT"' "$WORK_DIR/audit-g.jsonl" 2>/dev/null; then
|
|
echo "FAIL g: expected a CANNOT_ASSERT JSONL audit record" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
|
|
# (h) flag + admin stub + no asserting identity -> refusal before queue-clear
|
|
# and before the admin lookup: rc 78, no queue-clear line, an
|
|
# ASSERTION_UNATTRIBUTABLE JSONL record, and zero repos/ network calls.
|
|
: > "$URL_LOG"
|
|
set +e
|
|
out_h=$(MOSAIC_STUB_STATUS_MODE=no-status MOSAIC_STUB_ADMIN_MODE=admin run_guard_no_identity h --purpose merge --no-ci-expected 2>&1)
|
|
rc_h=$?
|
|
set -u
|
|
if expect_rc h 78 "$rc_h"; then
|
|
expect_text h "ASSERTION_UNATTRIBUTABLE state=no-status purpose=merge asserted-by=unknown reason=no-ci-expected branch=main" "$out_h"
|
|
expect_text h "queue-clear" "$out_h" absent
|
|
if ! grep -q '"outcome":"ASSERTION_UNATTRIBUTABLE"' "$WORK_DIR/audit-h.jsonl" 2>/dev/null; then
|
|
echo "FAIL h: expected an ASSERTION_UNATTRIBUTABLE JSONL audit record" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
fi
|
|
if repo_root_fetched; then
|
|
echo "FAIL h: an unattributable caller must not trigger the permission lookup" >&2
|
|
failures=$((failures + 1))
|
|
fi
|
|
|
|
if [[ "$failures" -ne 0 ]]; then
|
|
echo "ci-queue-wait no-ci-expected regression failed ($failures assertions)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "ci-queue-wait no-ci-expected regression passed (all outcome classes)"
|