npm install # Install dependencies
npm run dev # Local dev server (wrangler dev)
npm run typecheck # TypeScript type checking
npm test # Run all tests (vitest)
npm run deploy # Deploy to Cloudflare WorkersRun typecheck before committing. Tests are required.
Cloudflare Worker that receives GitHub webhooks and forwards to Telegram.
src/
index.ts # Worker entrypoint (fetch handler)
router.ts # HMAC-SHA256 signature verification
config.ts # KV config lookup (exact → wildcard → null)
matcher.ts # Event/target matching with public visibility filter
telegram.ts # Telegram Bot API client (sendMessage, sendAlert, escapeHtml)
types.ts # Shared TypeScript types (Target, RepoConfig, AdminConfig, GitHubEvent)
formatters/
index.ts # Event type → formatter mapping + fallback
*.ts # One formatter per GitHub event type (27 total)
Config lives in Cloudflare KV (binding: TG_GH_KV). Key format:
config:owner/repo— per-repo config (exact match)config:owner/*— org-level wildcard fallbackconfig:__admin__— admin alert target
Sync tool: npx tsx scripts/sync-kv.ts config.yaml
Config validation is in scripts/validate.ts, tests in test/sync-kv.test.ts.
- Zero runtime dependencies — only
@cloudflare/workers-typesas dev dep - Formatters output HTML for Telegram's
parse_mode: "HTML" escapeHtml()on all user-supplied content before embedding in HTML- Sensitive events (security alerts) are filtered from
public: truetargets - Errors send alerts to admin chat, then return appropriate HTTP status
wrangler.tomlusesKV_ID_PLACEHOLDERandKV_PREVIEW_ID_PLACEHOLDER— replace before deploy
- Tests use vitest
test/telegram.test.ts— escapeHtmltest/matcher.test.ts— target matching with public/sensitive filteringtest/formatters.test.ts— fallback, push, release, issues formatterstest/sync-kv.test.ts— config validation