Alertes d’échec GitHub Actions sur votre iPhone
GitHub sait déjà vous tenir informé de vos workflows : dans l’app GitHub Mobile, activez les notifications Actions, et vous recevrez un push pour les exécutions que vous avez lancées. Si cela vous suffit, inutile d’aller plus loin.
Honk va un cran plus loin. Il réunit les échecs de tous vos dépôts, y compris ceux déclenchés par d’autres, regroupés par workflow et par branche, dans la même boîte de réception que vos serveurs et vos tâches cron, avec un rétablissement quand la branche repasse au vert. Le plus rapide est de connecter le webhook de GitHub à Honk : une seule URL, et aucune modification de vos workflows. Si vous préférez décider dans le workflow lui-même, la seconde moitié de ce guide ajoute une étape à la fin d’un job.
Avant de commencer
- Un compte Honk. Honk est pour l’instant sur invitation : demandez un accès.
- Un projet pour la CI, dans un espace de travail dont vous êtes propriétaire ou administrateur.
- Un accès administrateur au dépôt, ou à l’organisation, sur GitHub.
1. Connecter GitHub dans Honk
Dans l’app web Honk, ouvrez le projet, allez dans Connexions et cliquez sur Connecter un service. Choisissez GitHub et cliquez sur Connecter. Honk affiche l’URL du webhook de la connexion, qui commence par https://honk-honk.app/v1/hooks/github/.
Sous Clé de signature, cliquez sur Générer, copiez la clé, puis cliquez sur Enregistrer la clé. GitHub signe chaque envoi avec elle, et Honk refuse ceux qui ne correspondent pas. Une fois la clé enregistrée, Honk ne l’affiche plus.
2. Ajouter le webhook dans GitHub
Dans le dépôt, ouvrez Settings ▸ Webhooks et cliquez sur Add webhook. Pour couvrir tous les dépôts d’un coup, passez plutôt par Settings ▸ Webhooks de l’organisation. Renseignez ensuite :
- Payload URL : l’URL fournie par Honk.
- Content type :
application/json. Honk ne sait pas lire l’encodage de formulaire que GitHub propose par défaut. - Secret : la clé que vous avez générée.
- Which events would you like to trigger this webhook? : choisissez Let me select individual events et cochez Workflow runs, ainsi que Deployment statuses, Releases et Issues si vous les voulez aussi.
Cliquez sur Add webhook. GitHub envoie aussitôt un ping, que la connexion affiche dans Honk comme son dernier envoi.
3. Vérifier les envois
Dans GitHub, l’onglet Recent Deliveries du webhook liste chaque envoi avec la réponse de Honk : 202 quand Honk l’a accepté, y compris pour les types d’événements qu’il ignore, et 401 quand la signature ne correspond pas. Dans Honk, la connexion affiche l’heure du dernier envoi, ou la dernière erreur.

La prochaine exécution en échec, sur n’importe quelle branche, déclenche un push. Rien d’autre à faire : aucun secret dans le dépôt, aucune étape à ajouter, et tous les workflows sont couverts, y compris les nouveaux.
Ce que devient chaque événement
- Une exécution en échec (
workflow_run), y compris celle qui n’a pas pu démarrer ou qui a dépassé son délai : un problème, un Klaxon long intitulé « CI failed on main · acme/api », avec le numéro d’exécution, la personne qui l’a lancée, le message du commit et un lien vers l’exécution. Un groupe par dépôt, workflow et branche. - L’exécution réussie suivante sur cette branche : un rétablissement, « CI passed on main · acme/api », qui clôt le problème. Une réussite sans échec préalable est écartée : une branche en bonne santé ne vous dérange jamais. Les exécutions annulées ou sautées sont ignorées.
- Un déploiement en échec (
deployment_status) : un problème, un Klaxon long, un groupe par dépôt et par environnement. Le déploiement réussi suivant le clôt, et un déploiement réussi sans échec préalable donne un Bip-bip, « Deployed to production · acme/api ». - Une release publiée (
release) : un Petit coup de klaxon, avec les notes de version. - Une nouvelle issue (
issues) : un Petit coup de klaxon, un groupe par issue.
Dans Événements transformés en messages, sur la connexion, décochez ceux dont vous ne voulez pas, puis cliquez sur Enregistrer. Chaque service connecté compte dans le forfait de votre espace de travail : Free en inclut 2, Pro 20 et Team 100. Les messages comptent dans les limites quotidiennes du forfait, comme tous les autres ; les tarifs les détaillent.
Autre méthode : une étape dans le workflow
Sans la connexion, une étape à la fin d’un job peut signaler l’échec elle-même. Vous choisissez job par job ce qui est envoyé, et cela fonctionne là où vous ne pouvez pas ajouter de webhook. Pour les mêmes workflows, utilisez l’une ou l’autre méthode : avec les deux, chaque échec vous serait signalé deux fois.
Cette méthode demande une clé d’ingestion : dans l’app web, ouvrez le projet, puis Clés, et créez-en une.
Enregistrer l’URL et la clé comme secrets
Un secret de dépôt ne vaut que pour ce dépôt ; un secret d’organisation vous évite de répéter l’opération partout. Avec GitHub CLI :
# with the GitHub CLI, for one repository (or use --org for all of them)
gh secret set HONK_URL --body "https://honk-honk.app"
gh secret set HONK_KEY # paste the ingestion key when askedAjouter une étape qui ne s’exécute qu’en cas d’échec
Placez cette étape en dernier dans le job qui vous intéresse. if: failure() ne l’exécute que si une étape précédente a échoué. Elle utilise jq et curl, déjà présents sur tous les runners hébergés par GitHub, il n’y a donc rien à installer :
- 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 @- || trueQuelques choix à noter :
- La clé de groupe combine le dépôt et la branche,
ci/acme/api/main. Le premier échec surmaindéclenche un push ; les échecs suivants surmainrejoignent le même groupe et deviennent des mises à jour discrètes. Un échec sur une autre branche forme son propre groupe. - La clé d’idempotence combine l’identifiant de l’exécution et le numéro de tentative. Si curl réessaie après une réponse perdue, Honk renvoie l’événement d’origine au lieu d’en créer un second. En revanche, un clic sur Re-run lance une nouvelle tentative, donc un nouvel événement.
jqconstruit le JSON : un nom de workflow ou de branche contenant des guillemets ne peut pas casser la requête.|| truegarantit qu’une panne de Honk ne change jamais la nature de l’échec d’un build.
Facultatif : un rétablissement quand la branche repasse au vert
Pour clore l’incident quand la branche est de nouveau verte, ajoutez une seconde étape, exécutée en cas de succès. Elle demande à GitHub si l’exécution précédente sur cette branche a échoué et, seulement dans ce cas, signale un rétablissement :
# 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 @- || trueCette étape reste facultative. Sans elle, un épisode sans nouvel événement devient inactif au bout de 24 heures, et l’échec suivant en ouvre un autre, avec un nouveau push.
La même chose avec la CLI honk
Si vous préférez la CLI honk, qui gère pour vous les nouvelles tentatives avec une seule clé d’idempotence et un délai maximal global, installez-la dans les étapes exécutées en cas d’échec et appelez uhoh. Go est préinstallé sur les runners Linux hébergés par GitHub :
- name: Install the honk CLI
if: failure()
run: |
go install github.com/honk-hq/go/cmd/honk@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 uhoh --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 }}" || trueLe résultat
Le premier échec sur main arrive en Klaxon long sur Honk pour iPhone, et le lien vers l’exécution s’ouvre d’un toucher depuis la boîte de réception. Les échecs suivants sur la même branche mettent à jour ce groupe sans refaire vibrer le téléphone, et les heures calmes retiennent les échecs de CI la nuit, sauf s’ils sont urgents. Pour signaler aussi les déploiements réussis, voyez le guide des déploiements ; le guide Sentry ajoute les erreurs que votre app rencontre une fois en ligne.
Pour l’instant, Honk est sur invitation : demandez un accès. Tout ce guide fonctionne avec le forfait Free.