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 (asDISCORD_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.