#!/usr/bin/env bash # pipeline-doctor (cluster #193): assert the parity contract for a repo. # # Given a repo path, it statically checks that the repo follows the corrected # emmett#44 parity standard, and prints the local-equivalent commands a dev can # run. It is read-only: it never touches the registry and never needs a token. # # Usage: pipeline-doctor [--strict] [] (default repo: .) # --strict also exit non-zero if any WARN was emitted (gate the soft checks). # Exit: 0 = all required checks pass (and, in --strict, no warnings); # 1 = one or more required checks failed (or a warning under --strict). # # This is a GATE-READY check (cluster #191/#193): a .woodpecker.yaml step or a # server pre-receive hook can call `pipeline-doctor --strict ` and rely on # the exit code. It is read-only: it never touches the registry, never needs a # token, and never prints one. set -euo pipefail STRICT=0 SELFTEST=0 REPO="." for a in "$@"; do case "$a" in --strict) STRICT=1 ;; --self-test) SELFTEST=1 ;; -h | --help) echo "Usage: pipeline-doctor [--strict] []" echo " Assert the parity contract for (default: .)." echo " --strict exit non-zero on any WARN as well as any FAIL." echo " --self-test run the token-leak heuristic fixtures and exit." exit 0 ;; -*) echo "error: unknown option '$a' (try --help)" >&2 exit 2 ;; *) REPO="$a" ;; esac done # --self-test (#199): exercise the two corrected heuristics on synthetic ci # fixtures so a regression in the token-contract / leak-scan logic is caught here # (and by a CI step) rather than by silently re-breaking 9 real repos. Each case # builds a throwaway repo, runs THIS script on it, and asserts PASS/FAIL. if [ "$SELFTEST" -eq 1 ]; then self="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")" st_fail=0 # The fixture token references are ASSEMBLED from $d at runtime so the raw # bytes of THIS file never contain a literal `echo "$TOKEN"` or a bare # `set -x` line — otherwise the doctor's own leak/xtrace scan would flag # pipeline-doctor.sh when run against parity-lib itself (#199). $sx is the # xtrace directive, likewise assembled to dodge the self-scan. d='$' sx="set -""x" # the literal `set -x`, split so THIS file's bytes don't carry it mk() { # mk mkdir -p "$1/ci" { printf '%s\n' '#!/usr/bin/env bash' 'set -euo pipefail' \ "PUBLISH=\"${d}{PUBLISH:-0}\"" 'resolve_token() {' \ " if [ -n \"${d}{REGISTRY_TOKEN:-}\" ]; then printf '%s' \"${d}REGISTRY_TOKEN\"; return; fi" \ " pass \"${d}PASS_ENTRY\"" '}' "tok=\"${d}(resolve_token)\"" printf '%b\n' "$2" } >"$1/ci/local.sh" } expect() { # expect