1+ # .github/workflows/telegram-notifier.yml
12name : Telegram Notifier
23
34on :
4- push :
5- branches : ["**"]
6- tags : ["*"]
75 pull_request :
86 types : [opened, reopened, synchronize, closed]
97 release :
108 types : [published]
9+ issues :
10+ types : [opened, reopened, closed, edited, labeled, unlabeled]
1111 workflow_dispatch :
1212 inputs :
1313 title :
14- description : " Manual title (e.g. 📢 Announcement )"
14+ description : " Manual title (default: 📢 Manual )"
1515 required : false
1616 default : " 📢 Manual"
1717 text :
18- description : " Message to send "
18+ description : " Message body "
1919 required : true
2020 chat_id :
2121 description : " Override TG_CHAT_ID (e.g. @Channel or numeric id)"
@@ -25,109 +25,81 @@ permissions:
2525 contents : read
2626
2727concurrency :
28- group : telegram-${{ github.ref }}-${{ github.event_name }}
28+ group : telegram-notify- ${{ github.ref }}-${{ github.event_name }}
2929 cancel-in-progress : false
3030
3131jobs :
3232 notify :
3333 runs-on : ubuntu-latest
34- environment : SANDBOX # must contain secrets TG_BOT_TOKEN and TG_CHAT_ID
35-
34+ environment : SANDBOX
3635 steps :
37- - name : Checkout (for commit log)
38- uses : actions/checkout@v4
39- with :
40- fetch-depth : 50
41-
4236 - name : Build message (plain text)
4337 id : msg
4438 shell : bash
4539 env :
4640 REPO : ${{ github.repository }}
4741 ACTOR : ${{ github.actor }}
4842 EVENT : ${{ github.event_name }}
49- REF_NAME : ${{ github.ref_name }}
50- RUN_URL : ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
51- REPO_URL : ${{ github.server_url }}/${{ github.repository }}
52-
53- GIT_BEFORE : ${{ github.event.before }}
54- GIT_SHA : ${{ github.sha }}
55-
56- PR_NUMBER : ${{ github.event.pull_request.number }}
43+ REF : ${{ github.ref_name }}
44+ RUN : ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
45+ # PR
46+ PR_NUM : ${{ github.event.pull_request.number }}
5747 PR_TITLE : ${{ github.event.pull_request.title }}
5848 PR_URL : ${{ github.event.pull_request.html_url }}
5949 PR_ACTION : ${{ github.event.action }}
6050 PR_MERGED : ${{ github.event.pull_request.merged }}
61-
51+ # Release
6252 REL_TAG : ${{ github.event.release.tag_name }}
6353 REL_NAME : ${{ github.event.release.name }}
6454 REL_URL : ${{ github.event.release.html_url }}
65-
66- WD_TEXT : ${{ github.event.inputs.text }}
55+ # Issue
56+ ISS_NUM : ${{ github.event.issue.number }}
57+ ISS_TITLE : ${{ github.event.issue.title }}
58+ ISS_URL : ${{ github.event.issue.html_url }}
59+ # Manual
6760 WD_TITLE : ${{ github.event.inputs.title }}
61+ WD_TEXT : ${{ github.event.inputs.text }}
6862 run : |
6963 set -euo pipefail
64+ header() { printf '%s\nRepo: %s\nBy: %s\nRef: %s\nRun: %s\n' "$1" "$REPO" "$ACTOR" "$REF" "$RUN"; }
65+
66+ case "$EVENT" in
67+ workflow_dispatch)
68+ TITLE="${WD_TITLE:-📢 Manual}"
69+ MSG="$(header "$TITLE")"
70+ [[ -n "${WD_TEXT:-}" ]] && MSG+=$'\n'"${WD_TEXT}"
71+ ;;
72+ pull_request)
73+ if [[ "${PR_ACTION}" == "closed" ]]; then
74+ [[ "${PR_MERGED}" == "true" ]] && STATUS="PR merged ✅" || STATUS="PR closed ❌"
75+ else
76+ STATUS="PR updated ✏️"
77+ fi
78+ MSG="$(header "$STATUS")"$'\n'"#${PR_NUM}: ${PR_TITLE}"$'\n'"${PR_URL}"
79+ ;;
80+ release)
81+ NAME="${REL_NAME:-$REL_TAG}"
82+ MSG="$(header 'Release published 🏷️')"$'\n'"Tag: ${REL_TAG}"$'\n'"Name: ${NAME}"$'\n'"${REL_URL}"
83+ ;;
84+ issues)
85+ case "${{ github.event.action }}" in
86+ opened) STATUS="Issue opened 🐞" ;;
87+ reopened) STATUS="Issue reopened ♻️" ;;
88+ closed) STATUS="Issue closed ✅" ;;
89+ edited) STATUS="Issue edited ✏️" ;;
90+ labeled) STATUS="Issue labeled 🏷️" ;;
91+ unlabeled) STATUS="Issue unlabeled 🏷️" ;;
92+ *) STATUS="Issue update 📌" ;;
93+ esac
94+ MSG="$(header "$STATUS")"$'\n'"#${ISS_NUM}: ${ISS_TITLE}"$'\n'"${ISS_URL}"
95+ ;;
96+ *)
97+ MSG="$(header "Event: $EVENT")"
98+ ;;
99+ esac
70100
71- header() {
72- printf '%s\nRepo: %s\nBy: %s\nRef: %s\nRun: %s\n' \
73- "$1" "$REPO" "$ACTOR" "$REF_NAME" "$RUN_URL"
74- }
75-
76- MESSAGE=""
77-
78- if [[ "$EVENT" == "workflow_dispatch" ]]; then
79- TITLE="${WD_TITLE:-📢 Manual}"
80- MESSAGE="$(header "$TITLE")"
81- [[ -n "${WD_TEXT:-}" ]] && MESSAGE+=$'\n'"${WD_TEXT}"
82-
83- elif [[ "$EVENT" == "push" ]]; then
84- BEFORE="${GIT_BEFORE:-}"
85- AFTER="$GIT_SHA"
86-
87- if [[ -z "$BEFORE" || "$BEFORE" =~ ^0+$ ]]; then
88- mapfile -t LINES < <(git log -n 10 --pretty=format:'%s%x1f%h' "$AFTER" || true)
89- else
90- mapfile -t LINES < <(git log --pretty=format:'%s%x1f%h' "$BEFORE..$AFTER" | head -n 10 || true)
91- fi
92-
93- COMMITS=""
94- if [[ ${#LINES[@]} -eq 0 ]]; then
95- COMMITS="- (no commit messages found)"
96- else
97- ACTOR_URL="https://github.com/${ACTOR}"
98- for row in "${LINES[@]}"; do
99- IFS=$'\x1f' read -r subj short <<<"$row"
100- COMMITS+="- ${subj} (${short}) by ${ACTOR_URL}"$'\n'
101- done
102- COMMITS="${COMMITS%$'\n'}"
103- fi
104-
105- MESSAGE="$(header '📣 Last 10 commits')"
106- MESSAGE+=$'\n'"${COMMITS}"$'\n\n'"Repo: ${REPO_URL}"
107-
108- elif [[ "$EVENT" == "pull_request" ]]; then
109- if [[ "$PR_ACTION" == "closed" ]]; then
110- [[ "${PR_MERGED}" == "true" ]] && STATUS="PR merged ✅" || STATUS="PR closed ❌"
111- else
112- STATUS="PR updated ✏️"
113- fi
114- MESSAGE="$(header "$STATUS")"
115- MESSAGE+=$'\n'"#${PR_NUMBER}: ${PR_TITLE}"$'\n'"${PR_URL}"
116-
117- elif [[ "$EVENT" == "release" ]]; then
118- NAME="${REL_NAME:-$REL_TAG}"
119- MESSAGE="$(header 'Release published 🏷️')"
120- MESSAGE+=$'\n'"Tag: ${REL_TAG}"$'\n'"Name: ${NAME}"$'\n'"${REL_URL}"
121-
122- else
123- MESSAGE="$(header "Event: $EVENT")"
124- fi
125-
126- # Write multi-line output safely (no EOF pitfalls)
127101 {
128- printf 'text<<MSGEOF\n'
129- printf '%s\n' "$MESSAGE"
130- printf 'MSGEOF\n'
102+ printf 'text<<MSGEOF\n'; printf '%s\n' "$MSG"; printf 'MSGEOF\n'
131103 } >> "$GITHUB_OUTPUT"
132104
133105 - name : Send to Telegram (plain text)
@@ -142,15 +114,10 @@ jobs:
142114 CHAT_ID="${OVERRIDE_CHAT_ID:-$TG_CHAT_ID_DEFAULT}"
143115 [[ -n "${TG_BOT_TOKEN:-}" && -n "${CHAT_ID:-}" ]] || { echo "Missing TG secrets"; exit 1; }
144116
145- # Send as plain text (no parse_mode) so spacing/lines stay exactly as built
146117 RESP="$(curl -sS -X POST "https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMessage" \
147118 -H 'Content-Type: application/json' \
148- -d "$(jq -n \
149- --arg chat_id "$CHAT_ID" \
150- --arg text "$TEXT" \
119+ -d "$(jq -n --arg chat_id "$CHAT_ID" --arg text "$TEXT" \
151120 '{chat_id:$chat_id, text:$text, disable_web_page_preview:true}')")"
152-
153121 echo "Telegram response: $RESP"
154122 echo "$RESP" | jq -e '.ok == true' >/dev/null
155-
156- echo "✅ Message sent to Telegram."
123+ echo "✅ Message sent."
0 commit comments