Skip to content

Commit 680ccb2

Browse files
authored
ci: Replace custom scripts with slack_notification action in Tests workflow (#125)
1 parent bd453e9 commit 680ccb2

1 file changed

Lines changed: 21 additions & 145 deletions

File tree

.github/workflows/tests.yml

Lines changed: 21 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)