Files
windmill/.github/workflows/shareable-discord-notification.yml
2026-02-27 13:32:12 +01:00

215 lines
8.1 KiB
YAML

name: "Notify Discord when a PR is opened or merged"
on:
workflow_call:
inputs:
PR_TITLE:
description: "The title of the PR"
type: string
PR_URL:
description: "The URL of the PR"
type: string
PR_AUTHOR:
description: "The author of the PR"
type: string
PR_STATUS:
description: "The status of the PR"
type: string
DISCORD_CHANNEL_ID:
description: "The Discord channel ID"
type: string
PR_NUMBER:
description: "The number of the PR"
type: string
DISCORD_GUILD_ID:
description: "The Discord guild ID"
type: string
COMMENT_BODY:
description: "The comment body"
type: string
default: ""
COMMENT_AUTHOR:
description: "The comment author"
type: string
default: ""
COMMENT_URL:
description: "The comment URL"
type: string
default: ""
COMMENT_IS_EDIT:
description: "Whether this is an edit of an existing comment"
type: string
default: "false"
secrets:
DISCORD_WEBHOOK_URL:
description: "Discord Webhook URL"
required: false
DISCORD_BOT_TOKEN:
description: "Discord Bot Token"
jobs:
open_thread:
runs-on: ubicloud-standard-2
if: ${{ inputs.PR_STATUS == 'opened' }}
steps:
- name: Send Discord notification and start a thread
env:
WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}
CHANNEL_ID: ${{ inputs.DISCORD_CHANNEL_ID }}
GUILD_ID: ${{ inputs.DISCORD_GUILD_ID }}
PR_TITLE: ${{ inputs.PR_TITLE }}
PR_NUMBER: ${{ inputs.PR_NUMBER }}
PR_URL: ${{ inputs.PR_URL }}
PR_AUTHOR: ${{ inputs.PR_AUTHOR }}
run: |
# Check if thread already exists
thread_exists=false
if threads=$(curl -s -H "Authorization: Bot $BOT_TOKEN" "https://discord.com/api/v10/guilds/${GUILD_ID}/threads/active"); then
if thread_id=$(echo "$threads" | jq -r --arg cid "$CHANNEL_ID" --arg pref "#${PR_NUMBER}:" '.threads[] | select(.parent_id == $cid and (.name | startswith($pref))) | .id' 2>/dev/null); then
if [ -n "$thread_id" ]; then
thread_exists=true
echo "Thread already exists, skipping creation"
fi
fi
else
echo "Failed to check for existing threads, will create new thread"
fi
# Create thread if it doesn't exist or if check failed
if [ "$thread_exists" = false ]; then
echo "Creating new thread"
THREAD_TITLE="#${PR_NUMBER}: ${PR_TITLE} by \`${PR_AUTHOR}\`"
payload=$(jq -n \
--arg content "${PR_URL}" \
--arg thread "${THREAD_TITLE:0:99}" \
'{
content: $content,
thread_name: $thread,
auto_archive_duration: 10080
}'
)
curl -H "Content-Type: application/json" \
-X POST \
-d "$payload" \
"$WEBHOOK_URL"
fi
merge_success_emoji:
runs-on: ubuntu-latest
if: ${{ inputs.PR_STATUS == 'merged' }}
steps:
- name: React
env:
BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}
CHANNEL_ID: ${{ inputs.DISCORD_CHANNEL_ID }}
GUILD_ID: ${{ inputs.DISCORD_GUILD_ID }}
PR_NUMBER: ${{ inputs.PR_NUMBER }}
run: |
# 1) get PR thread
threads=$(curl -H "Authorization: Bot $BOT_TOKEN" "https://discord.com/api/v10/guilds/${GUILD_ID}/threads/active")
thread_id=$(
echo "$threads" \
| jq -r --arg cid "$CHANNEL_ID" \
--arg pref "#${PR_NUMBER}:" \
'.threads[]
| select(.parent_id == $cid and (.name | startswith($pref)))
| .id'
)
if [ -z "$thread_id" ]; then
echo "Thread not found"
exit 1
fi
# 2) get the first message in that thread
messages=$(curl -H "Authorization: Bot $BOT_TOKEN" \
"https://discord.com/api/v10/channels/$thread_id/messages")
message_id=$(echo "$messages" | jq -r '.[-1].id')
if [ -z "$message_id" ]; then
echo "Message not found"
exit 1
fi
# 3) add the ✅ reaction
curl -X PUT \
-H "Authorization: Bot $BOT_TOKEN" \
"https://discord.com/api/v10/channels/$thread_id/messages/$message_id/reactions/%E2%9C%85/@me"
post_comment:
runs-on: ubuntu-latest
if: ${{ inputs.PR_STATUS == 'comment' }}
steps:
- name: Post or update comment in Discord thread
env:
BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}
CHANNEL_ID: ${{ inputs.DISCORD_CHANNEL_ID }}
GUILD_ID: ${{ inputs.DISCORD_GUILD_ID }}
PR_NUMBER: ${{ inputs.PR_NUMBER }}
COMMENT_BODY: ${{ inputs.COMMENT_BODY }}
COMMENT_AUTHOR: ${{ inputs.COMMENT_AUTHOR }}
COMMENT_URL: ${{ inputs.COMMENT_URL }}
COMMENT_IS_EDIT: ${{ inputs.COMMENT_IS_EDIT }}
run: |
# 1) Find the thread by PR number
threads=$(curl -s -H "Authorization: Bot $BOT_TOKEN" \
"https://discord.com/api/v10/guilds/${GUILD_ID}/threads/active")
thread_id=$(echo "$threads" | jq -r \
--arg cid "$CHANNEL_ID" \
--arg pref "#${PR_NUMBER}:" \
'.threads[] | select(.parent_id == $cid and (.name | startswith($pref))) | .id')
if [ -z "$thread_id" ]; then
echo "Thread not found for PR #${PR_NUMBER}, skipping"
exit 0
fi
# 2) Truncate comment body to fit Discord's 2000 char limit
# Reserve space for the author line + link (~100 chars)
max_body=1800
if [ ${#COMMENT_BODY} -gt $max_body ]; then
# For bot comments, show the tail (conclusions/code tend to be at the end)
if [[ "$COMMENT_AUTHOR" == *"[bot]"* ]] || [[ "$COMMENT_AUTHOR" == *"-bot"* ]]; then
truncated_body="...${COMMENT_BODY: -$max_body}"
else
truncated_body="${COMMENT_BODY:0:$max_body}..."
fi
else
truncated_body="$COMMENT_BODY"
fi
# 3) Build the message content
if [ "$COMMENT_IS_EDIT" = "true" ]; then
message=$(printf '**%s** [edited comment](%s):\n%s' "$COMMENT_AUTHOR" "$COMMENT_URL" "$truncated_body")
else
message=$(printf '**%s** [commented](%s):\n%s' "$COMMENT_AUTHOR" "$COMMENT_URL" "$truncated_body")
fi
payload=$(jq -n --arg content "$message" '{content: $content, flags: 4, allowed_mentions: {parse: []}}')
# 4) If this is an edit, try to find and update the existing Discord message
if [ "$COMMENT_IS_EDIT" = "true" ]; then
# Search recent messages in the thread for one containing the comment URL
messages=$(curl -s -H "Authorization: Bot $BOT_TOKEN" \
"https://discord.com/api/v10/channels/${thread_id}/messages?limit=100")
existing_msg_id=$(echo "$messages" | jq -r \
--arg url "$COMMENT_URL" \
'[.[] | select(.content | contains($url))] | first | .id // empty')
if [ -n "$existing_msg_id" ]; then
echo "Updating existing Discord message $existing_msg_id"
curl -s -X PATCH \
-H "Authorization: Bot $BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "$payload" \
"https://discord.com/api/v10/channels/${thread_id}/messages/${existing_msg_id}"
exit 0
fi
echo "Original Discord message not found, posting as new message"
fi
# 5) Post a new message to the thread
curl -s -X POST \
-H "Authorization: Bot $BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "$payload" \
"https://discord.com/api/v10/channels/${thread_id}/messages"