Skip to content

General GitHub event notification tool to Slack with Open Policy Agent and Rego

License

Notifications You must be signed in to change notification settings

m-mizutani/ghnotify

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ghnotify

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

Setup

1) Retrieve Bot User OAuth Token of Slack

Create your Slack bot and keep OAuth Tokens for Your Workspace in OAuth & Permissions page.

2) Creating Rego policy

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 from X-GitHub-Event header.
  • input.event: Webhook events. See docs for more detail and schema.

Result: What data should be returned

  • notify: Set of notification messages
    • notify[_].channel: Destination channel of Slack. It can be used by only API token
    • notify[_].text: Custom message of slack notification
    • notify[_].body: Custom message body
    • notify[_].color: Message bar color
    • notify[_].fields: Set of custom message fields.
      • notify[_].fields[_].name: Field name
      • notify[_].fields[_].value: Field value
      • notify[_].fields[_].url: Link assigned to the field

Example 1) Notification of "call me" in issue comment

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.

Example 2) Notification of workflow (actions) failed

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
    }
}

Example 3) Assigned "breaking-change" label to PR

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),
            },
        ],
    }
}

Run

Use Case 1: As GitHub Actions

  • 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"

Use Case 2: As GitHub App server

  • Pros: Easy to install
  • Cons: GitHub Actions can receive event on each repository, can not watch organization wide

Deploy ghnotify

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.

Create a new GitHub App

  1. Go to https://github.com/settings/apps and click New GitHub App
  2. Grant permissions and check events you want to subscribe in Subscribe to events.
  3. Check Active in Webhook section
  4. Set URL of deployed ghnotify to Webhook URL
  5. Set Webhook secret to Webhook secret if you configured
  6. Then click Create GitHub App

Example

Options

  • 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

License

Apache License 2.0