-
Notifications
You must be signed in to change notification settings - Fork 0
147 lines (133 loc) · 6.24 KB
/
codeowners-approved-slack.yml
File metadata and controls
147 lines (133 loc) · 6.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
name: CODEOWNERS Approved - Slack Notification
on:
workflow_call:
inputs:
skip-draft:
description: "Skip notification for draft PRs"
required: false
type: boolean
default: true
require-full-approval:
description: "If true, only notify when reviewDecision is APPROVED. If false, notify on first approval."
required: false
type: boolean
default: true
slack-message-prefix:
description: "Custom prefix for Slack message (emoji + text)"
required: false
type: string
default: ":white_check_mark: CODEOWNERS gate satisfied"
secrets:
SLACK_RELEASE_CHANGELOG_WEBHOOK:
description: "Slack incoming webhook URL"
required: true
GH_TOKEN:
description: "GitHub token with PR read access (uses GITHUB_TOKEN if not provided)"
required: false
jobs:
notify:
name: Notify Slack on CODEOWNERS Approval
# Only run when the submitted review is an approval
if: github.event.review.state == 'approved'
runs-on: ubuntu-latest
steps:
- name: Fetch PR decision and check for duplicate notification
id: pr
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_TOKEN || github.token }}
script: |
const { owner, repo } = context.repo;
const prNumber = context.payload.pull_request.number;
const query = `query($owner:String!, $repo:String!, $number:Int!) {
repository(owner:$owner, name:$repo) {
pullRequest(number:$number) {
number
title
url
isDraft
headRefOid
baseRefName
reviewDecision
}
}
}`;
const data = await github.graphql(query, { owner, repo, number: prNumber });
const pr = data.repository.pullRequest;
core.setOutput("number", String(pr.number));
core.setOutput("title", pr.title);
core.setOutput("url", pr.url);
core.setOutput("is_draft", pr.isDraft ? "true" : "false");
core.setOutput("head_sha", pr.headRefOid);
core.setOutput("base", pr.baseRefName);
core.setOutput("review_decision", pr.reviewDecision ?? "");
// Dedupe marker per head SHA (so new commits can re-trigger notification)
const marker = `<!-- codeowners-approved:${pr.headRefOid} -->`;
core.setOutput("marker", marker);
// Check if we've already notified for this SHA
const comments = await github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number: prNumber,
per_page: 100,
});
const alreadyNotified = comments.some(c => (c.body || "").includes(marker));
core.setOutput("already_notified", alreadyNotified ? "true" : "false");
// Log for debugging
console.log(`PR #${pr.number}: draft=${pr.isDraft}, decision=${pr.reviewDecision}, notified=${alreadyNotified}`);
- name: Skip notification (conditions not met)
if: |
(inputs.skip-draft && steps.pr.outputs.is_draft == 'true') ||
(inputs.require-full-approval && steps.pr.outputs.review_decision != 'APPROVED') ||
steps.pr.outputs.already_notified == 'true'
run: |
echo "### Notification Skipped" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Condition | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-----------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Is Draft | ${{ steps.pr.outputs.is_draft }} |" >> $GITHUB_STEP_SUMMARY
echo "| Review Decision | ${{ steps.pr.outputs.review_decision }} |" >> $GITHUB_STEP_SUMMARY
echo "| Already Notified | ${{ steps.pr.outputs.already_notified }} |" >> $GITHUB_STEP_SUMMARY
- name: Build Slack message
id: slack_msg
if: |
(inputs.skip-draft == false || steps.pr.outputs.is_draft != 'true') &&
(inputs.require-full-approval == false || steps.pr.outputs.review_decision == 'APPROVED') &&
steps.pr.outputs.already_notified != 'true'
run: |
{
echo "message<<EOF"
echo "${{ inputs.slack-message-prefix }}"
echo "<${{ steps.pr.outputs.url }}|PR #${{ steps.pr.outputs.number }} — ${{ steps.pr.outputs.title }}>"
echo "Base: \`${{ steps.pr.outputs.base }}\` Head: \`${{ steps.pr.outputs.head_sha }}\`"
echo "Approved by: \`${{ github.event.review.user.login }}\`"
echo "EOF"
} >> $GITHUB_OUTPUT
- name: Post to Slack
if: |
(inputs.skip-draft == false || steps.pr.outputs.is_draft != 'true') &&
(inputs.require-full-approval == false || steps.pr.outputs.review_decision == 'APPROVED') &&
steps.pr.outputs.already_notified != 'true'
uses: slackapi/slack-github-action@v2
with:
webhook-type: incoming-webhook
webhook: ${{ secrets.SLACK_RELEASE_CHANGELOG_WEBHOOK }}
payload: |
{
"text": ${{ toJSON(steps.slack_msg.outputs.message) }}
}
- name: Summary (notification sent)
if: |
(inputs.skip-draft == false || steps.pr.outputs.is_draft != 'true') &&
(inputs.require-full-approval == false || steps.pr.outputs.review_decision == 'APPROVED') &&
steps.pr.outputs.already_notified != 'true'
run: |
echo "### Slack Notification Sent" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| PR | [#${{ steps.pr.outputs.number }}](${{ steps.pr.outputs.url }}) |" >> $GITHUB_STEP_SUMMARY
echo "| Title | ${{ steps.pr.outputs.title }} |" >> $GITHUB_STEP_SUMMARY
echo "| Base | \`${{ steps.pr.outputs.base }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Head SHA | \`${{ steps.pr.outputs.head_sha }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Approved By | @${{ github.event.review.user.login }} |" >> $GITHUB_STEP_SUMMARY