From 5108a16ee9f8a349ac1d9bdf546678e3035f7a51 Mon Sep 17 00:00:00 2001 From: Jean-Paul van Ravensberg <14926452+DevSecNinja@users.noreply.github.com> Date: Fri, 1 May 2026 10:44:32 +0000 Subject: [PATCH] feat(ci): page Grafana IRM on main-branch workflow failures Adds a notify-irm job to every push-triggered workflow that consumes the new reusable composite action DevSecNinja/.github/.github/actions/notify-irm. On a push:main failure the workflow POSTs state=alerting to the homelab Grafana IRM Custom webhook; a green follow-up run posts state=ok to the same alert_uid (gha---) so the open incident auto-resolves. Workflows extended: - ci.yaml (push:main) - devcontainer-prebuild.yaml (push:main + tags + schedule + dispatch; PR runs excluded) - docs.yml (push:main) - release-please.yml (push:main) - sign-powershell.yml (push:main) - release.yml (tag-push; resolve-on-success disabled because alert_uid is per-tag and never re-fires) The composite action is silently skipped when GRAFANA_IRM_WEBHOOK_URL is unset, so this is a no-op for forks. --- .github/workflows/ci.yaml | 26 ++++++++++++++++++++ .github/workflows/devcontainer-prebuild.yaml | 20 +++++++++++++++ .github/workflows/docs.yml | 18 ++++++++++++++ .github/workflows/release-please.yml | 17 +++++++++++++ .github/workflows/release.yml | 21 ++++++++++++++++ .github/workflows/sign-powershell.yml | 17 +++++++++++++ 6 files changed, 119 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c3dca3e8..a253a8a3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -486,3 +486,29 @@ jobs: files: test-results.xml check_name: 'Pester Test Results' comment_mode: off + + # --- Page on main-branch CI failure (homelab IRM pager) --- + notify-irm: + name: Notify Grafana IRM + needs: + - validate + - test-devcontainer + - test-install + - test-coder-install + - test-light-server + - test-dev-server + - test-windows + - test-windows-coder + - test-bash-scripts + - test-powershell-scripts + if: ${{ always() && github.ref == 'refs/heads/main' && github.event_name == 'push' }} + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Notify Grafana IRM + uses: DevSecNinja/.github/.github/actions/notify-irm@a877d35266a54e54ef043e60a290ed76b4d7b34e # main + with: + webhook-url: ${{ secrets.GRAFANA_IRM_WEBHOOK_URL }} + # `needs.*.result` is system-controlled, safe to interpolate. + job-failed: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} diff --git a/.github/workflows/devcontainer-prebuild.yaml b/.github/workflows/devcontainer-prebuild.yaml index ea8ac77b..903a839d 100644 --- a/.github/workflows/devcontainer-prebuild.yaml +++ b/.github/workflows/devcontainer-prebuild.yaml @@ -193,3 +193,23 @@ jobs: subject-name: ${{ steps.release-manifest.outputs.image }} subject-digest: ${{ steps.release-manifest.outputs.digest }} push-to-registry: true + + # --- Page on main-branch / scheduled / dispatch / tag failure (homelab IRM pager) --- + # PR runs are excluded — they only build for validation and a red PR check + # is signal enough. + notify-irm: + name: Notify Grafana IRM + needs: + - prebuild + - merge + if: ${{ always() && github.event_name != 'pull_request' }} + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Notify Grafana IRM + uses: DevSecNinja/.github/.github/actions/notify-irm@a877d35266a54e54ef043e60a290ed76b4d7b34e # main + with: + webhook-url: ${{ secrets.GRAFANA_IRM_WEBHOOK_URL }} + # `needs.*.result` is system-controlled, safe to interpolate. + job-failed: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 98a3a4f5..972c2f09 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -65,3 +65,21 @@ jobs: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5 + + # --- Page on main-branch docs-build/deploy failure (homelab IRM pager) --- + notify-irm: + name: Notify Grafana IRM + needs: + - build + - deploy + if: ${{ always() && github.ref == 'refs/heads/main' && github.event_name == 'push' }} + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Notify Grafana IRM + uses: DevSecNinja/.github/.github/actions/notify-irm@a877d35266a54e54ef043e60a290ed76b4d7b34e # main + with: + webhook-url: ${{ secrets.GRAFANA_IRM_WEBHOOK_URL }} + # `needs.*.result` is system-controlled, safe to interpolate. + job-failed: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index b3a6079f..179ba5f7 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -42,3 +42,20 @@ jobs: app-id: ${{ vars.RELEASE_PLEASE_APP_ID }} secrets: app-private-key: ${{ secrets.RELEASE_PLEASE_APP_PRIVATE_KEY }} + + # --- Page on main-branch release-please failure (homelab IRM pager) --- + notify-irm: + name: Notify Grafana IRM + needs: + - release-please + if: ${{ always() && github.ref == 'refs/heads/main' && github.event_name == 'push' }} + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Notify Grafana IRM + uses: DevSecNinja/.github/.github/actions/notify-irm@a877d35266a54e54ef043e60a290ed76b4d7b34e # main + with: + webhook-url: ${{ secrets.GRAFANA_IRM_WEBHOOK_URL }} + # `needs.*.result` is system-controlled, safe to interpolate. + job-failed: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6722c392..de457e6e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -70,3 +70,24 @@ jobs: dist/log.sh.sha256 dist/log-sh-${{ github.ref_name }}.tar.gz dist/log-sh-${{ github.ref_name }}.tar.gz.sha256 + + # --- Page on tag-push release failure (homelab IRM pager) --- + # alert_uid is keyed on the tag (REF_NAME), so each release has its own + # alert group. resolve-on-success is disabled because there is no + # subsequent run on the same tag to post a green resolve. + notify-irm: + name: Notify Grafana IRM + needs: + - release + if: ${{ always() }} + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Notify Grafana IRM + uses: DevSecNinja/.github/.github/actions/notify-irm@a877d35266a54e54ef043e60a290ed76b4d7b34e # main + with: + webhook-url: ${{ secrets.GRAFANA_IRM_WEBHOOK_URL }} + # `needs.*.result` is system-controlled, safe to interpolate. + job-failed: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + resolve-on-success: "false" diff --git a/.github/workflows/sign-powershell.yml b/.github/workflows/sign-powershell.yml index f0557b20..ece3ddd6 100644 --- a/.github/workflows/sign-powershell.yml +++ b/.github/workflows/sign-powershell.yml @@ -89,3 +89,20 @@ jobs: repo: context.repo.repo, body: '✅ PowerShell scripts have been signed. Please pull the latest changes after merge.' }) + + # --- Page on main-branch script-signing failure (homelab IRM pager) --- + notify-irm: + name: Notify Grafana IRM + needs: + - sign-scripts + if: ${{ always() && github.ref == 'refs/heads/main' && github.event_name == 'push' }} + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Notify Grafana IRM + uses: DevSecNinja/.github/.github/actions/notify-irm@a877d35266a54e54ef043e60a290ed76b4d7b34e # main + with: + webhook-url: ${{ secrets.GRAFANA_IRM_WEBHOOK_URL }} + # `needs.*.result` is system-controlled, safe to interpolate. + job-failed: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}