From cd6bbb24816e93a6d379f9c28a6fd423b97c5b54 Mon Sep 17 00:00:00 2001 From: "hugh-hackman[bot]" <266376744+hugh-hackman[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 01:52:08 +0000 Subject: [PATCH] ci: automate ci health checks (#11) Co-authored-by: gandalf-the-greybeard[bot] --- .github/scripts/ci-health-check.sh | 72 ++++++++++++++++++++++++++ .github/workflows/ci-health-check.yaml | 24 +++++++++ 2 files changed, 96 insertions(+) create mode 100755 .github/scripts/ci-health-check.sh create mode 100644 .github/workflows/ci-health-check.yaml diff --git a/.github/scripts/ci-health-check.sh b/.github/scripts/ci-health-check.sh new file mode 100755 index 0000000..58604c5 --- /dev/null +++ b/.github/scripts/ci-health-check.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# ci-health-check.sh — Scan all privilegedescalation repos for CI/CD health +# Run from: /paperclip/privilegedescalation/engineering/hugh +# Requires: GH_TOKEN set (use: export GH_TOKEN=$(bash ./get-github-token.sh)) +set -euo pipefail + +ORG="privilegedescalation" +PLUGIN_REPOS=( + headlamp-polaris-plugin + headlamp-rook-plugin + headlamp-sealed-secrets-plugin + headlamp-intel-gpu-plugin + headlamp-tns-csi-plugin + headlamp-kube-vip-plugin +) + +echo "=== CI/CD Health Check — $(date -u '+%Y-%m-%d %H:%M UTC') ===" +echo "" + +failures=0 +warnings=0 + +for repo in "${PLUGIN_REPOS[@]}"; do + echo "--- ${repo} ---" + + # Get last 5 runs + runs=$(gh run list --repo "${ORG}/${repo}" --limit 5 --json name,conclusion,headBranch,updatedAt 2>/dev/null || echo "[]") + + if [ "$runs" = "[]" ]; then + echo " WARNING: No workflow runs found" + ((warnings++)) || true + continue + fi + + # Use node for JSON parsing (jq not available) + main_failures=$(echo "$runs" | node -e " + const d = JSON.parse(require('fs').readFileSync(0,'utf8')); + const fails = d.filter(r => r.headBranch==='main' && r.conclusion==='failure'); + console.log(fails.length); + ") + total=$(echo "$runs" | node -e " + const d = JSON.parse(require('fs').readFileSync(0,'utf8')); + console.log(d.length); + ") + + if [ "$main_failures" -gt 0 ]; then + echo " FAIL: ${main_failures} failure(s) in last ${total} runs on main:" + echo "$runs" | node -e " + const d = JSON.parse(require('fs').readFileSync(0,'utf8')); + d.filter(r => r.headBranch==='main' && r.conclusion==='failure') + .forEach(r => console.log(' - ' + r.name + ' (' + r.updatedAt + ')')); + " + ((failures++)) || true + else + echo " OK: All recent runs passing" + fi + + # Check latest release + latest_release=$(gh api "repos/${ORG}/${repo}/releases" --jq '.[0].tag_name // "none"' 2>/dev/null || echo "error") + echo " Latest release: ${latest_release}" + + echo "" +done + +echo "=== Summary ===" +echo "Repos scanned: ${#PLUGIN_REPOS[@]}" +echo "With failures: ${failures}" +echo "With warnings: ${warnings}" + +if [ "$failures" -gt 0 ]; then + exit 1 +fi diff --git a/.github/workflows/ci-health-check.yaml b/.github/workflows/ci-health-check.yaml new file mode 100644 index 0000000..a58b476 --- /dev/null +++ b/.github/workflows/ci-health-check.yaml @@ -0,0 +1,24 @@ +name: CI/CD Health Check + +on: + schedule: + - cron: '0 8 * * 1-5' # Every weekday at 8 AM UTC + workflow_dispatch: + +jobs: + health-check: + runs-on: local-ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Run CI/CD health check + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ./.github/scripts/ci-health-check.sh \ No newline at end of file