Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: Add a slack notifier workflow #18

Merged
merged 5 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions .github/workflows/slack-notifier.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
name: Post comments on slack, with rate limiting.
on:
workflow_call:
secrets:
GITHUB_PAT:
description: 'The github token used to read the timeout variable.'
required: true
SLACK_BOT_TOKEN:
description: 'The slack API token, with `chat:write` permissions.'
required: true
inputs:
channel-id:
description: 'The channel ID to send the message to.'
required: true
type: string
slack-message:
description: 'The message to send to slack.'
required: true
type: string
timeout-variable:
description: 'A repository variable used to store the last message timestamp.'
required: true
type: string
timeout-minutes:
description: 'The minimum time to wait before sending the message again, in minutes.'
required: false
type: string
# Default to 24 hours
default: '1440'
outputs:
sent:
description: 'Whether the message was sent. Returns false if we are waiting for a timeout.'
value: ${{ jobs.notify-slack.outputs.sent }}

jobs:
notify-slack:
runs-on: ubuntu-latest
outputs:
sent: ${{ steps.rate-limit.outputs.send }}
steps:
- name: Check last message timestamp
id: last-sent
run: |
set +e
gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/$OWNER/$REPO/actions/variables/$VAR \
> read-variable.json
if [ $? -ne 0 ]
then
echo "Could not read the variable."
echo "missing=true" >> $GITHUB_OUTPUT
else
jq -r '.value' read-variable.json > last-sent.txt
echo "missing=false" >> $GITHUB_OUTPUT
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_PAT }}
OWNER: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}
VAR: ${{ inputs.timeout-variable }}

- name: Create the timestamp variable if it's missing
if: ${{ steps.last-sent.outputs.missing == 'true' }}
run: |
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/$OWNER/$REPO/actions/variables \
-f "name=$VAR" -f "value=1990-01-01T00:00:00Z"
env:
GH_TOKEN: ${{ secrets.GITHUB_PAT }}
OWNER: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}
VAR: ${{ inputs.timeout-variable }}

- name: Rate limit
id: rate-limit
run: |
# Check if the last message was sent within the timeout
echo "Preparing to send message:"
echo
echo "\"$MESSAGE\""
echo

if [ -f last-sent.txt ]
then
LAST_SENT=$( cat last-sent.txt )
NOW=$( date +'%FT%TZ' )
echo "Last sent: $LAST_SENT"
echo "Now: $NOW"

DIFF_MINUTES=$(( ( $( date -d "$NOW" +%s ) - $( date -d "$LAST_SENT" +%s ) ) / 60 ))
echo "Timeout: $TIMEOUT mins"
echo "Difference: $DIFF_MINUTES mins"

if [ $DIFF_MINUTES -lt $TIMEOUT ]
then
echo "On timeout period. Not sending the message."
echo "send=false" >> "$GITHUB_OUTPUT"
exit 0
fi
else
echo "Last-sent variable was not set."
fi
echo "send=true" >> "$GITHUB_OUTPUT"
date +%s > last-sent.txt
env:
TIMEOUT: ${{ inputs.timeout-minutes }}
MESSAGE: ${{ inputs.slack-message }}

- name: Send notification
if: ${{ steps.rate-limit.outputs.send == 'true' }}
uses: slackapi/[email protected]
with:
channel-id: ${{ inputs.channel-id }}
slack-message: ${{ inputs.slack-message }}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

- name: Modify the variable to save the new timestamp
if: ${{ steps.rate-limit.outputs.send == 'true' }}
run: |
gh api \
--method PATCH \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/$OWNER/$REPO/actions/variables/$VAR \
-f "name=$VAR" -f "value=$( date +'%FT%TZ' )"
env:
GH_TOKEN: ${{ secrets.GITHUB_PAT }}
OWNER: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}
VAR: ${{ inputs.timeout-variable }}
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The following workflows are available:
- [`drop-cache`](#drop-cache): Drops the cache for a branch when a pull request is closed.
- [`pr-title`](#pr-title): Checks the title of pull requests to ensure they follow the conventional commits format.
- [`rs-semver-checks`](#rs-semver-checks): Runs `cargo-semver-checks` on a PR against the base branch, and reports back if there are breaking changes.
- [`slack-notifier`](#slack-notifier): Post comments on slack, with a rate limit to avoid spamming the channel.

## [`add-to-project`](https://github.com/CQCL/hugrverse-actions/blob/main/.github/workflows/add-to-project.yml)

Expand Down Expand Up @@ -184,3 +185,58 @@ The fine-grained `GITHUB_PAT` secret must include the following permissions:
| --- | --- |
| Pull requests | Read and write |


## [`slack-notifier`](https://github.com/CQCL/hugrverse-actions/blob/main/.github/workflows/slack-notifier.yml)

Post comments on slack using
[slackapi/slack-github-action](https://github.com/slackapi/slack-github-action),
adding a rate limit to avoid spamming the channel.

### Usage
```yaml
name: Send a slack message
on:
pull_request:
branches:
- main

jobs:
message-slack:
uses: CQCL/hugrverse-actions/.github/workflows/slack-notifier.yml@main
with:
channel-id: "SOME CHANNEL ID"
slack-message: "Hello 🌎!"
# A minimum time in minutes to wait before sending another message.
timeout-minutes: 60
# A repository variable used to store the last message timestamp.
timeout-variable: "HELLO_MESSAGE_TIMESTAMP"
secrets:
GITHUB_PAT: ${{ secrets.GITHUB_PAT }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
```

### Inputs

- `channel-id`: The ID of the channel to post the message to. (**required**)
- `slack-message`: The message to post. (**required**)
- `timeout-variable`: A repository variable used to store the last message timestamp. (**required**)
- `timeout-minutes`: A minimum time in minutes to wait before sending another message. Defaults to 24 hours.

### Outputs

- `sent`: A boolean indicating if the message was sent.

### Token Permissions

`SLACK_BOT_TOKEN` is a token generated by Slack with `chat:write` access to the
channel. See the
[slackapi/slack-github-action](https://github.com/slackapi/slack-github-action?tab=readme-ov-file#technique-2-slack-app)
documentation for more information.
If you are using a slack app, make sure to add it to the channel.
See formatting options in the [Slack API documentation](https://api.slack.com/reference/surfaces/formatting).

The fine-grained `GITHUB_PAT` secret must include the following permissions:

| Permission | Access |
| --- | --- |
| Variables (repository) | Read and write |