diff --git a/.github/actions/notify-irm/README.md b/.github/actions/notify-irm/README.md new file mode 100644 index 0000000..3d1a4f7 --- /dev/null +++ b/.github/actions/notify-irm/README.md @@ -0,0 +1,48 @@ +# notify-irm + +POST an alert state (`alerting`/`ok`) to a Grafana IRM Custom webhook +integration so a homelab IRM service can page on CI failure and +auto-resolve once the workflow goes green again. + +## Behaviour + +- Sends `state=alerting` when any prior job failed or was cancelled. +- Sends `state=ok` (with the same `alert_uid`) on a full green run so the + open incident auto-resolves. +- Silently skips when `webhook-url` is empty, so the workflow remains + usable on forks and during initial bring-up. +- `alert_uid` is keyed on `gha---` (no SHA), so + re-runs and follow-up commits collapse into the same alert group, and a + green run on a later commit resolves the incident raised by an earlier + failed commit. + +## Inputs + +| Name | Required | Default | Description | +| -------------------- | :------: | ------- | ---------------------------------------------------------------------------------------------------------- | +| `webhook-url` | yes | — | Grafana IRM Custom webhook URL. Empty value disables the step. | +| `job-failed` | yes | — | `'true'` when any prior job failed/was cancelled, `'false'` otherwise. | +| `service` | no | `ci` | Logical service tag for IRM routing/labelling. | +| `resolve-on-success` | no | `true` | When `true`, a green run posts `state=ok` to auto-resolve. Set `false` for unique-uid workflows (e.g. tags). | + +## Usage + +```yaml +notify-irm: + name: Notify Grafana IRM + needs: [lint, test] + 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@ # 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') }} +``` + +For tag-push workflows where every run has a unique `alert_uid`, set +`resolve-on-success: "false"` and gate with `if: ${{ always() }}` instead. diff --git a/.github/actions/notify-irm/action.yml b/.github/actions/notify-irm/action.yml index a6e695d..658854c 100644 --- a/.github/actions/notify-irm/action.yml +++ b/.github/actions/notify-irm/action.yml @@ -11,20 +11,9 @@ description: | follow-up commits collapse into the same alert group, and a green run on a later commit resolves the incident from a previous failed commit. - Typical usage in a caller workflow: - - notify-irm: - name: Notify Grafana IRM - needs: [job1, job2, ...] - if: ${{ always() && github.ref == 'refs/heads/main' && github.event_name == 'push' }} - runs-on: ubuntu-24.04 - permissions: - contents: read - steps: - - uses: DevSecNinja/.github/.github/actions/notify-irm@ # main - with: - webhook-url: ${{ secrets.GRAFANA_IRM_WEBHOOK_URL }} - job-failed: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + See README.md in this directory for usage examples — kept out of this + description because GitHub Actions templates expressions inside action.yml + even within description blocks. inputs: webhook-url: @@ -33,8 +22,8 @@ inputs: job-failed: description: | Set to 'true' when any prior job failed or was cancelled, 'false' on a - full green run. Typically sourced from - `contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')`. + full green run. Typically sourced from a contains() check on + needs.*.result for 'failure' or 'cancelled'. required: true service: description: Logical service tag for IRM routing/labelling.