AlphornAlphorn Docs

CI/CD Pipeline Notifications

Send CI/CD build notifications from GitHub Actions and GitLab CI when pipelines pass or fail, and route them to Slack, email, or other channels.

CI/CD pipelines run in the background - you need to know when something fails without constantly watching dashboards. Add a curl step to your pipeline and Alphorn routes the result to the right people.

GitHub Actions

Add a notification step at the end of your workflow. Values like the branch name are passed through env: and the JSON is built with jq, rather than pasting ${{ ... }} expressions into the script, so a crafted branch name can't inject shell commands or break the JSON. Add ALPHORN_WEBHOOK and ALPHORN_API_KEY as repository secrets (Settings → Secrets and variables → Actions) first:

.github/workflows/deploy.yml
- name: Notify on success
  if: success()
  env:
    ALPHORN_WEBHOOK: ${{ secrets.ALPHORN_WEBHOOK }}
    ALPHORN_API_KEY: ${{ secrets.ALPHORN_API_KEY }}
    REPO: ${{ github.repository }}
    REF_NAME: ${{ github.ref_name }}
    SHA: ${{ github.sha }}
  run: |
    jq -n --arg m "$REPO deployed from $REF_NAME (commit $SHA)" \
      '{title: "Deploy succeeded", message: $m, priority: 2, tags: ["ci", "deploy", "success"]}' |
    curl -fsS -X POST "$ALPHORN_WEBHOOK" \
      -H "Authorization: Bearer $ALPHORN_API_KEY" \
      -H "Content-Type: application/json" \
      --data-binary @-

- name: Notify on failure
  if: failure()
  env:
    ALPHORN_WEBHOOK: ${{ secrets.ALPHORN_WEBHOOK }}
    ALPHORN_API_KEY: ${{ secrets.ALPHORN_API_KEY }}
    REPO: ${{ github.repository }}
    REF_NAME: ${{ github.ref_name }}
    RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
  run: |
    jq -n --arg m "$REPO failed on $REF_NAME. See: $RUN_URL" \
      '{title: "Deploy FAILED", message: $m, priority: 5, tags: ["ci", "deploy", "failure"]}' |
    curl -fsS -X POST "$ALPHORN_WEBHOOK" \
      -H "Authorization: Bearer $ALPHORN_API_KEY" \
      -H "Content-Type: application/json" \
      --data-binary @-

GitLab CI

CI_JOB_STATUS is only set to the job's result (success, failed, or canceled) in after_script, so send the notification from there. Define ALPHORN_WEBHOOK and ALPHORN_API_KEY as CI/CD variables (Settings → CI/CD → Variables, mark the key as masked), and make sure the job image has jq and curl:

.gitlab-ci.yml
deploy:
  stage: deploy
  script:
    - ./deploy.sh
  after_script:
    - |
      if [ "$CI_JOB_STATUS" = "success" ]; then
        PRIORITY=2; TITLE="Deploy passed"; TAG="success"
      else
        PRIORITY=5; TITLE="Deploy FAILED"; TAG="failure"
      fi
      # jq escapes the branch name, so it can't break the JSON
      jq -n --arg t "$TITLE" --arg m "$CI_PROJECT_NAME on $CI_COMMIT_REF_NAME - $CI_PIPELINE_URL" \
        --argjson p "$PRIORITY" --arg tag "$TAG" \
        '{title: $t, message: $m, priority: $p, tags: ["ci", "deploy", $tag]}' |
      curl -fsS -X POST "$ALPHORN_WEBHOOK" \
        -H "Authorization: Bearer $ALPHORN_API_KEY" \
        -H "Content-Type: application/json" \
        --data-binary @-

Routing examples

ChannelFilterPurpose
Slack (#deployments)Tags has any of deployAll deploy activity
Slack (#dev)Tags has any of failureOnly failures, to avoid noise
PagerDutyPriority greater than 3 and tags has any of failurePage on-call for production failures
EmailTags has any of ciArchive all CI activity

On this page