Giter VIP home page Giter VIP logo

ghnotify's Introduction

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

ghnotify's People

Contributors

m-mizutani avatar rindrics avatar

Stargazers

 avatar  avatar Mike Keller avatar JJ (yuasa) avatar atsushi, sada avatar shim avatar  avatar Dave Hall avatar Anderson Carvalho avatar huuya avatar Masanori Ogino avatar sheepla avatar Masaki ISHIYAMA avatar zbv avatar Ryota Yoshikawa avatar Malena Ebert avatar Shuya Motouchi avatar Ryan Parman avatar otokunaga avatar Takuya Kosugiyama avatar Anders Eknert avatar

Watchers

 avatar James Cloos avatar  avatar

ghnotify's Issues

Want to monitor service status

Background

Until I set up ghnotify, I encountered several HTTP errors such as 404 and 500

What I want

It would be useful to monitor the status code and time required for ghnotify responses


I tried to resolve this by #13

Runtime error when `bool` type value is passed to `NotifyField.notify.fields.value`

What occurs

: fail to unmarshal OPA server result to out: json: cannot unmarshal bool into Go struct field NotifyField.notify.fields.value of type string

It occurs when

POSTing JSON body below while testing https://github.com/m-mizutani/ghnotify/blob/main/examples/policy/new_deploy_key.rego :

{
    "action": "created",
    "key": {
        "title": "key-title",
        "read_only": true
    }
}

What to expect

ghnotify should accept bool type value value for NotifyField.notify.fields.value because The field key.read_only of deploy_key event is defined as bool (c.f. https://docs.github.com/en/webhooks-and-events/webhooks/webhook-events-and-payloads#deploy_key )

I will resolved this by #10

`server` fails with runtime error when setting logging parameters via environmental variables

relevant version: v0.1.3

What occurs

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x69d098]

goroutine 1 [running]:
github.com/urfave/cli/v2.(*GenericFlag).Apply(0x4000348340, 0xce0730?)
	/go/pkg/mod/github.com/urfave/cli/[email protected]/flag_generic.go:77 +0xf8
github.com/urfave/cli/v2.flagSet({0xb4d266, 0x8}, {0x40005cd2c0, 0xb, 0x18?}, {{0x0?, 0x400014c2a0?}, 0x0?, 0x0?})
	/go/pkg/mod/github.com/urfave/cli/[email protected]/flag.go:177 +0x150
github.com/urfave/cli/v2.(*Command).newFlagSet(...)
	/go/pkg/mod/github.com/urfave/cli/[email protected]/command.go:281
github.com/urfave/cli/v2.(*Command).parseFlags(0x40003cb600, {0xce2638, 0x400014c2a0}, 0xa0?)
	/go/pkg/mod/github.com/urfave/cli/[email protected]/command.go:314 +0x60
github.com/urfave/cli/v2.(*Command).Run(0x40003cb600, 0x4000548ac0, {0x4000030080, 0x4, 0x4})
	/go/pkg/mod/github.com/urfave/cli/[email protected]/command.go:155 +0xa8
github.com/urfave/cli/v2.(*App).RunContext(0x4000028000, {0xce03b0?, 0x400003e020}, {0x4000030080, 0x4, 0x4})
	/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:332 +0x568
github.com/urfave/cli/v2.(*App).Run(...)
	/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:309
github.com/m-mizutani/ghnotify/pkg/controller/cmd.Run({0x4000030080, 0x4, 0x4})
	/src/pkg/controller/cmd/cli.go:204 +0xcb4
main.main()
	/src/main.go:10 +0x34

When it occurs

part of my docker-compose.yml:

version: '3'
services:
  ghnotify:
    image: ghcr.io/m-mizutani/ghnotify:v0.1.3
    command:
      - --remote-url
      - http://opa_server:8181/v1/data/github/notify
      - serve
    env_file:
      - .env
    environment:
      - GHNOTIFY_ADDR=0.0.0.0:80
      - GHNOTIFY_WEBHOOK_SECRET=my-dummy-secret
      - GHNOTIFY_LOG_LEVEL=debug                    # set log-level from environmental variable
    ports:
      - 4080:80
    networks:
      - my_network
  opa_server
    ...

Note

Endpoint for health checking?

  • what I need: an endpoint for health checking of ghnotify
  • why I need it:
    • I need to specify health-checking endpoint when I deploy ghnotify to container hosting services (e.g. ECS on AWS)
    • As a workaround, I've been using GET / request and 404 Not found response for health checking
  • expectation:
    • I expect the new health-checking endpoint to return 2XX response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.