A Slackbot for GitHub monorepos. Configure how repo notifications should be routed to specified Slack channels based on file prefixes, issue/PR labels, and CI build statuses.
Check out the accompanying blog post for an overview of Monorobot.
Install via OPAM:
opam install monorobot
Or install dependencies and build locally:
opam install --deps-only .
make
Run the _build/default/src/monorobot.exe
binary. The following commands are supported.
run
: Launch the HTTP servercheck_gh <GH_PAYLOAD>
: read a Github notification from a file and display the actions that will be taken (used for testing)check_slack <SLACK_PAYLOAD>
: read a Slack notification from a file and send it to a channel (used for testing)
- Commit a repository configuration file to the root of your target repository.
- Place a secrets file locally on the server.
- Configure GitHub
- If targeting a private repository, set up a personal access token with
repo
scope and store it in thegh_token
field of the secrets file. To use the "Project Owners" feature, the token owner must have triage role or above for the repository. - Create a webhook for the repository you are targeting. Set the Payload URL to be
<server_domain>/github
. - You can optionally secure the webhook with a token (e.g. use
head -c 30 /dev/urandom | base64
), and store it in thegh_hook_secret
field of the secrets file.
- If targeting a private repository, set up a personal access token with
- Configure Slack
- Create a Slack app.
- Click "Install to Workspace", and when prompted to grant permissions to your workspace, click "Allow".
- Set up notifications with one of the following methods:
- Web API (recommended): To use Slack's Web API, click on "OAuth & Permissions" in your app dashboard's sidebar. Give your bot a Bot Token Scope of
chat:write
(for per-channel authorization) orchat:write.public
(for authorization to all channels). Also givechat:write.customize
(to show branch name as bot username). If you want to send direct messages, also add theusers:read.email
scope, whichis necessary to find the user id matching the email of a commit author. Copy the generated bot token (xoxb-XXXX
) to theslack_access_token
field of your secrets file. This token is used by the bot to authenticate to the workspace, and remains valid until the token is revoked or the app is uninstalled. If you use thechat:write
scope, add the bot to each channel you want to notify. - Incoming Webhooks: To use incoming webhooks, enable them in your app dashboard and create one for each channel you want to notify. Store them in the
slack_hooks
field of your secrets file. If you decide to notify additional channels later, you will need to update the secrets file with the new webhooks and restart the server.
- Web API (recommended): To use Slack's Web API, click on "OAuth & Permissions" in your app dashboard's sidebar. Give your bot a Bot Token Scope of
You can configure Monorobot to unfurl GitHub links in Slack messages. Currently, commit, pull request, and issue links are supported.
Note: The slack_access_token
must be configured in your secrets file for link unfurling. See previous section for details.
- Give your app
links:read
andlinks:write
permissions. - Configure your app to support the Events API. During the url verification handshake, you should tell Slack to direct event notifications to
<server_domain>/slack/events
. Ensure the server is running before triggering the handshake. - Register the GitHub domains you want to support.
Monorobot will also try to match mentioned GitHub handles (e.g., in PR/issue/commit comments) to Slack emails. Where there is a match between canonicalised GitHub handle and canonicalised Slack email, the GitHub mention in Monorobot's notification will be replaced with a Slack mention. This feature requires slack_access_token
to be configured, and your app must also have the users:read
permission. See the previous section for how to set this up.
If your canonicalised GitHub handle is different from your canonicalised Slack email, or if you want to override this default matching scheme, you can create a manual mapping in your repository configuration under the user_mappings
option. See the documentation for details.
When a pipelinel is configured with a failed builds channel, Monorobot will send notifications to that Slack channel when a build fails for the main branch in the configured pipeline. This notification will mention the commit author and the build steps broken by the commit. This is useful for tracking the status of builds in Slack, and for getting notifications when a build fails.
Currently, this feature is only supported for Buildkite builds.
The logic is as follows:
- We receive a notification from GitHub for each step in the CI build lifecycle, including both individual steps and the entire build. We maintain a log of failed builds and failed steps for each build.
- When a notification for a failed build is received, we evaluate the failures by reviewing that build's history and compare it with the previous builds.
- We identify which steps were newly broken by the current build, i.e, did not fail in previous builds. We assume that previous builds still running will succeed while we haven't received a notifications for failed steps, so we treat any newly broken steps in the current build as broken by the current build.
- If there are newly broken steps, we notify the configured failed builds channel, including the commit author's name and the broken steps.
- If no steps were newly broken in the current build, we do not send a notification.
- In summary, only additional breakages are notified and notifications are sent as the builds finish. This means that they are not necessarily sent in the same order as the builds were started.
Some examples:
- Build #1 breaks steps
a
andb
, build #2 then breaks stepsa
andc
.- This will notifify the channel for build #1 regarding the steps
a
andb
, and for build #2 regarding the stepc
.
- This will notifify the channel for build #1 regarding the steps
- Build #1 breaks steps
a
andb
, build #2 breaks stepa
andc
, build #3 breaks stepa
andb
.- Similar as above, but we assume build #2 fixed step
b
and build #3 broke it again. So we notify the channel like above for the first two builds, and for build #3 regarding the stepb
only.
- Similar as above, but we assume build #2 fixed step
- Build #1 is running for a long time, breaks step
a
in the process and we get the notification (with which we update the builds state), build #2 breaks stepa
andb
. Build #2 finishes before build #1.- Will notify the channel for build #2 regarding step
b
. Then build #1 finishes and we notify the channel for the steps that build #1 newly broke. - Edge case: if by the time build #2 finishes we didn't receive any notification for a failed step in build #1, we will notify the channel for build #2 for the steps
a
andb
, and then again for build #1.
- Will notify the channel for build #2 regarding step
Commit a configuration file to the root of each repository you want to support, and add a secrets file on the bot server itself. Read on for instructions to set up each file:
curl -X POST \
http://localhost:8080/github \
-H 'Content-Type: application/json' \
-H 'User-Agent: {whatever user agent you define}' \
-H 'X-Github-Event: pull_request' \
-H 'X-Hub-Signature: {a signature value you define}' \
-H 'cache-control: no-cache' \
-d @mock_payloads/pr_notification.json
There are more payloads which will use a different X-Github-Event
signature:
pull_request => mock_payloads/pr_notification.json
push => mock_payloads/push_notification.json
check_suite => mock_payloads/ci_notification.json