master
sh 69 lines 2.38 KB
Raw
1 #!/usr/bin/env bash
2 # Report current CI status for a PR head commit.
3 #
4 # Usage:
5 # ci-status.sh <pr-number> # human-readable summary
6 # ci-status.sh <pr-number> --json # raw JSON
7 #
8 # This is read-only. Use it BEFORE every push to find FAILURES that must
9 # be addressed in the same push. Do NOT wait for in-progress checks
10 # between iterations -- the next push will trigger a fresh CI run on the
11 # new code, which is what matters. See SKILL.md Step 4b for the policy.
12
13 set -euo pipefail
14
15 # shellcheck source=./_lib.sh
16 # shellcheck disable=SC1091
17 source "$(dirname "$0")/_lib.sh"
18 pr_require_gh
19
20 PR="${1:?usage: $0 <pr-number> [--json]}"
21 pr_require_numeric "${PR}"
22 JSON=0
23 [[ "${2:-}" == "--json" ]] && JSON=1
24
25 SLUG="$(pr_require_slug)"
26
27 # pr view --json statusCheckRollup gives the per-check breakdown.
28 data="$(gh pr view "${PR}" --repo "${SLUG}" --json statusCheckRollup,headRefOid,mergeStateStatus)"
29
30 if (( JSON )); then
31 printf '%s\n' "${data}"
32 exit 0
33 fi
34
35 head_sha="$(jq -r '.headRefOid' <<< "${data}" | head -c 10)"
36 merge_state="$(jq -r '.mergeStateStatus' <<< "${data}")"
37
38 echo "Head: ${head_sha} Merge state: ${merge_state}"
39 echo
40
41 # Group checks by conclusion / status.
42 jq -r '
43 .statusCheckRollup
44 | map(. + {key: ((.conclusion // .status) // "PENDING")})
45 | group_by(.key)
46 | map({key: .[0].key, count: length, names: [.[].name // .[].context]})
47 | sort_by(.key)
48 | .[]
49 | "\(.key)\t\(.count)\t\((.names | sort | unique | join(", ")[0:200]))"
50 ' <<< "${data}" | column -t -s $'\t'
51
52 echo
53 total=$(jq '.statusCheckRollup | length' <<< "${data}")
54 fail=$(jq '[.statusCheckRollup[] | select((.conclusion // "")|test("FAILURE|TIMED_OUT|CANCELLED"))] | length' <<< "${data}")
55 running=$(jq '[.statusCheckRollup[] | select((.status // "")=="IN_PROGRESS" or (.status // "")=="QUEUED")] | length' <<< "${data}")
56 echo "Total checks: ${total} Failing: ${fail} Running: ${running}"
57
58 if (( running > 0 )); then
59 # Exit 2 is informational, not a "do not push" signal. The next push
60 # will start a fresh CI run on top of the new code -- that's what we
61 # actually want to verify. The skill's policy is to push anyway.
62 echo -e "${PR_GRAY}Note: ${running} check(s) still running; the next push will start a fresh CI run.${PR_NC}" >&2
63 exit 2
64 fi
65 if (( fail > 0 )); then
66 echo -e "${PR_RED}WARNING: ${fail} check(s) failing. Address these BEFORE pushing.${PR_NC}" >&2
67 exit 3
68 fi
69 exit 0