From 56859d4d1b7c5396f77afc35c6ea364612f262f6 Mon Sep 17 00:00:00 2001 From: Ondrej Belusky Date: Wed, 28 Oct 2026 09:21:58 +0100 Subject: [PATCH] Notify once per workflow run, failures always and successes on master, so every repo reports the same way --- README.md | 22 ++++++++++++++++ action.yml | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 README.md create mode 100644 action.yml diff --git a/README.md b/README.md new file mode 100644 index 0000000..7edc0e7 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# ci-notify + +One ntfy notification per workflow run. Add it as the last job, needing every +other job: a failed job posts to `errors` (priority 5), and a run where +everything passed on `master` posts to `gitea-releases`. Each notification +links to the run. Other branches only report failures, so a feature branch push +stays quiet. + +```yaml + notify: + needs: [test, build-master, deploy-master] + if: always() + runs-on: go-executor + steps: + - uses: https://lab.zlymeda.dynu.net/actions/ci-notify@master + with: + needs: ${{ toJSON(needs) }} + ntfy_token: ${{ secrets.NTFY_TOKEN }} +``` + +`success_branches` widens what is announced (e.g. `master develop`), and the +topics and tokens can be overridden. diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..f122dfe --- /dev/null +++ b/action.yml @@ -0,0 +1,73 @@ +name: CI notify +description: > + Send one ntfy notification for a whole workflow run: a failure whenever a job + failed, and a success when every job passed on a branch that ships. + +inputs: + needs: + description: The jobs to report on, as ${{ toJSON(needs) }} + required: true + success_branches: + description: Branches whose successful runs are announced, separated by spaces + default: master + ntfy_url: + description: ntfy server URL + default: https://ntfy.zlymeda.dynu.net + ntfy_topic: + description: Topic for successes + default: gitea-releases + ntfy_token: + description: Token for successes (secrets.NTFY_TOKEN) + default: '' + ntfy_failure_topic: + description: Topic for failures + default: errors + ntfy_failure_token: + description: Token for failures; the errors topic takes anonymous posts + default: '' + +runs: + using: composite + steps: + - name: Notify + shell: bash + env: + NEEDS: ${{ inputs.needs }} + SUCCESS_BRANCHES: ${{ inputs.success_branches }} + NTFY_URL: ${{ inputs.ntfy_url }} + NTFY_TOPIC: ${{ inputs.ntfy_topic }} + NTFY_TOKEN: ${{ inputs.ntfy_token }} + NTFY_FAILURE_TOPIC: ${{ inputs.ntfy_failure_topic }} + NTFY_FAILURE_TOKEN: ${{ inputs.ntfy_failure_token }} + REPO: ${{ github.repository }} + BRANCH: ${{ github.ref_name }} + SHA: ${{ github.sha }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + set -euo pipefail + # toJSON(needs) is pretty printed: a job name at two spaces, its "result" below it. + results=$(printf '%s\n' "$NEEDS" | awk ' + /^ "[^"]+": *\{/ { match($0, /"[^"]+"/); job = substr($0, RSTART + 1, RLENGTH - 2) } + /"result": *"/ { match($0, /"result": *"[^"]+"/); r = substr($0, RSTART, RLENGTH); sub(/.*"result": *"/, "", r); sub(/"$/, "", r); print job, r }') + [ -n "$results" ] || { echo "no job results in needs: $NEEDS"; exit 1; } + echo "$results" + failed=$(awk '$2 == "failure" { printf "%s%s", sep, $1; sep = ", " }' <<<"$results") + cancelled=$(awk '$2 == "cancelled" { print $1 }' <<<"$results") + passed=$(awk '$2 == "success" { printf "%s%s", sep, $1; sep = ", " }' <<<"$results") + + send() { # topic token priority tags message + auth=() + [ -n "$2" ] && auth=(-H "Authorization: Bearer $2") + curl -sSf -H "Title: $REPO ($BRANCH)" -H "Priority: $3" -H "Tags: $4" -H "Click: $RUN_URL" \ + "${auth[@]}" -d "$5" "$NTFY_URL/$1" >/dev/null + } + + if [ -n "$failed" ]; then + send "$NTFY_FAILURE_TOPIC" "$NTFY_FAILURE_TOKEN" 5 "rotating_light,warning" "Failed: $failed (${SHA:0:7})" + elif [ -n "$cancelled" ]; then + echo "cancelled, nothing to announce" + elif [ -n "$passed" ] && [[ " $SUCCESS_BRANCHES " == *" $BRANCH "* ]]; then + send "$NTFY_TOPIC" "$NTFY_TOKEN" 3 "rocket,white_check_mark" "Passed: $passed (${SHA:0:7})" + else + echo "$BRANCH is not announced on success" + fi