ghnotify
is a general GitHub event notification tool to Slack with Open Policy Agent and Rego. There are a lot of notification tools from GitHub to Slack. However, in most case, notification rules are deeply integrated with source code implementation and customization of notification rule by end-user is limited.
ghnotify
uses generic policy language Rego and OPA as runtime to separate implementation and policy completely. Therefore, ghnotify
can handle and notify all type of GitHub event, not only issue/PR comments but also such as following events according to your Rego policy.
- GitHub Actions success/failure
- deploy key creation
- push to specified branch
- add/remove a label
- repository creation, archived, transferred
- team modification
- a new GitHub App installation
Create your Slack bot and keep OAuth Tokens for Your Workspace in OAuth & Permissions page.
ghnotify
evaluates received GitHub event one by one. If notify
variable exists in evaluation results, ghnotify
notifies a message to Slack according to the results.
Policy rules are following.
Input: What data will be provided
input.name
: Event name. It comes fromX-GitHub-Event
header.input.event
: Webhook events. See docs for more detail and schema.
Result: What data should be returned
notify
: Set of notification messagesnotify[_].channel
: Destination channel of Slack. It can be used by only API tokennotify[_].text
: Custom message of slack notificationnotify[_].body
: Custom message bodynotify[_].color
: Message bar colornotify[_].fields
: Set of custom message fields.notify[_].fields[_].name
: Field namenotify[_].fields[_].value
: Field valuenotify[_].fields[_].url
: Link assigned to the field
package github.notify
notify[msg] {
input.name == "issue_comment"
contains(input.event.comment.body, "mizutani")
msg := {
"channel": "#notify-mizutani",
"text": "Hello, mizutani",
"body": input.event.comment.body,
}
}
Then, you shall get a message like following.
package github.notify
notify[msg] {
input.name == "workflow_run"
input.event.action == "completed"
input.event.conclusion == "failure"
msg := {
"channel": "#notify-failure",
"text": "workflow failed",
"color": "#E01E5A", # red
}
}
package github.notify
notify[msg] {
input.name == "pull_request"
input.event.action == "labeled"
input.event.label.name == "breaking-change"
labels := { name | name := input.event.pull_request.labels[_].name }
msg := {
"channel": "#notify-mizutani",
"text": "breaking change assigned",
"fields": [
{
"name": "All labels",
"value": concat(", ", labels),
},
],
}
}
- Pros: Easy to install
- Cons: GitHub Actions can receive events from only the repository
Create GitHub Actions workflow as following.
name: Build and publish container image
on:
push:
issue:
issue_comment:
jobs:
build:
runs-on: ubuntu-latest
env:
GHNOTIFY_SLACK_API_TOKEN: ${{ secrets.GHNOTIFY_SLACK_API_TOKEN }}
steps:
- name: checkout
uses: actions/checkout@v2
- name: dump event
run: echo '${{ toJSON(github.event) }}' > /tmp/event.json
- uses: docker://ghcr.io/m-mizutani/ghnotify:latest
with:
args: "emit -f /tmp/event.json -t ${{ github.event_name }} --local-policy ./policy"
- Pros: Easy to install
- Cons: GitHub Actions can receive event on each repository, can not watch organization wide
Deploy ghnotify
to your environment and prepare URL that can be accessed from public internet. I recommend Cloud Run of Google Cloud in the use case.
When deploying ghnotify
, I recommend to generate and use Webhook secret value. Please prepare random token and provide it to --webhook-secret
.
Callback endpoint will be http://{hostname}:4080/webhook/github
. You can change port number by --addr
option.
- Go to https://github.com/settings/apps and click
New GitHub App
- Grant permissions and check events you want to subscribe in
Subscribe to events
. - Check
Active
inWebhook
section - Set URL of deployed
ghnotify
toWebhook URL
- Set Webhook secret to
Webhook secret
if you configured - Then click
Create GitHub App
- Server
--addr
: Server address and port to listen webhook. e.g.0.0.0.0:8080
--webhook-secret
: Webhook secret
- Policy (either one of
--local-policy
and--remote-url
is required)--local-policy
: Policy files or directory.--local-package
: Package name of policy file--remote-url
: URL of OPA server--remote-header
: HTTP header to query OPA server
- Notification (either one of following is required)
--slack-api-token
: API token retrieved in Step 1 (Recommended)--slack-webhook
: Incoming webhook URL of Slack
Apache License 2.0