Post

Custom GitHub WebHook Notifications via GitHub Actions

Custom GitHub WebHook Notifications via GitHub Actions

Motivation for Custom Notifications

A class of notifications on GitHub repositories allows sending events via webhooks. A prevalent way people use this feature is by setting up a Slack or Discord channel to send events there. While for general use cases, it does allow customizing which events get sent; I found it lacking in two areas →

  • It doesn’t allow customization of the actor; for example - send an event only when a different user adds a comment to an issue
  • It doesn’t allow scheduled notifications; for example - send repository stars/forks/other statistics on a weekly schedule

I used to have a Discord channel dedicated to the default webhook notifications, mainly to receive workflow run events, issue comments, etc. I had it set to send me everything, but I always wanted to customize it! If we don’t want to receive stars, discussions, forks, etc. (just customize per repository in general), there isn’t an easy solution!

That’s when I figured out how underused my GitHub workflow triggers were! This blog post covers my research and implementation efforts on setting up custom notifications for my GitHub events using GitHub Actions to send WebHook events.

Implementation

Solution

GitHub Actions (GHA) allows automation of workflows, usually for building, testing, and deploying stuff. These workflows are defined in .github/workflows/ and can be triggered by various repository events (pull requests, issues, cron schedules, etc., not just pushes). Workflows consist of jobs, which contain steps executed in sequence. Steps can be standard shell commands or predefined actions from the GitHub Actions Marketplace.

Shell command support allows using curl to send requests to webhooks. Workflows also support a wide variety of triggers for executing jobs, making them the best method for setting up and sending custom notifications.

Workflow Setup

I created a GitHub Actions workflow for my Local-Content-Share repository to send notifications as my first attempt. Reading the documentation (linked at the end) took a while, but I narrowed it down to a few events that mattered to me for that repo. As such, GitHub listens for events and triggers the workflow that formats a message before sending it to a webhook. So, here is the example →

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
name: Custom Notifications
on:
  schedule:
    - cron: '30 16 * * 6' # 4:30 pm UTC every saturday
  issues:
    types: [opened, edited, deleted, closed]
  issue_comment:
    types: [created]
  workflow_run:
    workflows: ["Docker Publish", "Build Binary"]
    types: [completed]
  pull_request:
    types: [opened, closed, edited, review_requested]
  pull_request_review_comment:
    types: [created]
  pull_request_review:
    types: [submitted]

jobs:
  weekly-summary:
    if: github.event_name == 'schedule'
    runs-on: ubuntu-latest
    steps:
      - name: Calculate Summary
        run: |
 REPO="$"
 STARS=$(curl -s -H "Authorization: Bearer $" "https://api.github.com/repos/$REPO" | jq .stargazers_count)
 FORKS=$(curl -s -H "Authorization: Bearer $" "https://api.github.com/repos/$REPO" | jq .forks_count)
 COMMITS=$(curl -s -H "Authorization: Bearer $" \
 "https://api.github.com/repos/$REPO/commits?since=$(date -u -d 'last saturday' '+%Y-%m-%dT%H:%M:%SZ')" | jq length)
 curl -H "Content-Type: application/json" -X POST \
 -d "{\"content\": \"*Weekly summary for **$REPO***\nStars - $STARS, Forks - $FORKS, Commits this week - $COMMITS\"}" $

  issue-comment-notification:
    if: github.event_name == 'issues' || github.event_name == 'issue_comment'
    runs-on: ubuntu-latest
    steps:
      - name: Notify on Issue or Comment
        if: github.actor != 'Tanq16'
        run: |
 curl -H "Content-Type: application/json" -X POST \
 -d "{\"content\": \"*New issue/comment from **$***\n$\"}" $

  build-status-notification:
    if: github.event_name == 'workflow_run'
    runs-on: ubuntu-latest
    steps:
      - name: Notify on Build Status
        run: |
 curl -H "Content-Type: application/json" -X POST \
 -d "{\"content\": \"*Workflow run for **$***\n$ - $\"}" $

  pull-request-notification:
    if: github.event_name == 'pull_request' || github.event_name == 'pull_request_review_comment' || github.event_name == 'pull_request_review'
    runs-on: ubuntu-latest
    steps:
      - name: Notify on PR related activities
        if: github.actor != 'Tanq16'
        run: |
 curl -H "Content-Type: application/json" -X POST \
 -d "{\"content\": \"*New PR activity from **$***\n$\"}" $

Example Workflow Breakdown

  • The workflow listens for a wide variety of triggers like issue creation, comments, workflow runs, and pull requests
  • A weekly summary of stars, forks, and the number of commits in the past week is automatically sent every weekend
  • The curl command is used to send a JSON payload to a Discord webhook stored in the repository secrets (as DISCORD_WEBHOOK)
  • For individual triggers like issue comments, the job step only runs if the actor was not myself (i.e., my comment wouldn’t trigger an event)

Conditionals (like if: github.actor != 'your-username') are the main thing in GitHub workflows that allow filtering out actions from specific users and customizing them however you like. You could also significantly modify the content being sent with custom messages, links, etc.

API rate limits also apply when querying GitHub’s API frequently, so I don’t recommend many requests for a single job/workflow.

Fin

To summarize → for most use cases, leveraging GitHub Actions and webhook integrations is an effective way to stay updated on repository activity. While GitHub provides built-in notifications, the flexibility of custom actions makes it worth the effort! As a plus, if you’re new to CI/CD, this is a quick toe-dip into that fantastic domain.

Resources

This post is licensed under CC BY 4.0 by the author.