diff --git a/action.yml b/action.yml index 6438cc06..496ef378 100644 --- a/action.yml +++ b/action.yml @@ -340,23 +340,33 @@ runs: } return githubToSlack[actor] ? githubToSlack[actor] : `@${actor}`; - # TODO: Migrate to actions/github-script - - uses: actions-ecosystem/action-slack-notifier@fc778468d09c43a6f4d1b8cccaca59766656996a # v1.1.0 + - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 if: ${{ steps.reviewdog-enabled-pr.outputs.result == 'true' && inputs.slack_token && hashFiles('reviewdog.fail.log') }} with: - slack_token: ${{ inputs.slack_token }} - message: | - [semgrep] ${{ fromJson(steps.actor-slack.outputs.result) }} action failed, plz take a look. /cc ${{fromJson(steps.assignees-slack.outputs.result)}} ${{ fromJson(steps.reviewdog-fail-log-head.outputs.result) }} - channel: secops-hotspots - color: red - verbose: true - # TODO: Migrate to actions/github-script - - uses: actions-ecosystem/action-slack-notifier@fc778468d09c43a6f4d1b8cccaca59766656996a # v1.1.0 + script: | + const actionPath = '${{ github.action_path }}' + const {default: sendSlackMessage} = await import(`${actionPath}/src/steps/sendSlackMessage.js`) + const message = 'Repository: ${{ github.repository }}\npull-request: ${{ github.event.pull_request.html_url }}' + + await sendSlackMessage({ + slack_token: inputs.slack_token, + text: "[security-action] ${{ fromJson(steps.actor-slack.outputs.result) }} action failed, plz take a look. /cc ${{fromJson(steps.assignees-slack.outputs.result)}} ${{ fromJson(steps.reviewdog-fail-log-head.outputs.result) }}", + message, + channel: '#secops-hotspots', + color: 'red', + }) + - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 if: ${{ steps.reviewdog-enabled-pr.outputs.result == 'true' && inputs.slack_token && steps.should-trigger.outputs.result == 'true' }} with: - slack_token: ${{ inputs.slack_token }} - message: | - [semgrep] ${{ fromJson(steps.actor-slack.outputs.result) }} pushed commits. /cc ${{fromJson(steps.assignees-slack.outputs.result)}} - channel: secops-hotspots - color: green - verbose: true + script: | + const actionPath = '${{ github.action_path }}' + const {default: sendSlackMessage} = await import(`${actionPath}/src/steps/sendSlackMessage.js`) + const message = 'Repository: ${{ github.repository }}\npull-request: ${{ github.event.pull_request.html_url }}' + + await sendSlackMessage({ + slack_token: inputs.slack_token, + text: "[semgrep] ${{ fromJson(steps.actor-slack.outputs.result) }} pushed commits. /cc ${{fromJson(steps.assignees-slack.outputs.result)}}", + message, + channel: '#secops-hotspots', + color: 'green', + }) \ No newline at end of file diff --git a/src/sendSlackMessage.js b/src/sendSlackMessage.js index cecee4bc..3259909d 100644 --- a/src/sendSlackMessage.js +++ b/src/sendSlackMessage.js @@ -17,12 +17,25 @@ async function findChannelId (web, name) { } } +const colorCodes = { + black: '#000000', + red: '#F44336', + green: '#4CAF50', + yellow: '#FFEB3B', + blue: '#2196F3', + magenta: '#FF00FF', + cyan: '#00BCD4', + white: '#FFFFFF' +} + // send markdown message to slack channel export default async function sendSlackMessage ({ token = null, + text = null, channel = null, message = null, debug = false, + color = null, username = 'github-actions' }) { if (!token) { @@ -33,10 +46,16 @@ export default async function sendSlackMessage ({ throw new Error('channel is required!') } - if (!message) { - throw new Error('message is required!') + if (!message && !text) { + throw new Error('message || token is required!') } + if (colorCodes[color]) { + color = colorCodes[color] + } + + const colored = color?.match(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/) + debug = debug === 'true' || debug === true if (debug) { console.log(`token.length: ${token.length}, channel: ${channel}, message: ${message}`) } @@ -45,28 +64,52 @@ export default async function sendSlackMessage ({ const { WebClient } = await import('@slack/web-api') const web = new WebClient(token) - let blocks = await markdownToBlocks(message) // calculate the sha256 hash of the message const crypto = await import('crypto') const hash = crypto.createHash('sha256') - hash.update(message) + if (text !== null) hash.update(text) + if (message !== null) hash.update(message) + if (color !== null) hash.update(color) const hashHex = hash.digest('hex') - if (debug) { console.log(blocks) } + const blocks = [] + let attachments = null - // slack blocks have a limit of 50 blocks, remove the last blocks if there are more - if (blocks.length > 50) { - blocks = blocks.slice(0, 49) + if (text !== null) { blocks.push({ type: 'section', text: { type: 'mrkdwn', - text: '...and more' + text } }) } + if (message !== null) { + let mdBlocks = await markdownToBlocks(message) + // slack blocks have a limit of 50 blocks, remove the last blocks if there are more + if (mdBlocks.length > 50) { + mdBlocks = mdBlocks.slice(0, 49) + mdBlocks.push({ + type: 'section', + text: { + type: 'mrkdwn', + text: '...and more' + } + }) + } + if (colored) { + attachments = [{ + color, + blocks: mdBlocks + }] + } else { + blocks.push(...mdBlocks) + } + if (debug) { console.log(mdBlocks) } + } + // get the channel id const channelId = await findChannelId(web, channel) @@ -87,9 +130,13 @@ export default async function sendSlackMessage ({ // send the message const result = await web.chat.postMessage({ username, - text: `${username} alert`, + text: text || `${username} alert`, channel, + link_names: true, + unfurl_links: true, + unfurl_media: true, blocks, + attachments, metadata })