Forward GitHub repository and organization events to Telegram. Runs on Cloudflare Workers — no VPS, no always-on process.
Simplified Chinese: README.zh-CN.md
The screenshot is a real delivery from this repository: a push with commit details, then a delete after the Dependabot branch was removed.
The Worker accepts GitHub webhooks on POST /, verifies X-Hub-Signature-256, routes by repository or organization, and sends an HTML message to Telegram.
Recommended path: fork this repository, add four GitHub Actions secrets, then deploy with the bundled workflow. You do not need to create the Worker by hand in the Cloudflare dashboard.
- No server to keep running. Only Cloudflare Workers is used (no KV, D1, R2, or Durable Objects). Typical webhook volume fits the Workers free tier.
- Fork and deploy. Fill secrets, then run
Cloudflare Worker Deployor push a Git tag. - One Worker, many targets.
HOOK_CONFIG_JSONmapsowner/repoor an organization login to different chats and webhook secrets. - Signature required. Requests without a matching HMAC are rejected with
403. - Forks stay current. The daily
Sync Upstreamworkflow fast-forwardsmainwhen you have no fork-only commits.
Not this project: it is not a Telegram bot you chat with, and it does not speak GitLab. Unsupported GitHub events still pass signature checks, then produce no Telegram message.
flowchart LR
GitHub -->|POST / + HMAC| Worker
Worker -->|sendMessage HTML| Telegram
Labels below match EVENT_META in src/formatters/shared.ts.
| Event | Telegram title |
|---|---|
create |
Reference Created |
delete |
Reference Deleted |
discussion |
Discussion Activity |
fork |
Repository Forked |
issues |
Issue Activity |
ping |
Webhook Ping |
public |
Repository Public |
pull_request |
Pull Request Activity |
push |
Push Update |
star |
Stars Updated |
You need a Telegram bot that can send to the target chat, a Cloudflare account (Account ID + a token that can edit Workers Scripts), and a GitHub repository or organization to watch.
- Fork this repository and enable Actions on the fork.
- Add these secrets under
Settings -> Secrets and variables -> Actions:
| Secret | Purpose |
|---|---|
CLOUDFLARE_API_TOKEN |
Token used by the deploy workflow |
CLOUDFLARE_ACCOUNT_ID |
Cloudflare Account ID |
BOT_TOKEN |
Telegram bot token |
HOOK_CONFIG_JSON |
Routing JSON (must be one line) |
{"gh_webhooks":{"your-name/your-repo":{"chat_id":-1001234567890,"secret":"replace-with-random-secret"}}}chat_id may be a numeric ID (-1001234567890) or a public channel username (@channel_name). To rename the Worker, edit name in wrangler.toml (default: github-webhook-to-telegram).
- Deploy, then point GitHub at the Worker:
- Manual:
Actions -> Cloudflare Worker Deploy -> Run workflow - Tag:
git tag v1.0.0 && git push origin v1.0.0
Payload URL: https://<worker-name>.<your-subdomain>.workers.dev/
Content type: application/json
Secret: must match the selected secret in HOOK_CONFIG_JSON
Events: Send me everything
Active: checked
Start with Send me everything. After a delivery succeeds, you can narrow the event list. Full walkthrough: docs/deployment.md.
Matching order (first hit wins): organization.login, then repository.full_name. An organization route therefore overrides a repository route.
{
"gh_webhooks": {
"your-name/your-repo": {
"chat_id": -1001234567890,
"secret": "repo-secret"
},
"your-org": {
"chat_id": "@your_channel",
"secret": "org-secret"
}
}
}secret is the GitHub webhook secret, not BOT_TOKEN. A mismatch returns 403. Optional show_author defaults to true; set false to omit actor and author names from that route's Telegram messages. See docs/usage.md.
Local work is optional for the fork deploy path. Requires Node.js 24+ and pnpm 10.
pnpm install
pnpm typecheck
pnpm test
pnpm buildcp .dev.vars.example .dev.vars
pnpm devThe Worker only accepts POST /. Other paths return 404; other methods return 405. Do not commit .dev.vars.
- Deployment Overview — fork to production
- GitHub Actions Deployment — secrets, manual and tag releases
- Worker Configuration — Cloudflare, Wrangler, troubleshooting
- Usage Guide — Telegram,
HOOK_CONFIG_JSON, verification - Changelog
Forks: Sync Upstream runs daily. If your main has diverged, the workflow stops instead of overwriting; merge upstream, then rerun.
