Skip to content

Commit 1827443

Browse files
committed
for the 56 github event+action notification combinations, i setup rules for fields to exclude that arent needed for that event, cutting the data down by 83% (in total github has sent us 3.6gb of data in event notifications, this brings that down to 614mb) making it much easier to look at/work with and pass round.
1 parent 91a04cb commit 1827443

72 files changed

Lines changed: 292999 additions & 30 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# GitHub Webhooks RocketChat/Teams Announcer
22

3-
PHP webhook receiver (`web/github.php`) that validates GitHub event signatures, routes by event type, logs to `log/`, and POSTs to Rocket Chat + Microsoft Teams.
3+
PHP webhook receiver (`web/github.php`) that validates GitHub event signatures, builds chat-formatted notifications, and enqueues them to Redis (with direct Power Automate POST fallback) for RocketChat + Microsoft Teams delivery.
44

55
## Commands
66

@@ -15,44 +15,43 @@ vendor/bin/php-cs-fixer fix
1515
## Architecture
1616

1717
- **Entry**: `web/github.php` (active) · `web/github-old.php` (legacy, RC-only)
18-
- **Core**: `src/GithubWebhook.php` · `src/GithubMessageBuilder.php` · `src/IgnoredEventException.php` · `src/NotImplementedException.php`
19-
- **Config**: `src/config.php` (gitignored) — defines `GITHUB_WEBHOOKS_SECRET` and `$chatChannels['rocketchat']` / `$chatChannels['teams']`
20-
- **Logs**: `log/` — JSON files named `Ymd_His_eventtype_action_user_repo.json`
18+
- **Core**: `src/GithubWebhook.php` · `src/GithubMessageBuilder.php` · `src/NotificationQueue.php` · `src/IgnoredEventException.php` · `src/NotImplementedException.php`
19+
- **Config**: `.env` (copied from `.env.dist`) — defines `GITHUB_WEBHOOKS_SECRET`, `NOTIF_QUEUE_ENABLED`, `NOTIF_QUEUE_KEY_PREFIX`, `REDIS_HOST`, `REDIS_PORT`, `LOG_LEVEL`, `RATE_LIMIT_WINDOW`. RocketChat / Teams webhook URLs live in `src/config.php` (gitignored) under `$chatChannels['rocketchat']` / `$chatChannels['teams']`
20+
- **Logs**: `log/Y/m/d/` — JSON files named `His_eventtype_action_user_repo.json` (verbosity controlled by `LOG_LEVEL`)
21+
- **Field analysis**: `scripts/analyze_fields.php`, `scripts/filter_webhook.php`, `scripts/filter_webhook_batch.php` produce reports under `field_analysis_full/` (per-group JSON, `frequency_matrix.json`, `FIELD_CATEGORIZATION.md`)
2122
- **Tests**: `tests/` via `phpunit.xml` · fixtures in `tests/events/{event_name}/`
2223
- **Quality**: `phpstan.neon` · `phpstan-bootstrap.php` · `.php-cs-fixer.dist.php` (PSR2 + PHP74Migration)
2324
- **CI**: `.github/` — GitHub Actions workflows (`.github/workflows/ci.yml`)
2425

2526
## Event Handling Pattern
2627

27-
All event handling lives in `web/github.php` inside a `switch ($EventType)` block:
28+
All event handling lives in `web/github.php`:
2829

2930
```php
3031
// 1. Validate signature — always first
3132
if (!$Hook->ValidateHubSignature(GITHUB_WEBHOOKS_SECRET)) {
3233
throw new Exception('Secret validation failed.');
3334
}
34-
// 2. Log every event to log/ before processing
35-
file_put_contents(__DIR__.'/../log/'.date('Ymd_His').'_'.$EventType
36-
.(isset($Message['action']) ? '_'.$Message['action'] : '')
37-
.'_'.$User.'_'.str_replace(['/', '-', ' '], '_', $RepositoryName).'.json',
38-
json_encode($log, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
39-
// 3. Route by event type — $Builder->build() called before switch
40-
switch ($EventType) {
41-
case 'push': /* ... */ SendToChat($channelName, $Msg, $useRC, $useTeams); break;
42-
default: SendToChat($channelName, $Msg, $useRC, $useTeams); break;
43-
}
35+
// 2. Pick room from $RepositoryName ('int-dev-announce' for sugarcraft/* and a
36+
// short detain/* allowlist; otherwise 'notifications')
37+
// 3. Build the chat-formatted message
38+
$Builder = new GithubMessageBuilder($EventType, $Message);
39+
$Msg = $Builder->build();
40+
// 4. Enqueue to Redis; falls back to direct Power Automate POST when disabled
41+
// or unavailable
42+
$queue = new NotificationQueue();
43+
$queue->enqueueMessage($room, $Msg['text'], $dedupKey, $EventType, $action, $RepositoryName, $Message, $fallbackWebhookUrl);
44+
// 5. Log disposition via NotificationQueue::getLastStatus()
4445
```
4546

46-
## SendToChat Signature
47+
## NotificationQueue
4748

48-
```php
49-
SendToChat(string $Where, array $Payload, bool $useRC = true, bool $useTeams = true): bool
50-
```
51-
- `$Where` maps to `$chatChannels['rocketchat'][$Where]` and `$chatChannels['teams'][$Where]`
52-
- Pre-switch sets `$channelName = 'notifications'` (or `'int-dev-announce'` for `sugarcraft/*` and `detain/scoop-emulators` / `detain/detain` / `detain/sugarcraft`); pass it as `$Where`
53-
- Pre-switch defaults: `$useRC = false`, `$useTeams = true` — set `$useRC = true` per-case to enable Rocket Chat
54-
- Teams payload wraps `$Payload['text']` in `['type' => 'message', 'message' => ...]`
55-
- Always set `$useRC`/`$useTeams` flags per-case; some repos skip Teams (see `issues` case)
49+
`src/NotificationQueue.php` enqueues a JSON envelope to Redis via `LPUSH` when `NOTIF_QUEUE_ENABLED=true` (default); otherwise it POSTs directly to the Power Automate `fallback_webhook_url`.
50+
51+
- **Envelope keys**: `v`, `id` (uuid), `ts`, `expires_at`, `room`, `type`, `message`, `card`, `extra.dedup_key`, `extra.event_type`, `extra.action`, `extra.repo`, `extra.data`, `extra.source`, `fallback_webhook_url`
52+
- **Dedup keys** (per event): `github:push:{repo}:{branch}` · `github:issue:{repo}:{number}` · `github:pr:{repo}:{number}` · `github:checkrun:{repo}:{sha7}` · `github:check:{repo}:{sha7}` · `github:wf:{repo}:{branch}:{name}` · `github:wfjob:{repo}:{branch}:{jobName}` · `github:wiki:{repo}` · `github:status:{repo}:{sha7}` · `github:{event}:{repo}` for `star`/`watch`/`fork`/`ping`
53+
- **Oversize handling**: when the JSON exceeds 256KB, `extra.data` is stripped first, then the message text is truncated
54+
- **`getLastStatus()`** returns one of: `queued`, `direct_flag_off`, `direct_no_redis`, `direct_redis_exception`, `direct_oversize`, `failed_no_fallback`
5655

5756
## Exception Handling
5857

@@ -93,19 +92,14 @@ caliber refresh && git add CLAUDE.md .claude/ .cursor/ .github/copilot-instructi
9392
Read `CALIBER_LEARNINGS.md` for patterns and anti-patterns learned from previous sessions.
9493
These are auto-extracted from real tool usage — treat them as project-specific rules.
9594

96-
<!-- caliber:managed:model-config -->
9795
## Model Configuration
9896

9997
Recommended default: `claude-sonnet-4-6` with high effort (stronger reasoning; higher cost and latency than smaller models).
10098
Smaller/faster models trade quality for speed and cost — pick what fits the task.
10199
Pin your choice (`/model` in Claude Code, or `CALIBER_MODEL` when using Caliber with an API provider) so upstream default changes do not silently change behavior.
102100

103-
<!-- /caliber:managed:model-config -->
104-
105-
<!-- caliber:managed:sync -->
106101
## Context Sync
107102

108103
This project uses [Caliber](https://github.com/caliber-ai-org/ai-setup) to keep AI agent configs in sync across Claude Code, Cursor, Copilot, and Codex.
109104
Configs update automatically before each commit via `caliber refresh`.
110105
If the pre-commit hook is not set up, run `/setup-caliber` to configure everything automatically.
111-
<!-- /caliber:managed:sync -->

event_actions.txt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
check_run:completed,created
2+
check_suite:completed
3+
create:create
4+
delete:
5+
dependabot_alert:auto_dismissed,auto_reopened,created,fixed,reintroduced
6+
deploy_key:created
7+
deployment:created
8+
deployment_status:created
9+
dynamic:
10+
fork:
11+
gollum:created,edited
12+
issue_comment:created,edited
13+
issues:closed,edited,labeled,opened,reopened
14+
label:created
15+
page_build:
16+
ping:created,edited,started
17+
pull_request:assigned,closed,created,edited,labeled,opened,resolved,submitted,synchronize
18+
pull_request_review:created,resolved,submitted
19+
pull_request_review_comment:created
20+
pull_request_review_thread:resolved
21+
push:
22+
release:created,deleted,edited,published,released
23+
repository:create,created,edited,renamed,resolve
24+
repository_vulnerability_alert:create,resolve
25+
schedule:
26+
security_and_analysis:
27+
star:created
28+
status:created
29+
watch:started
30+
workflow_dispatch:
31+
workflow_job:completed,in_progress,queued,waiting
32+
workflow_run:completed,in_progress,requested

0 commit comments

Comments
 (0)