community-release-notifier workflow (Acode-Foundation/Acode)
The community-release-notifier workflow from Acode-Foundation/Acode, explained and optimized by Latchkey.
CI health: A - excellent
Point runs-on at Latchkey and get job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the community-release-notifier workflow from the Acode-Foundation/Acode repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: community-release-notifier
on:
release:
types: [ released ]
workflow_dispatch:
inputs:
tag_name:
required: true
description: "Release tag_name"
type: string
url:
required: true
description: "release URL"
type: string
body:
required: true
description: "Release Body"
type: string
default: ''
workflow_call:
inputs:
tag_name:
required: true
description: "Release tag_name"
type: string
url:
required: true
description: "release URL"
type: string
body:
required: true
description: "Release Body"
type: string
default: ''
secrets:
DISCORD_WEBHOOK_RELEASE_NOTES:
description: 'Discord Webhook for Notifying Releases to Discord'
required: true
TELEGRAM_BOT_TOKEN:
description: 'Telegram Bot Token'
required: true
TELEGRAM_CHAT_ID:
description: 'Telegram Chat ID (group/channel/supergroup)'
required: true
TELEGRAM_MESSAGE_THREAD_ID:
description: 'Topic / message_thread_id for Telegram forum/topic'
required: true
jobs:
notify:
if: github.repository_owner == 'Acode-Foundation'
runs-on: ubuntu-latest
steps:
- name: Prepare release variables
id: vars
env:
INPUT_TAG: ${{ github.event.release.tag_name || inputs.tag_name }}
INPUT_URL: ${{ github.event.release.url || inputs.url }}
INPUT_BODY: ${{ github.event.release.body || inputs.body }}
run: |
TAG="$INPUT_TAG"
URL="$INPUT_URL"
# Generate a random delimiter (hex string, safe and collision-resistant)
DELIMITER=$(openssl rand -hex 16 || head -c 16 /dev/urandom | xxd -p -c 16)
# Escape problematic characters for MarkdownV2 (very conservative escaping)
# We escape: _ * [ ] ( ) ~ ` > # + - = | { } . ! \
BODY_SAFE=$(printf '%s' "$INPUT_BODY" | \
sed 's/[_*[\]()~`>#+=|{}.!\\-]/\\&/g')
TAG_SAFE=$(printf '%s' "$TAG" | sed 's/[_*[\]()~`>#+=|{}.!\\-]/\\&/g')
if [[ "$TAG" == *"-nightly"* ]]; then
SUFFIX=" \(Nightly Release\)"
SUFFIXPLAIN=" (Nightly Release)"
else
SUFFIX=""
SUFFIXPLAIN=""
fi
# Announcement line - also escape for safety
ANNOUNCE_SAFE="π’ Acode [$TAG_SAFE]($URL) was just Released π${SUFFIX}\\!"
echo "announce=$ANNOUNCE_SAFE" >> $GITHUB_OUTPUT
{
echo "body_safe<<$DELIMITER"
printf '%s\n' "$BODY_SAFE"
echo "$DELIMITER"
} >> $GITHUB_OUTPUT
# Plain (MD) Announcement for Discord
ANNOUNCE_PLAIN="π’ Acode [$TAG](<$URL>) was just Released π${SUFFIXPLAIN}!"
echo "announce_plain=$ANNOUNCE_PLAIN" >> $GITHUB_OUTPUT
{
echo "body_plain<<$DELIMITER"
printf '%s\n' "$INPUT_BODY"
echo "$DELIMITER"
} >> $GITHUB_OUTPUT
# ββββββββββββββββββββββββββββββββββββββββββββββββ
# Truncate for Discord
# ββββββββββββββββββββββββββββββββββββββββββββββββ
- name: Truncate message for Discord
id: truncate-discord
uses: 2428392/gh-truncate-string-action@b3ff790d21cf42af3ca7579146eedb93c8fb0757 # v1.4.1
env:
# https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
with:
maxLength: 2000
stringToTruncate: |
${{ steps.vars.outputs.announce_plain }}
${{ steps.vars.outputs.body_plain }}
# ββββββββββββββββββββββββββββββββββββββββββββββββ
# Discord notification
# ββββββββββββββββββββββββββββββββββββββββββββββββ
- name: Discord Webhook (Publishing)
uses: tsickert/discord-webhook@b217a69502f52803de774ded2b1ab7c282e99645 # v7.0.0
env:
# https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
with:
webhook-url: ${{ secrets.DISCORD_WEBHOOK_RELEASE_NOTES }}
content: ${{ steps.truncate-discord.outputs.string }}
flags: 4 # 1 << 2 - SUPPRESS_EMBEDS!
# ββββββββββββββββββββββββββββββββββββββββββββββββ
# Telegram notification - MarkdownV2 + no link preview
# ββββββββββββββββββββββββββββββββββββββββββββββββ
- name: Send to Telegram
#if: ${{ secrets.TELEGRAM_BOT_TOKEN != '' && secrets.TELEGRAM_CHAT_ID != '' && secrets.TELEGRAM_MESSAGE_THREAD_ID != '' }}
uses: Salmansha08/telegram-github-action@17c9ce6b4210d2659dca29d34028b02fa29d70ad # or newer tag if available
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
message: |
${{ steps.vars.outputs.announce }}
${{ steps.vars.outputs.body_safe }}
format: markdown
disable_web_page_preview: true
# Only needed for topic-enabled supergroups/channels
message_thread_id: ${{ secrets.TELEGRAM_MESSAGE_THREAD_ID }}
continue-on-error: true
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: community-release-notifier on: release: types: [ released ] workflow_dispatch: inputs: tag_name: required: true description: "Release tag_name" type: string url: required: true description: "release URL" type: string body: required: true description: "Release Body" type: string default: '' workflow_call: inputs: tag_name: required: true description: "Release tag_name" type: string url: required: true description: "release URL" type: string body: required: true description: "Release Body" type: string default: '' secrets: DISCORD_WEBHOOK_RELEASE_NOTES: description: 'Discord Webhook for Notifying Releases to Discord' required: true TELEGRAM_BOT_TOKEN: description: 'Telegram Bot Token' required: true TELEGRAM_CHAT_ID: description: 'Telegram Chat ID (group/channel/supergroup)' required: true TELEGRAM_MESSAGE_THREAD_ID: description: 'Topic / message_thread_id for Telegram forum/topic' required: true jobs: notify: timeout-minutes: 30 if: github.repository_owner == 'Acode-Foundation' runs-on: latchkey-small steps: - name: Prepare release variables id: vars env: INPUT_TAG: ${{ github.event.release.tag_name || inputs.tag_name }} INPUT_URL: ${{ github.event.release.url || inputs.url }} INPUT_BODY: ${{ github.event.release.body || inputs.body }} run: | TAG="$INPUT_TAG" URL="$INPUT_URL" # Generate a random delimiter (hex string, safe and collision-resistant) DELIMITER=$(openssl rand -hex 16 || head -c 16 /dev/urandom | xxd -p -c 16) # Escape problematic characters for MarkdownV2 (very conservative escaping) # We escape: _ * [ ] ( ) ~ ` > # + - = | { } . ! \ BODY_SAFE=$(printf '%s' "$INPUT_BODY" | \ sed 's/[_*[\]()~`>#+=|{}.!\\-]/\\&/g') TAG_SAFE=$(printf '%s' "$TAG" | sed 's/[_*[\]()~`>#+=|{}.!\\-]/\\&/g') if [[ "$TAG" == *"-nightly"* ]]; then SUFFIX=" \(Nightly Release\)" SUFFIXPLAIN=" (Nightly Release)" else SUFFIX="" SUFFIXPLAIN="" fi # Announcement line - also escape for safety ANNOUNCE_SAFE="π’ Acode [$TAG_SAFE]($URL) was just Released π${SUFFIX}\\!" echo "announce=$ANNOUNCE_SAFE" >> $GITHUB_OUTPUT { echo "body_safe<<$DELIMITER" printf '%s\n' "$BODY_SAFE" echo "$DELIMITER" } >> $GITHUB_OUTPUT # Plain (MD) Announcement for Discord ANNOUNCE_PLAIN="π’ Acode [$TAG](<$URL>) was just Released π${SUFFIXPLAIN}!" echo "announce_plain=$ANNOUNCE_PLAIN" >> $GITHUB_OUTPUT { echo "body_plain<<$DELIMITER" printf '%s\n' "$INPUT_BODY" echo "$DELIMITER" } >> $GITHUB_OUTPUT # ββββββββββββββββββββββββββββββββββββββββββββββββ # Truncate for Discord # ββββββββββββββββββββββββββββββββββββββββββββββββ - name: Truncate message for Discord id: truncate-discord uses: 2428392/gh-truncate-string-action@b3ff790d21cf42af3ca7579146eedb93c8fb0757 # v1.4.1 env: # https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true with: maxLength: 2000 stringToTruncate: | ${{ steps.vars.outputs.announce_plain }} ${{ steps.vars.outputs.body_plain }} # ββββββββββββββββββββββββββββββββββββββββββββββββ # Discord notification # ββββββββββββββββββββββββββββββββββββββββββββββββ - name: Discord Webhook (Publishing) uses: tsickert/discord-webhook@b217a69502f52803de774ded2b1ab7c282e99645 # v7.0.0 env: # https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true with: webhook-url: ${{ secrets.DISCORD_WEBHOOK_RELEASE_NOTES }} content: ${{ steps.truncate-discord.outputs.string }} flags: 4 # 1 << 2 - SUPPRESS_EMBEDS! # ββββββββββββββββββββββββββββββββββββββββββββββββ # Telegram notification - MarkdownV2 + no link preview # ββββββββββββββββββββββββββββββββββββββββββββββββ - name: Send to Telegram #if: ${{ secrets.TELEGRAM_BOT_TOKEN != '' && secrets.TELEGRAM_CHAT_ID != '' && secrets.TELEGRAM_MESSAGE_THREAD_ID != '' }} uses: Salmansha08/telegram-github-action@17c9ce6b4210d2659dca29d34028b02fa29d70ad # or newer tag if available with: to: ${{ secrets.TELEGRAM_CHAT_ID }} token: ${{ secrets.TELEGRAM_BOT_TOKEN }} message: | ${{ steps.vars.outputs.announce }} ${{ steps.vars.outputs.body_safe }} format: markdown disable_web_page_preview: true # Only needed for topic-enabled supergroups/channels message_thread_id: ${{ secrets.TELEGRAM_MESSAGE_THREAD_ID }} continue-on-error: true
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Add a job timeout so a hung step cannot burn hours of runner time.
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.