Commit 91a04cb
committed
Refactor webhook to use Redis queue with NotificationQueue class
Architecture Changes:
- Add NotificationQueue class (src/NotificationQueue.php) as producer-side counterpart
to teams-chat-bot's Redis queue. Enqueues JSON envelopes with message text, room,
dedup_key, and full GitHub payload. Falls back to direct Power Automate POST if Redis
is unavailable so events are never silently dropped.
- Add GithubMessageBuilder class (src/GithubMessageBuilder.php) extracting all message
formatting logic from github.php into a dedicated, testable class with build() method
returning ['avatar' => ..., 'alias?' => ..., 'text' => ...].
- Refactor web/github.php to use the new classes instead of inline message building
and direct curl calls to RocketChat/Teams. Now validates, picks room, builds dedup key,
rate-limits optionally, formats message via GithubMessageBuilder, and enqueues via
NotificationQueue.
- Remove inline SendToChat(), WildCard(), and full switch-case event handlers from github.php.
These are replaced by GithubMessageBuilder buildText() method which handles: issues,
pull_request, push, check_suite/check_run, workflow_run/workflow_job, gollum, and default.
New Dependencies (composer.json):
- predis/predis ^2.0 — Redis client for NotificationQueue
- vlucas/phpdotenv ^5.5 — Environment variable loading from .env
- Add autoload classmap for src/ directory
Environment Configuration (.env.dist):
- GITHUB_WEBHOOKS_SECRET — HMAC secret for webhook validation
- NOTIF_QUEUE_ENABLED=true — Enable Redis queue (default), fall back to direct POST when false
- NOTIF_QUEUE_KEY_PREFIX=notif: — Redis key prefix
- REDIS_HOST=dragonfly.mailbaby.net, REDIS_PORT=6379 — Redis connection (fallback)
- LOG_LEVEL=debug — Disk log verbosity (debug/info/warn)
- RATE_LIMIT_WINDOW=0 — Producer-side rate limiter window in seconds (0=disabled, recommended)
NotificationQueue Features:
- Envelope v1 format with uuid, ts, expires_at, room, type, message, card, extra, fallback_webhook_url
- MAX_BYTES=262144 (256KB) — strips raw payload first if oversized, then truncates message
- TTL_SECONDS=300 — envelope expiration
- Per-event dedup keys: github:push:{repo}:{branch}, github:issue:{repo}:{num}, etc.
- shouldSendOrSuppress() — SET/GET-based rate limiter using Redis SETEX with NX flag
- Dispositions: queued, direct_flag_off, direct_no_redis, direct_redis_exception, direct_oversize, failed_no_fallback
Room Routing:
- int-dev-announce: sugarcraft/* repos + detain/{CandyCore,scoop-emulators,detain,sugarcraft,watchable,php-dup-finder}
- notifications: all other repos
Deduplication Keys per event type:
- push: github:push:{repo}:{branch}
- issues: github:issue:{repo}:{number}
- pull_request: github:pr:{repo}:{number}
- check_run: github:checkrun:{repo}:{sha7}
- check_suite: github:check:{repo}:{sha7}
- workflow_run: github:wf:{repo}:{branch}:{name}
- workflow_job: github:wfjob:{repo}:{branch}:{jobName}
- gollum: github:wiki:{repo}
- status: github:status:{repo}:{sha7}
- star/watch/fork: github:{event}:{repo}
- ping: github:ping:{repo}
Logging:
- GITHUB_LOG_DIR = log/ — daily subdirectories (Y/m/d/)
- github_log_event() function for debug-level disk logging
- error_log for disposition reporting: github: disp={queued|direct_...} {event}({action}) repo={repo} room={room} dedup={key} text="..."
README Updated:
- Complete architecture diagram with flow
- Configuration reference for all .env variables
- RocketChat/Teams channel URL table
- Event handling flow description
- Supported events table with emoji and description
- Message format features (markdown links, branch backticks, labels, truncation)
- Events ignored by design table
- NotificationQueue envelope format and delivery flow
- Deduplication key formats table
- Dispositions table
- Logging directory structure
- GithubWebhook and GithubMessageBuilder API reference
- Test fixtures listing (46 event types)
- Quality tools and dependencies1 parent ac61e46 commit 91a04cb
6 files changed
Lines changed: 762 additions & 486 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
2 | 3 | | |
3 | 4 | | |
| |||
0 commit comments