๐ฎ Slack Message Broker #231214
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This workflow sends a message to the plutus-ci channel whenever a status check fails, | |
| # and tried to notify the author of the commit that caused the failure. | |
| # | |
| # This workflow triggers whenever a workflow run or a check run is completed. | |
| name: "๐ฎ Slack Message Broker" | |
| on: | |
| check_run: | |
| types: [completed] | |
| workflow_run: | |
| workflows: | |
| - "๐ Broken Links" | |
| - "๐ท Cabal Build All" | |
| - "๐ฝ Cardano Constitution Tests" | |
| - "๐ฐ Cost Model Benchmark" | |
| - "๐ฆ Docusaurus Site" | |
| - "๐ Haddock Site" | |
| - "๐ฉบ Longitudinal Benchmark" | |
| - "๐ฎ Metatheory Site" | |
| - "๐ Nightly Testsuite" | |
| - "๐ Papers & Specs" | |
| - "๐ Code Coverage Report" | |
| - "๐ Compare Golden Budgets" | |
| - "pages-build-deployment" | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| jobs: | |
| Send: | |
| runs-on: [ubuntu-latest] | |
| steps: | |
| - name: Prepare Slack Message | |
| uses: actions/github-script@v7.1.0 | |
| id: prepare-slack-message | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| SENDER_LOGIN: ${{ github.event.sender.login }} | |
| WORKFLOW_NAME: ${{ github.event.workflow.name }} | |
| WORKFLOW_RUN_NAME: ${{ github.event.workflow_run.name }} | |
| WORKFLOW_RUN_URL: ${{ github.event.workflow_run.html_url }} | |
| WORKFLOW_RUN_STATUS: ${{ github.event.workflow_run.status }} | |
| WORKFLOW_RUN_CONCLUSION: ${{ github.event.workflow_run.conclusion }} | |
| CHECK_RUN_NAME: ${{ github.event.check_run.name }} | |
| CHECK_RUN_STATUS: ${{ github.event.check_run.status }} | |
| CHECK_RUN_CONCLUSION: ${{ github.event.check_run.conclusion }} | |
| CHECK_RUN_URL: ${{ github.event.check_run.html_url }} | |
| with: | |
| script: | | |
| console.log(JSON.stringify(context.payload)); | |
| function getSlackMembersToBeNotified() { | |
| const senderLogin = process.env.SENDER_LOGIN; | |
| const workflowName = process.env.WORKFLOW_NAME; | |
| const slackMemberIds = { | |
| "zeme-wana": ["U03HGDNDRKR"], | |
| "effectfully": ["UBH8K0ZU2"], | |
| "kwxm": ["UCF4SL4BT"], | |
| "Unisay": ["U02V796524S"], | |
| "ramsay-t": ["U05T49F9FV1"], | |
| "ana-pantilie": ["U05V2854W86"], | |
| "zliu41": ["U03BP2HTKDK"], | |
| "bezirg": ["UQ1LUSR8B"], | |
| "erikd": ["U914V9D2B"], | |
| "SeungheonOh": ["U08RN7SACTT"] | |
| }; | |
| const workflowOwners = { | |
| "๐ฝ Cardano Constitution Tests": ["UQ1LUSR8B"], | |
| "๐ฉบ Longitudinal Benchmark": ["UBH8K0ZU2"], | |
| "๐ฐ Cost Model Benchmark": ["UBH8K0ZU2"], | |
| "๐ Nightly Testsuite": ["UQ1LUSR8B"] | |
| }; | |
| function at(ids) { | |
| return ids.reduce((acc, id) => acc + `<@${id}> `, ""); | |
| } | |
| if (workflowName in workflowOwners) { | |
| return at(workflowOwners[workflowName]); | |
| } else if (senderLogin in slackMemberIds) { | |
| return at(slackMemberIds[senderLogin]); | |
| } else { | |
| return `@${senderLogin}`; | |
| } | |
| } | |
| const eventName = process.env.EVENT_NAME; | |
| const isWorkflowRunEvent = eventName === "workflow_run"; | |
| const isCheckRunEvent = eventName === "check_run"; | |
| async function isDraftPullRequest() { | |
| const event = isWorkflowRunEvent ? context.payload.workflow_run | |
| : isCheckRunEvent ? context.payload.check_run | |
| : null; | |
| const pr = event && event.pull_requests && event.pull_requests[0]; | |
| console.log(`isWorkflowRunEvent: ${isWorkflowRunEvent}`); | |
| console.log(`isCheckRunEvent: ${isCheckRunEvent}`); | |
| if (!pr) { | |
| console.log("No associated pull request; treating as non-draft."); | |
| return false; | |
| } | |
| try { | |
| const { data } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: pr.number, | |
| }); | |
| console.log(`PR #${pr.number} draft: ${data.draft}`); | |
| return data.draft === true; | |
| } catch (error) { | |
| // Fail open: if we cannot determine draft status, send the message. | |
| console.log(`Could not fetch PR #${pr.number}: ${error}`); | |
| return false; | |
| } | |
| } | |
| const slackMembers = getSlackMembersToBeNotified(); | |
| const isDraftPR = await isDraftPullRequest(); | |
| let message; | |
| let shouldSendMessage; | |
| function handleWorkflowRunEvent() { | |
| const name = process.env.WORKFLOW_RUN_NAME; | |
| const url = process.env.WORKFLOW_RUN_URL; | |
| const status = process.env.WORKFLOW_RUN_STATUS; | |
| const conclusion = process.env.WORKFLOW_RUN_CONCLUSION; | |
| const failureConclusions = [ "failure", "null", "action_required", "neutral", "timed_out" ]; | |
| if (failureConclusions.includes(conclusion)) { | |
| message = `โ ${name} \`${conclusion}\` <${url}|View Logs> ${slackMembers}`; | |
| shouldSendMessage = true; | |
| } else { | |
| message = `${name} \`${status}\` \`${conclusion}\` <${url}|View Logs> ${slackMembers}`; | |
| shouldSendMessage = false; | |
| } | |
| } | |
| function handleCheckRunEvent() { | |
| const name = process.env.CHECK_RUN_NAME; | |
| const status = process.env.CHECK_RUN_STATUS; | |
| const conclusion = process.env.CHECK_RUN_CONCLUSION; | |
| const url = process.env.CHECK_RUN_URL; | |
| const checkRunWatchlist = [ | |
| "ci/hydra-build:aarch64-darwin.required", | |
| "ci/hydra-build:x86_64-linux.required", | |
| "ci/eval" | |
| ]; | |
| if (conclusion === "failure" && checkRunWatchlist.includes(name)) { | |
| message = `โ ${name} \`${conclusion}\` <${url}|View Logs> ${slackMembers}`; | |
| shouldSendMessage = true; | |
| } else { | |
| message = `${name} \`${status}\` \`${conclusion}\` <${url}|View Logs> ${slackMembers}`; | |
| shouldSendMessage = false; | |
| } | |
| } | |
| if (isDraftPR) { | |
| message = `Draft PR, skipping notification: ${eventName}`; | |
| shouldSendMessage = false; | |
| } else if (isWorkflowRunEvent) { | |
| handleWorkflowRunEvent(); | |
| } else if (isCheckRunEvent) { | |
| handleCheckRunEvent(); | |
| } else { | |
| message = `Unknown event: ${eventName}`; | |
| shouldSendMessage = true; | |
| } | |
| console.log(`message: ${message}`); | |
| console.log(`shouldSendMessage: ${shouldSendMessage}`); | |
| core.setOutput("message", message); | |
| core.setOutput("shouldSendMessage", shouldSendMessage); | |
| - name: Notify Slack | |
| uses: slackapi/slack-github-action@v3.0.3 | |
| if: ${{ steps.prepare-slack-message.outputs.shouldSendMessage == 'true' }} | |
| with: | |
| method: chat.postMessage | |
| token: ${{ secrets.SLACK_BOT_TOKEN }} | |
| payload: | | |
| "channel": "C07A1GSNZEE", | |
| "text": "${{ steps.prepare-slack-message.outputs.message }}", | |