Skip to content

Commit 7b793c9

Browse files
doc-2075: Updating the notify-slack github action script to ping people during their working hours. (#7592)
* doc-2075: adding everyone & times online * doc-2075: added option to avoid duplicate postings * doc-2075: added option to record comment in PR that it has been posted to Slack to avoid duplication & so GH is aware (otherwise may still duplicate) * doc-2075: add comments to clarify what some sections are doing if not clear * doc-2075: added text to github comment * doc-2075: moved users to base64 secret, added explicit exit and explicit secret cleanup * doc-2075: typo fix * doc-2075: added option to allow script to continue but skip remaining steps to avoid failure * doc-2075: clean up typos * Doc 2075 gha call users subbranch (#7644) * doc-2075: testing changes * doc-2075: fixed grep conditional * doc-2075: added Mon-Fri, added option to post @here when no one is on and update to comment * chore(ci): trigger CI again
1 parent 91586d8 commit 7b793c9

File tree

1 file changed

+110
-6
lines changed

1 file changed

+110
-6
lines changed
Lines changed: 110 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
# This workflow is triggered on a pull request labeled with 'notify-slack'. It sends a Slack notification
2-
# to alert the team that a PR is ready for review.
1+
# This workflow will post to Slack when a PR is labeled with "notify-slack".
2+
# It will notify the appropriate reviewers based on the current UTC hour.
3+
# It also ensures that Slack is not notified multiple times for the same PR.
4+
# The reviewers are defined in a Base64 encoded JSON file stored in a GitHub secret.
5+
# After notifying, it records the notification in the PR comments and securely deletes the reviewers file.
6+
# The workflow is designed to be efficient and secure, ensuring that sensitive information is handled properly.
37

48
name: Ready for Review
59

@@ -8,7 +12,7 @@ on:
812
types: [labeled]
913

1014
permissions:
11-
pull-requests: read
15+
pull-requests: write
1216

1317
concurrency:
1418
group: readyforreviewci-${{ github.ref }}
@@ -17,16 +21,116 @@ concurrency:
1721
jobs:
1822
notify-slack:
1923
if: contains(github.event.pull_request.labels.*.name, 'notify-slack')
20-
2124
runs-on: ubuntu-latest
2225

2326
steps:
24-
- name: Send Slack Notification
27+
- name: Check for prior Slack notification comment
28+
id: check
29+
run: |
30+
COMMENTS=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
31+
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments)
32+
33+
COMMENT_ID=$(echo "$COMMENTS" | jq '.[] | select(.body | contains("<!-- slack-notified -->")) | .id')
34+
35+
if [ -n "$COMMENT_ID" ]; then
36+
echo "Slack already notified."
37+
echo "notified=true" >> $GITHUB_OUTPUT
38+
echo "comment_id=$COMMENT_ID" >> $GITHUB_OUTPUT
39+
else
40+
echo "notified=false" >> $GITHUB_OUTPUT
41+
fi
42+
43+
- name: Exit if already notified
44+
if: steps.check.outputs.notified == 'true'
45+
continue-on-error: true
46+
run: echo "Slack already notified — skipping remaining steps."
47+
48+
- name: Decode reviewer config (Base64)
49+
if: steps.check.outputs.notified == 'false'
50+
id: config
51+
run: |
52+
echo "${{ secrets.REVIEWER_CONFIG_B64 }}" | base64 -d > reviewers.json
53+
54+
- name: Choose Reviewers From Config
55+
if: steps.check.outputs.notified == 'false'
56+
id: pick
57+
run: |
58+
HOUR=$(date -u +'%H')
59+
DAY=$(date -u +%a | tr '[:upper:]' '[:lower:]')
60+
echo "UTC Hour: $HOUR | Day: $DAY"
61+
62+
REVIEWERS=""
63+
64+
for reviewer in $(jq -r 'keys[]' reviewers.json); do
65+
START=$(jq -r ".\"$reviewer\".start" reviewers.json)
66+
END=$(jq -r ".\"$reviewer\".end" reviewers.json)
67+
SLACK_ID=$(jq -r ".\"$reviewer\".slack_id" reviewers.json)
68+
69+
if jq -e ".\"$reviewer\".days" reviewers.json > /dev/null; then
70+
DAYS=$(jq -r ".\"$reviewer\".days[]" reviewers.json | tr '\n' ' ')
71+
[[ "$DAYS" != *"$DAY"* ]] && continue
72+
fi
73+
74+
if [ "$HOUR" -ge "$START" ] && [ "$HOUR" -lt "$END" ]; then
75+
REVIEWERS+="<@$SLACK_ID> "
76+
fi
77+
done
78+
79+
if [ -z "$REVIEWERS" ]; then
80+
REVIEWERS="<!here> _(No reviewers available — notifying team)_"
81+
fi
82+
83+
echo "reviewers=$REVIEWERS" >> $GITHUB_OUTPUT
84+
85+
- name: Notify Slack
86+
if: steps.check.outputs.notified == 'false'
2587
uses: rtCamp/action-slack-notify@v2.3.3
2688
env:
2789
SLACK_WEBHOOK: ${{ secrets.SLACK_PRIVATE_TEAM_WEBHOOK }}
2890
SLACK_USERNAME: "spectromate"
2991
SLACK_ICON_EMOJI: ":robot_panic:"
3092
SLACK_COLOR: "#A020F0"
3193
SLACK_MESSAGE: |
32-
:review: *<${{ github.event.pull_request.html_url }}|${{ github.event.pull_request.title }}>* is ready for review!
94+
:review: *<${{ github.event.pull_request.html_url }}|${{ github.event.pull_request.title }}>* is ready for review!
95+
Pinging: ${{ steps.pick.outputs.reviewers }}
96+
97+
- name: Create or Update Slack comment manually
98+
if: steps.check.outputs.notified == 'false'
99+
run: |
100+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
101+
BODY="✅ Slack reviewers notified at $TIMESTAMP\n${{ steps.pick.outputs.reviewers }}\n<!-- slack-notified -->"
102+
103+
if [ -n "${{ steps.check.outputs.comment_id }}" ]; then
104+
echo "Updating existing comment..."
105+
curl -s -X PATCH -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
106+
-H "Accept: application/vnd.github.v3+json" \
107+
-d "$(jq -nc --arg body "$BODY" '{body: $body}')" \
108+
https://api.github.com/repos/${{ github.repository }}/issues/comments/${{ steps.check.outputs.comment_id }}
109+
else
110+
echo "Creating new comment..."
111+
curl -s -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
112+
-H "Accept: application/vnd.github.v3+json" \
113+
-d "$(jq -nc --arg body "$BODY" '{body: $body}')" \
114+
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments
115+
fi
116+
117+
- name: Securely overwrite and delete reviewers.json
118+
if: always()
119+
run: |
120+
if [ -f reviewers.json ]; then
121+
echo "Shredding reviewers.json"
122+
dd if=/dev/urandom of=reviewers.json bs=1 count=$(stat -c%s reviewers.json) conv=notrunc status=none
123+
rm -f reviewers.json
124+
echo "Secure deletion complete."
125+
else
126+
echo "No reviewers.json file to delete."
127+
fi
128+
129+
- name: Final Job Status Summary
130+
if: always()
131+
run: |
132+
if [ "${{ steps.check.outputs.notified }}" == "true" ]; then
133+
echo "✅ Job completed: Slack was already notified (comment updated if needed)."
134+
else
135+
echo "✅ Job completed: Slack notification was posted successfully."
136+
fi

0 commit comments

Comments
 (0)