Skip to content

Commit 91a04cb

Browse files
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 dependencies
1 parent ac61e46 commit 91a04cb

6 files changed

Lines changed: 762 additions & 486 deletions

File tree

.env.dist

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# GitHub webhook HMAC secret — must match the secret configured in
2+
# https://github.com/organizations/interserver/settings/hooks
3+
GITHUB_WEBHOOKS_SECRET=
4+
5+
# Notification queue settings — when NOTIF_QUEUE_ENABLED=true the github
6+
# webhook pushes envelopes onto Redis for the teams-chat-bot to consume.
7+
# When false (default), it falls through to direct Power Automate POSTs.
8+
NOTIF_QUEUE_ENABLED=true
9+
NOTIF_QUEUE_KEY_PREFIX=notif:
10+
11+
# Redis / Dragonfly connection (used by NotificationQueue when enabled).
12+
# These are only consulted as a fallback — the canonical values come from
13+
# /home/sites/mystage/include/config/config.settings.php which src/config.php
14+
# loads automatically. Override here only when running outside the shared
15+
# InterServer environment.
16+
REDIS_HOST=dragonfly.mailbaby.net
17+
REDIS_PORT=6379
18+
19+
# Disk log verbosity for incoming events:
20+
# debug → write every event
21+
# info → write only on send-failure (recommended)
22+
# warn → don't write at all
23+
LOG_LEVEL=debug
24+
25+
# Producer-side per-event-type rate limiter window (seconds). 0 disables
26+
# (default) — recommended, since the teams-chat-bot already coalesces and
27+
# edits-on-followup downstream. Only set non-zero to suppress same-dedup_key
28+
# bursts at the webhook itself.
29+
RATE_LIMIT_WINDOW=0

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.env
12
vendor/
23
src/config.php
34
composer.lock

0 commit comments

Comments
 (0)