Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 100 additions & 47 deletions .github/workflows/slack.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
name: Slack Notify (CloudDrove Style)

on:
workflow_call:
inputs:
Expand Down Expand Up @@ -29,10 +30,12 @@ on:
type: string
required: false
default: Open Run
description: 'Text label for the optional Slack button'
button_url:
type: string
required: false
default: ""
description: 'Target URL for the Slack button (shows only if set)'
logo_url:
type: string
required: false
Expand All @@ -41,20 +44,23 @@ on:
type: string
required: false
default: CloudDrove
description: 'Brand/logo image URL displayed in Slack blocks'
link_to_run:
type: boolean
required: false
default: true
description: 'Whether to include a "View GitHub Run" link in footer'
secrets:
SLACK_BOT_TOKEN:
required: true
description: 'Slack bot token with chat:write permission'

jobs:
send:
runs-on: ubuntu-latest
steps:
- name: Build payload (Block Kit)
- name: Build Slack Payload
id: build
shell: bash
env:
CHANNEL: ${{ inputs.channel }}
TITLE: ${{ inputs.title }}
Expand All @@ -65,93 +71,140 @@ jobs:
BUTTON_URL: ${{ inputs.button_url }}
LOGO_URL: ${{ inputs.logo_url }}
BRAND: ${{ inputs.brand }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
LINK_TO_RUN: ${{ inputs.link_to_run }}
ACTOR: ${{ github.actor }}
REF: ${{ github.ref }}
SHA: ${{ github.sha }}
REPO: ${{ github.repository }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
ACTOR: ${{ github.actor }}
EVENT_NAME: ${{ github.event_name }}
run: |
set -e

# Map status -> emoji (you can tweak)
# Emoji for status
case "${STATUS,,}" in
success) EMOJI="✅";;
failed) EMOJI="❌";;
cancelled)EMOJI="⚠️";;
warning) EMOJI="⚠️";;
info|*) EMOJI="ℹ️";;
success) EMOJI="✅";;
failure) EMOJI="❌";;
cancelled|warning) EMOJI="⚠️";;
info|*) EMOJI="ℹ️";;
esac

# Default fields (always appended)
DEFAULT_FIELDS=$(jq -n --arg ref "$REF" --arg sha "$SHA" --arg actor "@$ACTOR" \
'[ {"label":"Ref","value":$ref},
{"label":"Commit","value":$sha},
{"label":"Actor","value":$actor}
]')
SHORT_SHA=${SHA:0:7}
COMMIT_URL="https://github.com/${REPO}/commit/${SHA}"
ACTOR_URL="https://github.com/${ACTOR}"

# Default fields with clickable actor link
DEFAULT_FIELDS=$(jq -n \
--arg ref "$REF" \
--arg sha "$SHORT_SHA" \
--arg sha_url "$COMMIT_URL" \
--arg actor "@$ACTOR" \
--arg actor_url "$ACTOR_URL" \
--arg event "$EVENT_NAME" \
'[
{"label":"Ref","value":$ref},
{"label":"Commit","value": ("<" + $sha_url + "|" + $sha + ">")},
{"label":"Triggered By","value": ("<" + $actor_url + "|" + $actor + ">")},
{"label":"Event","value":$event}
]')

# Merge custom + default fields
FIELDS=$(jq -c -n \
# Merge fields
ALL_FIELDS=$(jq -c -n \
--argjson a "${FIELDS_JSON}" \
--argjson b "${DEFAULT_FIELDS}" \
'$a + $b')

# Build Block Kit "fields" array
FIELDS_BLOCK=$(jq -c '[ .[] | {type:"mrkdwn", text: ("*"+.label+"*:\n`"+.value+"`")} ]' <<<"$FIELDS")
# Slack field layout
FIELD_ITEMS=$(jq -c '[ .[] | {
type: "mrkdwn",
text: ("*" + .label + "*:\n" + .value)
} ]' <<<"$ALL_FIELDS")

# Optional body section
FIELD_BLOCK=$(jq -c -n --argjson fields "$FIELD_ITEMS" '{
type: "section",
fields: $fields
}')

# Optional body
if [ -n "$BODY_MD" ]; then
BODY_BLOCK=$(jq -c -n --arg t "$BODY_MD" \
'{ "type":"section", "text": { "type":"mrkdwn", "text": $t } }')
else
BODY_BLOCK="null"
BODY_BLOCK=null
fi

# Context line with logo + brand + run link
# Top header branding block
HEADER_CONTEXT=$(jq -c -n --arg logo "$LOGO_URL" --arg brand "$BRAND" '{
type: "context",
elements: [
{ "type": "image", "image_url": $logo, "alt_text": "brand" },
{ "type": "mrkdwn", "text": "*\($brand)*" }
]
}')

# Footer branding block
if [ "$LINK_TO_RUN" = "true" ]; then
CTX_TEXT="*by '"$BRAND"'* • <'"$RUN_URL"'|View GitHub Run>"
FOOTER_CONTEXT=$(jq -c -n --arg logo "$LOGO_URL" --arg brand "$BRAND" --arg url "$RUN_URL" '{
type: "context",
elements: [
{ "type": "image", "image_url": $logo, "alt_text": "brand" },
{ "type": "mrkdwn", "text": "*by \($brand)* • <\($url)|View GitHub Run>" }
]
}')
else
CTX_TEXT="*by '"$BRAND"'*"
FOOTER_CONTEXT=$(jq -c -n --arg logo "$LOGO_URL" --arg brand "$BRAND" '{
type: "context",
elements: [
{ "type": "image", "image_url": $logo, "alt_text": "brand" },
{ "type": "mrkdwn", "text": "*by \($brand)*" }
]
}')
fi

CONTEXT_BLOCK=$(jq -n -c --arg logo "$LOGO_URL" --arg t "$CTX_TEXT" \
'{ "type":"context", "elements": [
{ "type":"image", "image_url": $logo, "alt_text": "brand" },
{ "type":"mrkdwn", "text": $t }
] }')

# Optional button row
# Optional button
if [ -n "$BUTTON_URL" ]; then
ACTIONS=$(jq -n -c --arg txt "$BUTTON_TEXT" --arg url "$BUTTON_URL" \
'{ "type":"actions",
"elements":[ { "type":"button","text":{"type":"plain_text","text":$txt},"url":$url,"style":"primary"} ] }')
ACTIONS=$(jq -c -n --arg txt "$BUTTON_TEXT" --arg url "$BUTTON_URL" '{
type: "actions",
elements: [
{ "type":"button", "text": { "type":"plain_text", "text": $txt }, "url": $url, "style": "primary" }
]
}')
else
ACTIONS="null"
ACTIONS=null
fi

# Assemble blocks
# Final payload
jq -n \
--arg ch "$CHANNEL" \
--arg title "$EMOJI $TITLE — ${STATUS^^}" \
--argjson fields "$FIELDS_BLOCK" \
--argjson context "$CONTEXT_BLOCK" \
--argjson header "$HEADER_CONTEXT" \
--argjson fields "$FIELD_BLOCK" \
--argjson body "$BODY_BLOCK" \
--argjson actions "$ACTIONS" \
'{
--argjson footer "$FOOTER_CONTEXT" '
def optional(x): if x != null and x != "null" then [x] else [] end;

{
channel: $ch,
blocks: [
{ "type":"header", "text":{"type":"plain_text","text":$title,"emoji":true} },
$context,
{ "type":"section", "fields": $fields },
( $body // empty ),
( $actions // empty )
]
blocks: (
[ $header ]
+ [ { "type": "header", "text": { "type": "plain_text", "text": $title, "emoji": true } } ]
+ [ $fields ]
+ optional($body)
+ optional($actions)
+ [ $footer ]
)
}' > payload.json

echo "payload=$(jq -c . payload.json)" >> $GITHUB_OUTPUT

- name: Send to Slack
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
payload: ${{ steps.build.outputs.payload }}
token: ${{ secrets.SLACK_BOT_TOKEN }}
unfurl_links: false
unfurl_media: false

...