failures: the run’s policy findings, aterrorlevel by default, on the pull request, issue or repository the run was about.stale: what the stale feature changed in a sweep: items it marked, unmarked, abandoned or closed.
- Slack, through an incoming webhook.
- Discord, through a channel webhook.
- Linear, where each notification opens an issue in a team.
Turn it on
1
Get the channel's secret
- Slack: create an incoming webhook for the channel and copy its URL.
- Discord: in the channel’s settings, open Integrations > Webhooks, create a webhook and copy its URL.
- Linear: create a personal API key that can create issues in the team, and copy the id (a UUID) of the team issues should go to. Label ids are UUIDs too.
2
Store it as an Actions secret
In the repository or organisation, open Settings > Secrets and variables > Actions and add the secret, for example
SLACK_WEBHOOK_URL. Never put it in the config file: anyone who can read the repository can read that.3
Pass it to smartcloud as an environment variable
.github/workflows/smartcloud.yml
4
Add a channel
.github/smartcloud.yml
maintainers) is a name of your choosing; type says where it sends. Send yourself a test by running a feature that finds an error, or preview with a dry run, which lists the notifications it would have sent.Options
notifications.channels maps a name of your choosing to a channel.
secret is only needed when two channels of the same type need different secrets, or your secret has another name:
Complete example
.github/smartcloud.yml
.github/workflows/smartcloud.yml
How it works
After every run, once the check runs and the report comment are published, smartcloud looks at each channel:- It works out which kinds (
on) the run has something to say about. Afailuresnotification needs at least one finding atlevelor above; astaleone needs at least one change the stale feature made. - It reads the channel’s secret from its environment variable. When the variable is unset or empty, the channel is skipped with a warning.
- It sends the notification. Channels are sent to in parallel; one that fails or does not answer within 15 seconds is recorded as a warning, and the others are still sent to.
What you will see
- Slack: a message titled, for example, “2 policy failures on pull request #42 in my-org/app”, linked to the pull request, issue or repository, with one bullet per finding (
error DCO: ...) or change. Text is escaped, so a title cannot mention@channelor inject a link. - Discord: one embed with the same content. Mentions are switched off, so a title cannot ping
@everyone. - Linear: a new issue in
team, titled like the message, whose description lists the findings or changes and links back to GitHub.
notifications: failures not sent on maintainers: SLACK_WEBHOOK_URL is not set.
Forks and restricted runs
GitHub passes no secrets to a pull request from a fork, or to Dependabot’s runs, so every channel’s variable is empty there. Each channel is skipped with a warning, and the run carries on and never fails because of it. Scheduled runs, which carry stale changes, always have their secrets.Troubleshooting
notifications: failures not sent on <channel>: SLACK_WEBHOOK_URL is not set
notifications: failures not sent on <channel>: SLACK_WEBHOOK_URL is not set
The environment variable the channel reads is missing or empty. Pass the secret in the workflow step’s
env, with
the name the channel’s secret gives (or the default for its type). On a fork’s pull request this is expected.slack: no answer within 15s
slack: no answer within 15s
The service did not answer in time. The notification is dropped for this run; the next run with something to say
sends again.
Nothing is sent although the check failed
Nothing is sent although the check failed
Check the channel’s
on includes failures, and its level: with the default error, warnings are not sent. A
pull request whose report comment has not changed since the last run is not notified again.Linear rejects the request
Linear rejects the request
The API key must be able to create issues in
team, and team and labels must be ids, not names.Adding a channel
Channels live inpackages/notifications and share one interface, so adding one takes three steps:
- Add the channel’s options to the
NotificationChannelunion inpackages/config/src/sections.ts, with atypeliteral, the shared fields (secret,on,level) and any of its own. - Implement a
Channelinpackages/notifications/src/channels/: itstype, thedefaultSecretvariable, andsend, which delivers oneNotificationthrough the HTTP client and fails with aChannelError. - List it in
defaultChannelsinpackages/notifications/src/registry.ts. The registry’s type has a key for everytypein the union, so the compiler points at a channel that is configured but not implemented.