# GitHub Actions: Fehlschläge als Push aufs iPhone

> GitHub-Actions-Fehler als Push aufs iPhone: ein Workflow-Schritt, eine Gruppe pro Repository und Branch, Entwarnung, wenn der Branch wieder grün ist.

Source: https://honk-me.app/de/anleitungen/github-actions-fehler-push

GitHub kann dich schon selbst über Workflow-Läufe informieren. Schalte in der App GitHub Mobile die Mitteilungen für Actions ein, und du bekommst einen Push für Läufe, die du gestartet hast. Wenn dir das reicht, brauchst du nichts weiter.

Honk geht einen Schritt weiter. Es meldet Fehlschläge aus vielen Repositories, auch aus Läufen, die andere gestartet haben, und bündelt sie in einer Gruppe pro Branch. Sie landen im selben Posteingang wie deine Server und Cronjobs, und sobald der Branch wieder grün ist, gibt Honk Entwarnung. Dafür reicht ein einziger Schritt am Ende eines Jobs.

## Voraussetzungen

- Ein Honk-Konto. Honk gibt es vorerst nur auf Einladung: [Zugang anfragen](https://honk-me.app/de/zugang-anfragen).
- Ein Projekt für CI und ein Ingest-Schlüssel: Öffne in der Web-App das Projekt und erstelle unter **Schlüssel** einen neuen.

## 1. URL und Schlüssel als Secrets speichern

Repository-Secrets gelten für ein einzelnes Repository, Organisations-Secrets ersparen dir die Wiederholung in jedem. Mit der GitHub CLI geht das so:

```sh
# with the GitHub CLI, for one repository (or use --org for all of them)
gh secret set HONK_URL --body "https://honk-me.app"
gh secret set HONK_KEY        # paste the ingestion key when asked
```

## 2. Einen Schritt hinzufügen, der nur bei Fehlschlag läuft

Setz diesen Schritt ans Ende des Jobs, der dir wichtig ist. `if: failure()` führt ihn nur aus, wenn ein früherer Schritt fehlgeschlagen ist. Er braucht nur `jq` und `curl`, und beide sind auf jedem GitHub-gehosteten Runner vorinstalliert:

```yaml
      - name: Tell Honk
        if: failure()
        env:
          HONK_URL: ${{ secrets.HONK_URL }}
          HONK_KEY: ${{ secrets.HONK_KEY }}
          WORKFLOW: ${{ github.workflow }}
          REPO: ${{ github.repository }}
          BRANCH: ${{ github.ref_name }}
          RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
          ATTEMPT: ${{ github.run_id }}-${{ github.run_attempt }}
        run: |
          jq -n --arg title "CI failed: $WORKFLOW on $BRANCH" --arg url "$RUN_URL" --arg key "ci/$REPO/$BRANCH" \
            '{title: $title, message: $url, url: $url, severity: "long", event_type: "problem",
              group_key: $key, source: "github-actions", category: "deployments"}' |
          curl -sS --max-time 10 --retry 3 --retry-all-errors "$HONK_URL/v1/messages" \
            -H "Authorization: Bearer $HONK_KEY" -H "Content-Type: application/json" \
            -H "Idempotency-Key: gh-$ATTEMPT" --data-binary @- || true
```

Darauf kommt es an:

- **Der Gruppenschlüssel besteht aus Repository und Branch**, `ci/acme/api/main`. Der erste Fehlschlag auf `main` wird gepusht. Weitere Fehlschläge auf `main` landen in derselben Gruppe und werden zu ruhigen Updates. Ein Fehlschlag auf einem anderen Branch bekommt eine eigene Gruppe.
- **Der Idempotency-Key ist die Run-ID plus die Versuchsnummer.** Wiederholt curl die Anfrage nach einer verlorenen Antwort, gibt Honk das ursprüngliche Ereignis zurück, statt ein zweites anzulegen. Drückst du dagegen **Re-run**, ist der neue Versuch ein neues Ereignis.
- **`jq` baut das JSON**, damit ein Workflow- oder Branch-Name mit Anführungszeichen die Anfrage nicht kaputt machen kann.
- **`|| true`** sorgt dafür, dass ein Ausfall von Honk aus einem fehlgeschlagenen Build nie einen anderen Fehler macht.

## 3. Optional: Entwarnung, wenn wieder alles grün ist

Um den Vorfall zu schließen, sobald der Branch wieder durchläuft, fügst du einen zweiten Schritt hinzu. Er läuft bei Erfolg, fragt GitHub, ob der vorherige Lauf auf diesem Branch fehlgeschlagen ist, und gibt nur dann Entwarnung:

```yaml
      # needs `permissions: actions: read` when the workflow restricts the token
      - name: Tell Honk it works again
        if: success()
        env:
          GH_TOKEN: ${{ github.token }}
          HONK_URL: ${{ secrets.HONK_URL }}
          HONK_KEY: ${{ secrets.HONK_KEY }}
          WORKFLOW: ${{ github.workflow }}
          REPO: ${{ github.repository }}
          BRANCH: ${{ github.ref_name }}
          ATTEMPT: ${{ github.run_id }}-${{ github.run_attempt }}
        run: |
          previous=$(gh run list --repo "$REPO" --workflow "$WORKFLOW" --branch "$BRANCH" \
            --limit 2 --json conclusion --jq '.[1].conclusion')
          [ "$previous" = "failure" ] || exit 0
          jq -n --arg title "CI green again: $WORKFLOW on $BRANCH" --arg key "ci/$REPO/$BRANCH" \
            '{title: $title, message: "The last run passed.", severity: "beep", event_type: "recovery",
              group_key: $key, source: "github-actions", category: "deployments"}' |
          curl -sS --max-time 10 --retry 3 --retry-all-errors "$HONK_URL/v1/messages" \
            -H "Authorization: Bearer $HONK_KEY" -H "Content-Type: application/json" \
            -H "Idempotency-Key: gh-$ATTEMPT-ok" --data-binary @- || true
```

Ohne diesen Schritt geht nichts kaputt: Eine Episode ohne neue Ereignisse wird nach 24 Stunden inaktiv, und der nächste Fehlschlag eröffnet eine neue und wird wieder gepusht.

## Dasselbe mit der honk-me-CLI

Lieber mit der CLI? Sie übernimmt Wiederholungen mit einem Idempotency-Key und ein Gesamtzeitlimit für dich. Installiere sie in Schritten, die nur bei einem Fehlschlag laufen, und ruf `problem` auf. Go ist auf den GitHub-gehosteten Linux-Runnern vorinstalliert:

```yaml
      - name: Install honk-me
        if: failure()
        run: |
          go install github.com/honk-me/honk-go/cmd/honk-me@latest
          echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"

      - name: Notify
        if: failure()
        env:
          HONK_URL: ${{ secrets.HONK_URL }}
          HONK_KEY: ${{ secrets.HONK_KEY }}
        run: |
          honk-me problem --group-key "ci/${{ github.repository }}/${{ github.ref_name }}" \
            --title "CI failed: ${{ github.workflow }}" --message "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
            --source github-actions --category deployments \
            --idempotency-key "gh-${{ github.run_id }}-${{ github.run_attempt }}" || true
```

## Was du bekommst

Der erste Fehlschlag auf `main` kommt als Langes Hupen an. Den Link zum Lauf öffnest du im Posteingang mit einem Tippen. Wiederholungen auf demselben Branch aktualisieren die Gruppe, statt dein Handy erneut vibrieren zu lassen. Ruhezeiten halten CI-Fehlschläge über Nacht zurück, außer du sendest sie als dringend. Wie du Honk auch erfolgreiche Deploys meldest, zeigt die [Deploy-Anleitung](https://honk-me.app/de/anleitungen/deploy-push).
