diff --git a/scripts/tests/generated-child_test.sh b/scripts/tests/generated-child_test.sh index 54c06cf..eaba66a 100755 --- a/scripts/tests/generated-child_test.sh +++ b/scripts/tests/generated-child_test.sh @@ -48,9 +48,12 @@ bad() { printf ' FAIL %s\n %s\n' "$1" "${2:-}"; fail=$((fail+1)); } echo "generated-child tests" +# A missing tool is a FAILURE, not a skip. An `exit 0` with zero assertions is +# indistinguishable from a real pass to anything reading the exit code -- which +# is the whole failure mode this harness exists to close. if ! command -v golangci-lint >/dev/null 2>&1; then - echo " SKIP golangci-lint not installed — cannot gate the generated child" >&2 - exit 0 + bad "golangci-lint is available" "not on PATH — the generated child cannot be gated" + echo; echo "$pass passed, $fail failed"; exit 1 fi tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' EXIT @@ -73,7 +76,7 @@ if [ ! -d "$tmp/cmd/__PROJECT_NAME__" ]; then echo; echo "$pass passed, $fail failed"; exit 1 fi mv "$tmp/cmd/__PROJECT_NAME__" "$tmp/cmd/childproj" -find "$tmp" -type f \( -name '*.go' -o -name '*.mod' -o -name '*.yml' -o -name '*.md' \) \ +find "$tmp" -type f \( -name '*.go' -o -name '*.mod' -o -name '*.yml' -o -name '*.md' -o -name 'Dockerfile' \) \ -exec sed -i \ -e 's|__MODULE_PATH__|git.d-ma.be/mathias/childproj|g' \ -e 's|__PROJECT_NAME__|childproj|g' {} + @@ -97,12 +100,21 @@ out="$(cd "$tmp" && go vet ./... 2>&1)" # The one that caught #1/#2: errcheck on the deferred shutdown, in a package the # template's own `golangci-lint run ./...` never analysed. -out="$(cd "$tmp" && golangci-lint run ./... 2>&1)" -if printf '%s' "$out" | grep -qE '^[0-9]+ issues:|issues:$'; then - bad "the generated child passes golangci-lint" "$(printf '%s' "$out" | grep -E '\.go:[0-9]+' | head -3)" -else - ok "the generated child passes golangci-lint" -fi +# Graded on the EXIT CODE, never on grepping the output. golangci-lint exits +# 0 clean / 1 issues found / >1 the linter itself failed. Matching its +# human-readable summary instead scores a CRASHED linter as a pass -- bad +# config, unwritable TMPDIR, OOM, or a future change to its output format all +# produce non-matching text. Since this harness is the only gate covering the +# entrypoint, that would leave it unchecked with CI green, which is precisely +# the defect class this file exists to end. +out="$(cd "$tmp" && golangci-lint run ./... 2>&1)"; rc=$? +case "$rc" in + 0) ok "the generated child passes golangci-lint" ;; + 1) bad "the generated child passes golangci-lint" \ + "$(printf '%s' "$out" | grep -E '\.go:[0-9]+' | head -3)" ;; + *) bad "golangci-lint ran successfully" \ + "linter exited $rc — the child is UNCHECKED, not clean: $(printf '%s' "$out" | tail -2)" ;; +esac echo echo "$pass passed, $fail failed"