11# This workflow will post to Slack when a PR is labeled with "notify-slack".
2- # Additionally, it will notify the appropriate reviewers based on the current UTC hour.
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 uses the rtCamp/action-slack-notify action to send messages to Slack.
7+ # The workflow is designed to be efficient and secure, ensuring that sensitive information is handled properly.
8+
39
410name : Ready for Review
511
814 types : [labeled]
915
1016permissions :
11- pull-requests : write # Needed to read/write PR comments
17+ pull-requests : write
1218
1319concurrency :
1420 group : readyforreviewci-${{ github.ref }}
1521 cancel-in-progress : true
1622
1723jobs :
18- notify-slack :
19- if : contains(github.event.pull_request.labels.*.name, 'notify-slack') # Only run if the PR is labeled with "notify-slack"
24+ notify-slack : # Notify Slack when PR is labeled with "notify-slack"
25+ if : contains(github.event.pull_request.labels.*.name, 'notify-slack')
2026 runs-on : ubuntu-latest
2127
22- env :
23- SLACK_USER_BEN : ${{ secrets.SLACK_USER_BEN }} # add users to GitHub Secrets and then reference them here.
24- SLACK_USER_ADELINA : ${{ secrets.SLACK_USER_ADELINA }}
25- SLACK_USER_LINUS : ${{ secrets.SLACK_USER_LINUS }}
26- SLACK_USER_AMANDA : ${{ secrets.SLACK_USER_AMANDA }}
27- SLACK_USER_CAROLINA : ${{ secrets.SLACK_USER_CAROLINA }}
28- SLACK_USER_LENNY : ${{ secrets.SLACK_USER_LENNY }}
29- SLACK_USER_SVETA : ${{ secrets.SLACK_USER_SVETA }}
30-
3128 steps :
32- - name : Check for prior Slack notification comment # This step checks if the PR has already been notified in Slack to avoid duplicate notifications.
29+ - name : Check for prior Slack notification comment # Avoid duplicate notifications
3330 id : check
3431 run : |
3532 COMMENTS=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
3633 https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments)
37- echo "$COMMENTS" | grep -q "<!-- slack-notified -->" && echo "notified=true" >> $GITHUB_OUTPUT || echo "notified=false" >> $GITHUB_OUTPUT
3834
39-
35+ echo "$COMMENTS" | grep -q "<!-- slack-notified -->"
36+ if [ $? -eq 0 ]; then
37+ echo "Slack already notified."
38+ echo "notified=true" >> $GITHUB_OUTPUT
39+ exit 0
40+ else
41+ echo "notified=false" >> $GITHUB_OUTPUT
42+ fi
43+
4044 - name : Exit if already notified
4145 if : steps.check.outputs.notified == 'true'
42- run : echo "Slack already notified. Exiting." # Script should exit here if already notified.
46+ run : |
47+ echo "Workflow stopping because Slack was already notified."
48+ exit 0 # Exit early to avoid unnecessary steps
4349
44- - name : Get Current UTC Hour
45- id : time
46- run : echo "hour=$(date -u +'%H')" >> $GITHUB_OUTPUT
50+ - name : Decode reviewer config (Base64)
51+ id : config
52+ run : |
53+ echo "${{ secrets.REVIEWER_CONFIG_B64 }}" | base64 -d > reviewers.json
4754
48- - name : Choose Reviewers Based on Time
55+ - name : Choose Reviewers From Config # Select reviewers from GitHub Action Secret REVIEWER_CONFIG_B64 based on current UTC hour
4956 id : pick
5057 run : |
51- HOUR=${{ steps.time.outputs.hour }}
58+ HOUR=$(date -u +'%H')
59+ echo "Current UTC Hour: $HOUR"
5260 REVIEWERS=""
5361
54- if [ "$HOUR" -ge 7 ] && [ "$HOUR" -lt 15 ]; then
55- REVIEWERS+="<@$SLACK_USER_BEN> "
56- fi
57- if [ "$HOUR" -ge 10 ] && [ "$HOUR" -lt 18 ]; then
58- REVIEWERS+="<@$SLACK_USER_ADELINA> "
59- fi
60- if [ "$HOUR" -ge 11 ] && [ "$HOUR" -lt 19 ]; then
61- REVIEWERS+="<@$SLACK_USER_LINUS> "
62- fi
63- if [ "$HOUR" -ge 12 ] && [ "$HOUR" -lt 20 ]; then
64- REVIEWERS+="<@$SLACK_USER_AMANDA> "
65- fi
66- if [ "$HOUR" -ge 12 ] && [ "$HOUR" -lt 21 ]; then
67- REVIEWERS+="<@$SLACK_USER_CAROLINA> "
68- fi
69- if [ "$HOUR" -ge 15 ] && [ "$HOUR" -lt 22 ]; then
70- REVIEWERS+="<@$SLACK_USER_LENNY> <@$SLACK_USER_SVETA>"
71- fi
62+ for reviewer in $(jq -r 'keys[]' reviewers.json); do
63+ START=$(jq -r ".\"$reviewer\".start" reviewers.json)
64+ END=$(jq -r ".\"$reviewer\".end" reviewers.json)
65+ SLACK_ID=$(jq -r ".\"$reviewer\".slack_id" reviewers.json)
7266
67+ if [ "$HOUR" -ge "$START" ] && [ "$HOUR" -lt "$END" ]; then
68+ REVIEWERS+="<@$SLACK_ID> "
69+ fi
70+ done
71+
72+ # Output reviewers without printing to logs
7373 echo "reviewers=$REVIEWERS" >> $GITHUB_OUTPUT
7474
7575 - name : Notify Slack
7676 uses : rtCamp/action-slack-notify@v2.3.3
7777 env :
78- SLACK_WEBHOOK : ${{ secrets.SLACK_PRIVATE_TEAM_WEBHOOK }}
78+ SLACK_WEBHOOK : ${{ secrets.SLACK_PRIVATE_TEAM_TEST_WEBHOOK }}
7979 SLACK_USERNAME : " spectromate"
8080 SLACK_ICON_EMOJI : " :robot_panic:"
8181 SLACK_COLOR : " #A020F0"
8282 SLACK_MESSAGE : |
83- :review: *<${{ github.event.pull_request.html_url }}|${{ github.event.pull_request.title }}>* is ready for review!
83+ :review: *<${{ github.event.pull_request.html_url }}|${{ github.event.pull_request.title }}>* is ready for review! :review:
8484 Pinging: ${{ steps.pick.outputs.reviewers }}
85-
86- - name : Record Slack notification via comment # This step adds a comment to the PR to indicate that Slack has been notified.
87- if : steps.check.outputs.notified == 'false'
85+
86+ - name : Record Slack notification as PR comment
8887 run : |
89- curl -s -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
88+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
89+ curl -s -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
9090 -H "Accept: application/vnd.github.v3+json" \
91- -d "{\"body\":\"✅ Slack reviewers have been notified: ${{ steps.pick.outputs.reviewers }}\"}" \
92- https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments
91+ -d "{\"body\":\"✅ Slack reviewers notified at $TIMESTAMP\n${{ steps.pick.outputs.reviewers }}\n<!-- slack-notified -->\"}" \
92+ https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments
93+
94+ - name : Securely overwrite and delete reviewers.json # Shred the reviewers.json file to ensure sensitive data is not left behind
95+ if : always()
96+ run : |
97+ if [ -f reviewers.json ]; then
98+ echo "Shredding reviewers.json"
99+ dd if=/dev/urandom of=reviewers.json bs=1 count=$(stat -c%s reviewers.json) conv=notrunc status=none
100+ rm -f reviewers.json
101+ echo "Secure deletion complete."
102+ else
103+ echo "No reviewers.json file to delete."
104+ fi
0 commit comments