From 0fe3e5bc50f198a353d1456c5a10feb888a2da7e Mon Sep 17 00:00:00 2001 From: zhom <2717306+zhom@users.noreply.github.com> Date: Sat, 9 May 2026 21:07:32 +0400 Subject: [PATCH] feat: telegram notifications --- .github/workflows/notify-telegram.yml | 114 ++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 .github/workflows/notify-telegram.yml diff --git a/.github/workflows/notify-telegram.yml b/.github/workflows/notify-telegram.yml new file mode 100644 index 0000000..d9e5bfb --- /dev/null +++ b/.github/workflows/notify-telegram.yml @@ -0,0 +1,114 @@ +name: Notify Telegram + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + notify: + # Only post for stable releases on the canonical repo. Pre-releases + # (rolling builds, RCs) are skipped so the channel stays low-noise. + if: github.repository == 'zhom/donutbrowser' && !github.event.release.prerelease + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: main + fetch-depth: 0 + + - name: Post release announcement to Telegram + env: + TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} + TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} + TAG: ${{ github.event.release.tag_name }} + REPO: ${{ github.repository }} + run: | + if [ -z "$TELEGRAM_BOT_TOKEN" ] || [ -z "$TELEGRAM_CHAT_ID" ]; then + echo "::warning::TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID is not set — skipping Telegram notification." + exit 0 + fi + + # Resolve the previous stable tag the same way notify-discord does + # so the changelog ranges line up. + PREV_TAG=$(git tag --sort=-version:refname \ + | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ + | grep -v "^${TAG}$" \ + | head -n 1) + if [ -z "$PREV_TAG" ]; then + PREV_TAG=$(git rev-list --max-parents=0 HEAD) + fi + + strip_prefix() { echo "$1" | sed -E 's/^[a-z]+(\([^)]*\))?: //'; } + + # Build a plain bullet list from feat / fix / refactor commits. + # Other commit types (chore, docs, ci, test, deps) are intentionally + # filtered out — same convention as the Discord embed. + CHANGES="" + while IFS= read -r msg; do + [ -z "$msg" ] && continue + case "$msg" in + feat\(*\):*|feat:*|fix\(*\):*|fix:*|refactor\(*\):*|refactor:*) + CHANGES="${CHANGES}• $(strip_prefix "$msg")"$'\n' + ;; + esac + done < <(git log --pretty=format:%s "${PREV_TAG}..${TAG}") + + if [ -z "$CHANGES" ]; then + CHANGES="• See release notes."$'\n' + fi + + # HTML-escape the changelog before injecting into Telegram HTML + # mode — commit messages can legitimately contain `<`, `>`, `&`. + # The static markup around it (we control it) is left as-is. + ESCAPED_CHANGES=$(printf '%s' "$CHANGES" \ + | python3 -c "import html, sys; sys.stdout.write(html.escape(sys.stdin.read()))") + + VERSION="${TAG}" + VERSION_NUM="${TAG#v}" + RELEASE_URL="https://github.com/${REPO}/releases/tag/${VERSION}" + DL="https://github.com/${REPO}/releases/download/${VERSION}" + + # Build the API payload in one jq pass — keeps every literal + # newline, every angle bracket, and every quote correctly escaped + # for both shell and JSON. + PAYLOAD=$(jq -n \ + --arg chat_id "$TELEGRAM_CHAT_ID" \ + --arg version "$VERSION" \ + --arg changes "$ESCAPED_CHANGES" \ + --arg dl "$DL" \ + --arg vnum "$VERSION_NUM" \ + --arg release_url "$RELEASE_URL" \ + '{ + chat_id: $chat_id, + parse_mode: "HTML", + disable_web_page_preview: true, + text: ( + "Donut Browser " + $version + " released\n\n" + + $changes + "\n" + + "Download\n" + + "macOS (Apple Silicon) · " + + "macOS (Intel)\n" + + "Windows x64 · " + + "Linux x64\n\n" + + "Full release notes" + ) + }') + + # Use --fail-with-body so we surface Telegram's error JSON on 4xx/5xx + # instead of just a curl exit code. + RESPONSE=$(curl -sSL --fail-with-body \ + -H "Content-Type: application/json" \ + -d "$PAYLOAD" \ + "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage") \ + || { echo "::error::Telegram API call failed"; echo "$RESPONSE"; exit 1; } + + if [ "$(jq -r .ok <<< "$RESPONSE")" != "true" ]; then + echo "::error::Telegram API rejected the message:" + jq . <<< "$RESPONSE" + exit 1 + fi + + echo "Posted to Telegram (message_id $(jq -r .result.message_id <<< "$RESPONSE"))"