@@ -34,149 +34,25 @@ jobs:
3434 if : failure()
3535 runs-on : ubuntu-latest
3636 steps :
37- - name : Resolve Slack recipients
38- id : resolve
39- uses : actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
40- env :
41- SLACK_BOT_TOKEN : ${{ secrets.SLACK_GHBOT_TOKEN }}
42- SLACK_GITHUB_FIELD_ID : " Xf0A2BPU8U77"
43- CHANNEL_ID : " C067BD0377F"
44- PR_AUTHOR : ${{ github.event.pull_request.user.login }}
45- ACTOR : ${{ github.actor }}
46- EVENT_NAME : ${{ github.event_name }}
37+ - name : Notify Slack
38+ uses : FlowFuse/github-actions-workflows/actions/slack_notification@slack_notification/v1
4739 with :
48- script : |
49- const token = process.env.SLACK_BOT_TOKEN;
50- const fieldId = process.env.SLACK_GITHUB_FIELD_ID;
51-
52- // Resolve a GitHub login -> Slack user ID by scanning workspace profiles and
53- // matching the custom profile field (GitHub). Returns undefined if not found.
54- async function resolveSlackId(login) {
55- const target = login.toLowerCase();
56- let cursor;
57- do {
58- const params = new URLSearchParams({ limit: '200' });
59- if (cursor) params.set('cursor', cursor);
60- const res = await fetch(`https://slack.com/api/users.list?${params}`, {
61- headers: { Authorization: `Bearer ${token}` }
62- });
63- const data = await res.json();
64- if (!data.ok) { core.setFailed(`Slack users.list error: ${data.error}`); return; }
65- for (const member of data.members) {
66- if (member.deleted || member.is_bot) continue;
67- const profileRes = await fetch(`https://slack.com/api/users.profile.get?user=${member.id}`, {
68- headers: { Authorization: `Bearer ${token}` }
69- });
70- const profileData = await profileRes.json();
71- if (!profileData.ok) continue;
72- const ghField = profileData.profile?.fields?.[fieldId]?.value;
73- if (!ghField) continue;
74- if (ghField.toLowerCase() === target) return member.id;
75- }
76- cursor = data.response_metadata?.next_cursor;
77- } while (cursor);
78- return undefined;
79- }
80-
81- // Push to main - notify the channel, mentioning the actor who pushed.
82- if (process.env.EVENT_NAME !== 'pull_request') {
83- const actor = process.env.ACTOR;
84- const mention = actor ? await resolveSlackId(actor) : undefined;
85- if (!mention) core.warning(`No Slack user found with GitHub username: ${actor}`);
86- core.setOutput('recipients', JSON.stringify([{ slack_id: process.env.CHANNEL_ID, role: 'Channel', mention: mention || null }]));
87- return;
88- }
89-
90- // Pull request - notify the author. Bot authors have no Slack profile: skip silently.
91- const author = process.env.PR_AUTHOR;
92- if (!author || author.endsWith('[bot]')) {
93- core.setOutput('recipients', '[]');
94- return;
95- }
96-
97- const slackId = await resolveSlackId(author);
98- if (!slackId) {
99- core.warning(`No Slack user found with GitHub username: ${author}`);
100- core.setOutput('recipients', '[]');
101- return;
102- }
103- core.setOutput('recipients', JSON.stringify([{ slack_id: slackId, github: author.toLowerCase(), role: 'Author' }]));
104-
105- - name : Send Slack notification
106- if : steps.resolve.outputs.recipients != '' && steps.resolve.outputs.recipients != '[]'
107- uses : actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
108- env :
109- SLACK_BOT_TOKEN : ${{ secrets.SLACK_GHBOT_TOKEN }}
110- RECIPIENTS : ${{ steps.resolve.outputs.recipients }}
111- EVENT_NAME : ${{ github.event_name }}
112- REF_NAME : ${{ github.ref_name }}
113- PR_NUMBER : ${{ github.event.pull_request.number }}
114- COMMIT_SHA : ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
115- ACTOR : ${{ github.actor }}
116- SERVER_URL : ${{ github.server_url }}
117- REPOSITORY : ${{ github.repository }}
118- RUN_ID : ${{ github.run_id }}
119- with :
120- script : |
121- const token = process.env.SLACK_BOT_TOKEN;
122- const recipients = JSON.parse(process.env.RECIPIENTS);
123- const isBranch = process.env.EVENT_NAME !== 'pull_request';
124- const refName = process.env.REF_NAME;
125- const prNumber = process.env.PR_NUMBER;
126- const commitSha = process.env.COMMIT_SHA;
127- const actor = process.env.ACTOR;
128- const serverUrl = process.env.SERVER_URL;
129- const repository = process.env.REPOSITORY;
130- const runId = process.env.RUN_ID;
131-
132- const headerText = isBranch
133- ? `Tests failed against ${refName} branch`
134- : `Tests failed against #${prNumber} pull request`;
135- const summaryIcon = isBranch ? 'no_entry' : 'warning';
136- const summaryText = isBranch
137- ? ' Deployment to FFC environments will not happen until this issue is resolved.'
138- : ' Please resolve the problem before merging your changes into the main branch.';
139- const refLink = isBranch
140- ? `*Branch:* ${refName}`
141- : `*Pull request:* <${serverUrl}/${repository}/pull/${prNumber}|${prNumber}>`;
142-
143- let failures = 0;
144- for (const r of recipients) {
145- // Channel posts mention the actor's Slack ID (a real ping) if resolved;
146- // otherwise (and for DMs) show the plain GitHub login.
147- const authorText = r.mention ? `<@${r.mention}>` : actor;
148- const blocks = [
149- { type: 'header', text: { type: 'plain_text', text: `:x: ${headerText}`, emoji: true } },
150- { type: 'divider' },
151- { type: 'rich_text', elements: [ { type: 'rich_text_section', elements: [
152- { type: 'emoji', name: summaryIcon },
153- { type: 'text', text: summaryText, style: { bold: true } }
154- ] } ] },
155- { type: 'divider' },
156- { type: 'section', fields: [
157- { type: 'mrkdwn', text: `*Author:* ${authorText}` },
158- { type: 'mrkdwn', text: `<${serverUrl}/${repository}/actions/runs/${runId}|View failed workflow>` },
159- { type: 'mrkdwn', text: `*Last commit:* <${serverUrl}/${repository}/commit/${commitSha}|${commitSha}>` },
160- { type: 'mrkdwn', text: refLink }
161- ] }
162- ];
163- const res = await fetch('https://slack.com/api/chat.postMessage', {
164- method: 'POST',
165- headers: {
166- Authorization: `Bearer ${token}`,
167- 'Content-Type': 'application/json; charset=utf-8'
168- },
169- body: JSON.stringify({ channel: r.slack_id, blocks })
170- });
171- const data = await res.json();
172- if (!data.ok) {
173- core.warning(`Slack chat.postMessage failed for ${r.slack_id}: ${data.error}`);
174- failures++;
175- } else {
176- core.info(`Notified ${r.slack_id} (${r.role})`);
177- }
178- }
179-
180- if (failures > 0 && failures === recipients.length) {
181- core.setFailed(`All ${failures} Slack notifications failed`);
182- }
40+ bot-token : ${{ secrets.SLACK_GHBOT_TOKEN }}
41+ mode : ${{ github.event_name == 'pull_request' && 'author' || 'channel' }}
42+ mention-actor : ${{ github.event_name != 'pull_request' }}
43+ blocks : |
44+ [
45+ { "type": "header", "text": { "type": "plain_text", "text": ":x: ${{ github.event_name == 'pull_request' && format('Tests failed against #{0} pull request', github.event.pull_request.number) || format('Tests failed against {0} branch', github.ref_name) }}", "emoji": true } },
46+ { "type": "divider" },
47+ { "type": "rich_text", "elements": [ { "type": "rich_text_section", "elements": [
48+ { "type": "emoji", "name": "${{ github.event_name == 'pull_request' && 'warning' || 'no_entry' }}" },
49+ { "type": "text", "text": "${{ github.event_name == 'pull_request' && ' Please resolve the problem before merging your changes into the main branch.' || ' Deployment to FFC environments will not happen until this issue is resolved.' }}", "style": { "bold": true } }
50+ ] } ] },
51+ { "type": "divider" },
52+ { "type": "section", "fields": [
53+ { "type": "mrkdwn", "text": "*Author:* ${{ github.event_name == 'pull_request' && github.actor || '{{MENTION}}' }}" },
54+ { "type": "mrkdwn", "text": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View failed workflow>" },
55+ { "type": "mrkdwn", "text": "${{ format('*Last commit:* <{0}/{1}/commit/{2}|{2}>', github.server_url, github.repository, github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha) }}" },
56+ { "type": "mrkdwn", "text": "${{ github.event_name == 'pull_request' && format('*Pull request:* <{0}/{1}/pull/{2}|{2}>', github.server_url, github.repository, github.event.pull_request.number) || format('*Branch:* {0}', github.ref_name) }}" }
57+ ] }
58+ ]
0 commit comments