Files
stack/tools/verify-greenfield-case-coverage.test.sh
T
be-coder-05 f33bd0da96
ci/woodpecker/pr/ci Pipeline was canceled
ci/woodpecker/pr/greenfield-install Pipeline was canceled
ci(installer): enforce greenfield case coverage
2026-08-06 02:52:14 -05:00

127 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SUBJECT="$ROOT/tools/verify-greenfield-case-coverage.sh"
WORKFLOW="$ROOT/.woodpecker/greenfield-install.yml"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
manifest="$TMP/expected-red.tsv"
state_root="$TMP/state"
run_id="pipeline-1"
printf '%s\n' \
'# representative manifest comment' \
$'# case\tkind\tkey/value' \
'' \
$'next-git-present\texit\t1' \
$'main-git-present\texit\t1' \
$'next-git-absent\texit\t1' > "$manifest"
bash "$SUBJECT" init "$manifest" "$state_root" "$run_id"
# Positive firing control: a skipped expected arm makes the final gate red.
bash "$SUBJECT" mark "$manifest" "$state_root" "$run_id" next-git-present
bash "$SUBJECT" mark "$manifest" "$state_root" "$run_id" main-git-present
set +e
skipped_output="$(bash "$SUBJECT" check "$manifest" "$state_root" "$run_id" 2>&1)"
skipped_status=$?
set -e
[[ "$skipped_status" -eq 1 ]]
grep -qF '[fixture-suite] cases_defined=3 cases_executed=2' <<<"$skipped_output"
grep -qF '[fixture-suite] missing_case=next-git-absent' <<<"$skipped_output"
# Count inflation cannot pass: equal counts with one missing and one unexpected remain red.
: > "$state_root/$run_id/unexpected-case.ran"
set +e
inflated_output="$(bash "$SUBJECT" check "$manifest" "$state_root" "$run_id" 2>&1)"
inflated_status=$?
set -e
[[ "$inflated_status" -eq 1 ]]
grep -qF '[fixture-suite] cases_defined=3 cases_executed=3' <<<"$inflated_output"
grep -qF '[fixture-suite] missing_case=next-git-absent' <<<"$inflated_output"
grep -qF '[fixture-suite] unexpected_case=unexpected-case' <<<"$inflated_output"
# Re-initializing the same run clears stale markers instead of certifying a later run.
bash "$SUBJECT" init "$manifest" "$state_root" "$run_id"
set +e
stale_output="$(bash "$SUBJECT" check "$manifest" "$state_root" "$run_id" 2>&1)"
stale_status=$?
set -e
[[ "$stale_status" -eq 1 ]]
grep -qF '[fixture-suite] cases_defined=3 cases_executed=0' <<<"$stale_output"
# Exact set equality is the sole green disposition.
for case_name in next-git-present main-git-present next-git-absent; do
bash "$SUBJECT" mark "$manifest" "$state_root" "$run_id" "$case_name"
done
complete_output="$(bash "$SUBJECT" check "$manifest" "$state_root" "$run_id")"
grep -qF '[fixture-suite] cases_defined=3 cases_executed=3' <<<"$complete_output"
# The repository's production manifest, including its comments, initializes and checks.
production_manifest="$ROOT/tools/fixtures/greenfield-expected-red.tsv"
production_state="$TMP/production-state"
bash "$SUBJECT" init "$production_manifest" "$production_state" production-1
for case_name in next-git-present main-git-present next-git-absent; do
bash "$SUBJECT" mark "$production_manifest" "$production_state" production-1 "$case_name"
done
production_output="$(bash "$SUBJECT" check "$production_manifest" "$production_state" production-1)"
grep -qF '[fixture-suite] cases_defined=3 cases_executed=3' <<<"$production_output"
# A future manifest case changes the derived set and cannot silently escape coverage.
printf '%s\n' $'future-case\texit\t1' >> "$manifest"
set +e
future_output="$(bash "$SUBJECT" check "$manifest" "$state_root" "$run_id" 2>&1)"
future_status=$?
set -e
[[ "$future_status" -eq 1 ]]
grep -qF '[fixture-suite] cases_defined=4 cases_executed=3' <<<"$future_output"
grep -qF '[fixture-suite] missing_case=future-case' <<<"$future_output"
# The workflow writes each marker only after that case's per-case verifier succeeds,
# and the final check is eligible after either success or failure.
python3 - "$WORKFLOW" <<'PY'
import re
import sys
from pathlib import Path
text = Path(sys.argv[1]).read_text(encoding="utf-8")
steps = {
match.group(1): match.group(2)
for match in re.finditer(r"(?ms)^ ([A-Za-z0-9_-]+):\n(.*?)(?=^ [A-Za-z0-9_-]+:\n|\Z)", text)
}
case_steps = (
("greenfield-git-present", "next-git-present"),
("greenfield-main-git-present", "main-git-present"),
("greenfield-git-absent", "next-git-absent"),
)
for step, case in case_steps:
block = steps[step]
verify = block.index("bash tools/verify-greenfield-expected-red.sh")
mark = block.index(f"mark \\\n tools/fixtures/greenfield-expected-red.tsv .greenfield-case-state \\\n \"$coverage_run\" {case}")
assert verify < mark, f"{step} marks execution before successful verification"
for step in (
"greenfield-git-present",
"greenfield-main-git-present",
"greenfield-remote-installer-contract",
"greenfield-git-absent",
):
assert re.search(
r"(?m)^ depends_on:\n - greenfield-case-denominator-init$", steps[step]
), f"{step} can race marker initialization"
final = steps["greenfield-case-denominator"]
assert "status: [success, failure]" in final
assert "bash tools/verify-greenfield-case-coverage.sh check" in final
for dependency in (
"greenfield-git-present",
"greenfield-main-git-present",
"greenfield-remote-installer-contract",
"greenfield-git-absent",
):
assert f" - {dependency}\n" in final, f"final gate can race {dependency}"
PY
printf 'greenfield case coverage tests passed\n'