A lightweight Telegram bot that receives release events from any CI/CD pipeline and posts formatted notifications to a configured Telegram channel — with a single curl call.
CI/CD pipeline ──> POST /webhook ──> release-bot ──> sendMessage ──> Telegram channel
- Any CI/CD system — GitHub Actions, GitLab CI, Jenkins, Bitbucket, or a bare
curl - Shared-secret auth —
Authorization: Bearer <token>header; returns 401 on bad/missing tokens - JSON responses — every response is
{"ok": bool, "detail": "..."}for easy pipeline scripting - Docker-first — ships as a container; all config via environment variables, nothing hardcoded
- Fail-fast startup — missing env vars cause a non-zero exit at boot, not a silent runtime crash
Message @BotFather on Telegram → /newbot → copy the token.
Add the bot to your channel and get the chat ID (e.g. via @userinfobot).
cp .env.example .env
# Edit .env with your real values
docker compose up -dcurl -X POST http://localhost:8080/webhook \
-H "Authorization: Bearer your-shared-secret-here" \
-H "Content-Type: application/json" \
-d '{"project": "my-service", "version": "1.2.3", "message": "Bug fixes and performance improvements."}'The bot posts to your Telegram channel:
my-service v1.2.3
Bug fixes and performance improvements.
All configuration is via environment variables (or a .env file for local dev).
| Variable | Required | Description |
|---|---|---|
TELEGRAM_BOT_TOKEN |
✓ | Bot API token from @BotFather |
TELEGRAM_CHAT_ID |
✓ | Target channel/chat ID (e.g. -100123456789) |
WEBHOOK_SECRET |
✓ | Shared secret for Authorization: Bearer header |
HOST |
— | Bind address (default: 0.0.0.0) |
PORT |
— | Listen port (default: 8080) |
Send a release notification.
Headers
Authorization: Bearer <WEBHOOK_SECRET>
Content-Type: application/json
Body
{
"project": "my-service",
"version": "1.2.3",
"message": "What changed in this release."
}Responses
| Status | Body | Meaning |
|---|---|---|
200 |
{"ok": true, "detail": "Message sent to Telegram"} |
Notification delivered |
401 |
{"ok": false, "detail": "Unauthorized"} |
Missing or invalid token |
422 |
{"ok": false, "detail": "..."} |
Malformed request body |
500 |
{"ok": false, "detail": "..."} |
Telegram delivery error |
- name: Notify release
run: |
curl -fsSL -X POST ${{ secrets.RELEASE_BOT_URL }}/webhook \
-H "Authorization: Bearer ${{ secrets.RELEASE_BOT_SECRET }}" \
-H "Content-Type: application/json" \
-d "{\"project\": \"${{ github.repository }}\", \"version\": \"${{ github.ref_name }}\", \"message\": \"${{ github.event.release.body }}\"}"notify:
script:
- |
curl -fsSL -X POST "$RELEASE_BOT_URL/webhook" \
-H "Authorization: Bearer $RELEASE_BOT_SECRET" \
-H "Content-Type: application/json" \
-d "{\"project\": \"$CI_PROJECT_NAME\", \"version\": \"$CI_COMMIT_TAG\", \"message\": \"New release\"}"curl -fsSL -X POST "$RELEASE_BOT_URL/webhook" \
-H "Authorization: Bearer $RELEASE_BOT_SECRET" \
-H "Content-Type: application/json" \
-d "{\"project\": \"my-app\", \"version\": \"$VERSION\", \"message\": \"$RELEASE_NOTES\"}"Pre-built images are published to GitHub Container Registry:
docker pull ghcr.io/left-try/release-bot:latestdocker run -d \
-p 8080:8080 \
-e TELEGRAM_BOT_TOKEN=... \
-e TELEGRAM_CHAT_ID=... \
-e WEBHOOK_SECRET=... \
ghcr.io/left-try/release-bot:latestRequirements: Python 3.12+
pip install -r requirements.txt
cp .env.example .env # fill in values
uvicorn bot.main:create_app --factory --reloadRun tests:
pytestTests use httpx.AsyncClient against the ASGI app directly — no real Telegram calls, no network required.
Build Docker image:
docker build -t release-bot .