Skip to content

Commit c0732d1

Browse files
committed
Add slack alert
1 parent 37833b8 commit c0732d1

File tree

4 files changed

+151
-3
lines changed

4 files changed

+151
-3
lines changed

.github/workflows/daily.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ name: Daily Collection
22

33
on:
44
workflow_dispatch:
5+
inputs:
6+
slack_channel:
7+
description: Slack channel to post the error message to if the builds fail.
8+
required: false
9+
default: "sdv-alerts-debug"
510
schedule:
611
- cron: '0 0 * * *'
712

@@ -28,3 +33,22 @@ jobs:
2833
env:
2934
PYDRIVE_CREDENTIALS: ${{ secrets.PYDRIVE_CREDENTIALS }}
3035
BIGQUERY_CREDENTIALS: ${{ secrets.BIGQUERY_CREDENTIALS }}
36+
37+
alert:
38+
needs: [collect]
39+
runs-on: ubuntu-latest
40+
if: failure()
41+
steps:
42+
- uses: actions/checkout@v4
43+
- uses: actions/setup-python@v5
44+
with:
45+
python-version: '3.13'
46+
- name: Install slack dependencies
47+
run: |
48+
python -m pip install --upgrade pip
49+
python -m pip install invoke
50+
python -m pip install .[dev]
51+
- name: Slack alert if failure
52+
run: python -m github_analytics.slack_utils -r ${{ github.run_id }} -c ${{ github.event.inputs.slack_channel || 'sdv-alerts' }}
53+
env:
54+
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}

.github/workflows/dryrun.yaml

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
name: Health-check Dry Run
22

33
on:
4-
- workflow_dispatch
4+
- workflow_dispatch:
5+
inputs:
6+
slack_channel:
7+
description: Slack channel to post the error message to if the builds fail.
8+
required: false
9+
default: "sdv-alerts-debug"
10+
511
- push
612
- pull_request
713

814
jobs:
9-
collect:
15+
dry_run:
1016
runs-on: ubuntu-latest
1117
steps:
1218
- uses: actions/checkout@v4
@@ -29,3 +35,22 @@ jobs:
2935
env:
3036
PYDRIVE_CREDENTIALS: ${{ secrets.PYDRIVE_CREDENTIALS }}
3137
BIGQUERY_CREDENTIALS: ${{ secrets.BIGQUERY_CREDENTIALS }}
38+
39+
alert:
40+
needs: [dry_run]
41+
runs-on: ubuntu-latest
42+
if: failure()
43+
steps:
44+
- uses: actions/checkout@v4
45+
- uses: actions/setup-python@v5
46+
with:
47+
python-version: '3.13'
48+
- name: Install slack dependencies
49+
run: |
50+
python -m pip install --upgrade pip
51+
python -m pip install invoke
52+
python -m pip install .[dev]
53+
- name: Slack alert if failure
54+
run: python -m github_analytics.slack_utils -r ${{ github.run_id }} -c ${{ github.event.inputs.slack_channel || 'sdv-alerts' }}
55+
env:
56+
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}

download_analytics/slack_utils.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""Utility functions for Slack integration."""
2+
3+
import argparse
4+
import os
5+
6+
from slack_sdk import WebClient
7+
8+
GITHUB_URL_PREFIX = 'https://github.com/datacebo/download-analytics/actions/runs/'
9+
DEFAULT_SLACK_CHANNEL = 'sdv-alerts-debug'
10+
11+
12+
def _get_slack_client():
13+
"""Create an authenticated Slack client.
14+
15+
Returns:
16+
WebClient:
17+
An authenticated Slack WebClient instance.
18+
"""
19+
token = os.getenv('SLACK_TOKEN')
20+
client = WebClient(token=token)
21+
return client
22+
23+
24+
def post_slack_message(channel, text):
25+
"""Post a message to a Slack channel.
26+
27+
Args:
28+
channel (str):
29+
The name of the channel to post to.
30+
text (str):
31+
The message to send to the channel.
32+
33+
Returns:
34+
SlackResponse:
35+
Response from Slack API call
36+
"""
37+
client = _get_slack_client()
38+
response = client.chat_postMessage(channel=channel, text=text)
39+
if not response['ok']:
40+
error = response.get('error', 'unknown_error')
41+
msg = f'{error} occured trying to post message to {channel}'
42+
raise RuntimeError(msg)
43+
44+
return response
45+
46+
47+
def post_slack_message_in_thread(channel, text, thread_ts):
48+
"""Post a message as a threaded reply in a Slack channel.
49+
50+
Args:
51+
channel (str):
52+
The name of the channel to post to.
53+
text (str):
54+
The message to send as a reply in the thread.
55+
thread_ts (str):
56+
The timestamp of the message that starts the thread.
57+
58+
Returns:
59+
SlackResponse:
60+
Response from Slack API call.
61+
"""
62+
client = _get_slack_client()
63+
response = client.chat_postMessage(channel=channel, text=text, thread_ts=thread_ts)
64+
if not response['ok']:
65+
error = response.get('error', 'unknown_error')
66+
msg = f'{error} occurred trying to post threaded message to {channel}'
67+
raise RuntimeError(msg)
68+
69+
return response
70+
71+
72+
def send_alert(args):
73+
"""Send an alert message to a slack channel."""
74+
url = GITHUB_URL_PREFIX + args.run_id
75+
message = f'Download Analytics build failed :fire: :dumpster-fire: :fire: See errors <{url}|here>'
76+
post_slack_message(args.channel, message)
77+
78+
79+
def get_parser():
80+
"""Get the parser."""
81+
parser = argparse.ArgumentParser(description='Function to alert when a Github workflow fails.')
82+
parser.add_argument('-r', '--run-id', type=str, help='The id of the github run.')
83+
parser.add_argument(
84+
'-c',
85+
'--channel',
86+
type=str,
87+
help='The slack channel to post to.',
88+
default=DEFAULT_SLACK_CHANNEL,
89+
)
90+
parser.set_defaults(action=send_alert)
91+
92+
return parser
93+
94+
95+
if __name__ == '__main__':
96+
parser = get_parser()
97+
args = parser.parse_args()
98+
args.action(args)

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ include = ['download_analytics', 'download_analytics.*']
3737
[project.optional-dependencies]
3838
dev = [
3939
"ruff>=0.9.8",
40-
"invoke"
40+
"invoke",
41+
"slack-sdk>=3.34,<4.0",
4142
]
4243

4344
[tool.ruff]

0 commit comments

Comments
 (0)