91 lines
4.0 KiB
Bash
Executable File
91 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# scripts/ci-detect-already-validated.sh — emit `skip=true|false` to $GITHUB_OUTPUT for the
|
|
# docker-build.yml cross-run tree-identity gate (ersatztv#420). On a merge-to-main push, if the
|
|
# merged tree is byte-identical to a PR head that ALREADY passed `test`+`migrations` (a GREEN
|
|
# combined commit status), the heavy compile/test/migrations work is redundant -- the exact same
|
|
# source was already validated. `build` still runs and still builds+pushes the image, so no image
|
|
# ever ships from unvalidated source.
|
|
#
|
|
# The bias is ALWAYS toward running MORE, never less: a false 'true' would ship (or claim to
|
|
# validate) unreviewed/unvalidated source, so every ambiguous or unverifiable case resolves to
|
|
# skip=false. It is fine (just wasteful) to re-run on an identical tree; it is a correctness bug
|
|
# to skip validation on a tree that differs or was never proven green.
|
|
#
|
|
# Runs identically locally and in CI. Locally (no $GITHUB_OUTPUT) it prints the decision to
|
|
# stdout; e.g. GITHUB_EVENT_NAME=push GITHUB_REF=refs/heads/main scripts/ci-detect-already-validated.sh
|
|
set -euo pipefail
|
|
|
|
out="${GITHUB_OUTPUT:-/dev/stdout}"
|
|
event="${GITHUB_EVENT_NAME:-}"
|
|
ref="${GITHUB_REF:-}"
|
|
|
|
emit() {
|
|
echo "skip=$1" >> "$out"
|
|
echo "-> skip=$1"
|
|
}
|
|
|
|
# Only a push directly to main can possibly be a merge-to-main we can cross-check against an
|
|
# already-validated PR head. Everything else (pull_request, tag push, workflow_dispatch, a push
|
|
# to any other branch) -> always run.
|
|
if [ "$event" != "push" ] || [ "$ref" != "refs/heads/main" ]; then
|
|
echo "event='${event:-<none>}' ref='${ref:-<none>}' (need push to refs/heads/main); running full validation (safe default)"
|
|
emit false
|
|
exit 0
|
|
fi
|
|
|
|
# Deepen history so HEAD's second parent (and its tree) are resolvable -- a shallow checkout may
|
|
# have neither. Mirrors the docs-only/docs-reminder jobs' fetch style. Non-fatal: a failed
|
|
# deepen still falls through to the HEAD^2 check below, which then fails safe.
|
|
git fetch --deepen=2 origin 2>/dev/null || git fetch --unshallow origin 2>/dev/null || true
|
|
|
|
# HEAD must be a real merge commit with a second parent -- that second parent is the PR head CI
|
|
# actually validated. No second parent (a direct/fast-forward/squash push) -> nothing to compare
|
|
# against -> always run.
|
|
pr_head="$(git rev-parse --verify -q HEAD^2 || true)"
|
|
if [ -z "$pr_head" ]; then
|
|
echo "HEAD has no second parent (not a merge commit); running full validation (safe default)"
|
|
emit false
|
|
exit 0
|
|
fi
|
|
|
|
merge_tree="$(git rev-parse --verify -q 'HEAD^{tree}' || true)"
|
|
pr_tree="$(git rev-parse --verify -q "${pr_head}^{tree}" || true)"
|
|
if [ -z "$merge_tree" ] || [ -z "$pr_tree" ]; then
|
|
echo "could not resolve HEAD or HEAD^2 tree; running full validation (safe default)"
|
|
emit false
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$merge_tree" != "$pr_tree" ]; then
|
|
echo "merged tree ($merge_tree) != PR head $pr_head tree ($pr_tree) -- main advanced since the PR was validated; running full validation"
|
|
emit false
|
|
exit 0
|
|
fi
|
|
|
|
# Merge tree matches the PR head tree exactly. Confirm that PR head was actually validated green
|
|
# before trusting it -- query the Gitea combined commit status API. Auth is required (private
|
|
# instance); a missing/failing/non-success response always falls through to skip=false.
|
|
if [ -z "${ETV_STATUS_AUTH:-}" ]; then
|
|
echo "ETV_STATUS_AUTH not set; cannot verify PR head status; running full validation (safe default)"
|
|
emit false
|
|
exit 0
|
|
fi
|
|
|
|
status_url="http://192.168.1.95:3000/api/v1/repos/timothy/ersatztv/commits/${pr_head}/status"
|
|
status_json="$(curl -sf -u "$ETV_STATUS_AUTH" "$status_url" || true)"
|
|
if [ -z "$status_json" ]; then
|
|
echo "status API request for PR head ${pr_head} failed; running full validation (safe default)"
|
|
emit false
|
|
exit 0
|
|
fi
|
|
|
|
state="$(printf '%s' "$status_json" | jq -r '.state // empty' 2>/dev/null || true)"
|
|
if [ "$state" != "success" ]; then
|
|
echo "PR head ${pr_head} combined status is '${state:-<unknown>}', not 'success'; running full validation (safe default)"
|
|
emit false
|
|
exit 0
|
|
fi
|
|
|
|
echo "merged tree == green PR head ${pr_head} (status=success) -> skipping re-validation"
|
|
emit true
|