Skip to content

Commit 459bbcf

Browse files
committed
chore: New PR announcement GH Action.
Add a new GH Action to announce to specific Slack channel every PR that is opened, reopened, and review_requested. Signed-off-by: Paulo Vital <paulo.vital@ibm.com>
1 parent 426d1d9 commit 459bbcf

2 files changed

Lines changed: 194 additions & 0 deletions

File tree

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#!/usr/bin/env python3
2+
"""
3+
GitHub Actions script to send Slack notifications for new pull requests.
4+
"""
5+
6+
import os
7+
import sys
8+
from typing import Tuple
9+
10+
import httpx
11+
12+
13+
def send_slack_message(
14+
slack_team: str, slack_service: str, slack_token: str, message: str
15+
) -> bool:
16+
"""Send a message to Slack channel."""
17+
18+
url = (
19+
f"https://hooks.slack.com/services/T{slack_team}/B{slack_service}/{slack_token}"
20+
)
21+
22+
headers = {
23+
"Content-Type": "application/json",
24+
}
25+
26+
data = {"text": message}
27+
28+
try:
29+
with httpx.Client() as client:
30+
response = client.post(url, headers=headers, json=data)
31+
response.raise_for_status()
32+
33+
result = response.text
34+
if "ok" in result:
35+
print("✅ Slack message sent successfully")
36+
return True
37+
else:
38+
print(f"❌ Slack API error: {result}")
39+
return False
40+
41+
except httpx.HTTPError as e:
42+
print(f"❌ Request error: {e}")
43+
return False
44+
45+
46+
def ensure_environment_variables_are_present() -> (
47+
Tuple[str, str, str, str, str, str, str, str]
48+
):
49+
"""
50+
Ensures that all necessary environment variables are present for the application to run.
51+
52+
This function checks for the presence of required environment variables related to Slack bot token,
53+
Pull Request (PR) details, and repository name. It also validates that the Slack channel is set.
54+
55+
Raises:
56+
SystemExit: If any of the required environment variables are missing.
57+
58+
Returns:
59+
A tuple containing the values of the following environment variables:
60+
- SLACK_TOKEN: The token for the Slack bot.
61+
- SLACK_TEAM: The ID of the Slack team.
62+
- SLACK_SERVICE: The ID of the Slack service.
63+
- PR_NUMBER: The number of the Pull Request.
64+
- PR_TITLE: The title of the Pull Request.
65+
- PR_URL: The URL of the Pull Request.
66+
- PR_AUTHOR: The author of the Pull Request.
67+
- REPO_NAME: The name of the repository.
68+
"""
69+
# Get environment variables
70+
slack_token = os.getenv("SLACK_TOKEN")
71+
slack_team = os.getenv("SLACK_TEAM")
72+
slack_service = os.getenv("SLACK_SERVICE")
73+
pr_number = os.getenv("PR_NUMBER")
74+
pr_title = os.getenv("PR_TITLE")
75+
pr_url = os.getenv("PR_URL")
76+
pr_author = os.getenv("PR_AUTHOR")
77+
repo_name = os.getenv("REPO_NAME")
78+
79+
# Validate required environment variables
80+
if not slack_token:
81+
print("❌ SLACK_TOKEN environment variable is required")
82+
sys.exit(1)
83+
84+
if not slack_team:
85+
print("❌ SLACK_TEAM environment variable is required")
86+
sys.exit(1)
87+
88+
if not slack_service:
89+
print("❌ SLACK_SERVICE environment variable is required")
90+
sys.exit(1)
91+
92+
if not all([pr_number, pr_title, pr_url, pr_author, repo_name]):
93+
print(
94+
"❌ Missing required PR information (PR_NUMBER, PR_TITLE, PR_URL, PR_AUTHOR, REPO_NAME)"
95+
)
96+
sys.exit(1)
97+
98+
# Since we're validating these variables, we can assert they're not None
99+
assert pr_number is not None
100+
assert pr_title is not None
101+
assert pr_url is not None
102+
assert pr_author is not None
103+
assert repo_name is not None
104+
105+
return (
106+
slack_token,
107+
slack_team,
108+
slack_service,
109+
pr_number,
110+
pr_title,
111+
pr_url,
112+
pr_author,
113+
repo_name,
114+
)
115+
116+
117+
def main() -> None:
118+
"""Main function to process PR and send Slack notification."""
119+
120+
(
121+
slack_token,
122+
slack_team,
123+
slack_service,
124+
pr_number,
125+
pr_title,
126+
pr_url,
127+
pr_author,
128+
repo_name,
129+
) = ensure_environment_variables_are_present()
130+
131+
print(f"Processing PR #{pr_number}")
132+
133+
# Create Slack message
134+
message = (
135+
f":mega: Oyez! Oyez! Oyez!\n"
136+
f"Hello Team. Please, review the opened PR #{pr_number} in {repo_name}\n"
137+
f"*{pr_title}* by @{pr_author}\n"
138+
f":pull-request-opened: {pr_url}"
139+
)
140+
141+
# Send to Slack
142+
success = send_slack_message(slack_service, slack_team, slack_token, message)
143+
144+
if not success:
145+
sys.exit(1)
146+
147+
print("✅ Process completed successfully")
148+
149+
150+
if __name__ == "__main__":
151+
main()
152+
153+
# Made with Bob
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: PR Slack Notification
2+
3+
permissions:
4+
contents: read
5+
pull-requests: read
6+
7+
on:
8+
pull_request:
9+
types: [opened, reopened, review_requested]
10+
11+
jobs:
12+
notify-slack:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0 # Fetch all history to access commit messages
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v4
23+
with:
24+
python-version: '3.13'
25+
26+
- name: Install dependencies
27+
run: |
28+
pip install httpx
29+
30+
- name: Send Slack notification
31+
env:
32+
SLACK_TOKEN: ${{ secrets.RUPY_PR_ANNOUNCEMENT_TOKEN }}
33+
SLACK_SERVICE: ${{ secrets.RUPY_PR_ANNOUNCEMENT_CHANNEL_ID }}
34+
SLACK_TEAM: ${{ secrets.RUPY_TOWN_CRIER_SERVICE_ID }}
35+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36+
PR_NUMBER: ${{ github.event.number }}
37+
PR_TITLE: ${{ github.event.pull_request.title }}
38+
PR_URL: ${{ github.event.pull_request.html_url }}
39+
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
40+
REPO_NAME: ${{ github.repository }}
41+
run: python .github/scripts/announce_pr_on_slack.py

0 commit comments

Comments
 (0)