Skip to content

Commit f21be13

Browse files
committed
update
1 parent 6a51e1d commit f21be13

43 files changed

Lines changed: 3651 additions & 296 deletions

Some content is hidden

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

.claude/skills/add-event-handler/SKILL.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ description: Adds a new GitHub event type case to the switch block in `web/githu
2626
$Url = $Entity['html_url'] ?? '';
2727
$Title = $Entity['title'] ?? $Entity['name'] ?? '';
2828

29-
$ChatMsg = "🔔 [{$User}](https://github.com/{$User}) **{$Action}** "
29+
$ChatMsg = "\u{1F514} [{$User}](https://github.com/{$User}) **{$Action}** "
3030
. "[{$Title}]({$Url}) "
3131
. "in [{$RepositoryName}](https://github.com/{$RepositoryName}).";
3232

3333
// Optional: append body preview (max 500 chars)
3434
if (!empty($Entity['body'])) {
3535
$ChatMsg .= "\n\n> " . substr($Entity['body'], 0, 500)
36-
. (strlen($Entity['body']) > 500 ? "" : "");
36+
. (strlen($Entity['body']) > 500 ? "\u2026" : "");
3737
}
3838

3939
$Msg['text'] = $ChatMsg;
@@ -71,7 +71,7 @@ description: Adds a new GitHub event type case to the switch block in `web/githu
7171
6. **Add a test fixture** under `tests/events/<event_name>/`:
7272
- `payload.json` — raw GitHub webhook payload (copy from GitHub delivery logs or docs)
7373
- `type.txt` — event name only, e.g. `your_event` (no trailing newline needed; `trim()` is applied)
74-
- Note: `expected.bin` / `discord.json` are consumed by `IrcConverter`/`DiscordConverter` tests, not by `web/github.php` — add them only if those converters also need updating.
74+
- `expected_text.txt` — expected chat message text; run `vendor/bin/phpunit tests/GithubMessageBuilderTest.php`, capture actual output, write to file
7575

7676
7. **Run quality checks** to verify no syntax errors or style violations:
7777
```bash
@@ -94,20 +94,20 @@ description: Adds a new GitHub event type case to the switch block in `web/githu
9494
$Url = $Milestone['html_url'] ?? '';
9595
$Title = $Milestone['title'] ?? '';
9696

97-
$ChatMsg = "🏁 [{$User}](https://github.com/{$User}) **{$Action}** "
97+
$ChatMsg = "\u{1F3C1} [{$User}](https://github.com/{$User}) **{$Action}** "
9898
. "milestone [{$Title}]({$Url}) "
9999
. "in [{$RepositoryName}](https://github.com/{$RepositoryName}).";
100100

101101
if (!empty($Milestone['description'])) {
102102
$ChatMsg .= "\n\n> " . substr($Milestone['description'], 0, 500)
103-
. (strlen($Milestone['description']) > 500 ? "" : "");
103+
. (strlen($Milestone['description']) > 500 ? "\u2026" : "");
104104
}
105105

106106
$Msg['text'] = $ChatMsg;
107107
SendToChat('notifications', $Msg, $useRC, $useTeams);
108108
break;
109109
```
110-
3. Created `tests/events/milestone/payload.json` and `tests/events/milestone/type.txt` containing `milestone`.
110+
3. Created `tests/events/milestone/payload.json`, `tests/events/milestone/type.txt` (`milestone`), and `tests/events/milestone/expected_text.txt`.
111111
4. Ran `vendor/bin/phpstan analyse` — no errors.
112112

113113
**Result:** `milestone` events POST to Rocket Chat and Teams with action, linked title, and optional description preview.
@@ -122,4 +122,4 @@ description: Adds a new GitHub event type case to the switch block in `web/githu
122122

123123
- **Event still hits `default:`**: The `$EventType` string comes from the `X-GitHub-Event` header. Verify your `case` string matches exactly (lowercase, underscores) — e.g. `'pull_request'` not `'pullRequest'`.
124124

125-
- **`SendToChat` returns `false` silently**: The channel key `'notifications'` must exist in both `$chatChannels['rocketchat']` and `$chatChannels['teams']` in `src/config.php`. If the URL is missing, curl will fail with HTTP 0.
125+
- **`SendToChat` returns `false` silently**: The channel key `'notifications'` must exist in both `$chatChannels['rocketchat']` and `$chatChannels['teams']` in `src/config.php`. If the URL is missing, curl will fail with HTTP 0.
Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,31 @@
11
---
22
name: add-test-fixture
3-
description: Creates a new test event fixture directory under tests/events/{event_name}/ with payload.json, type.txt, expected.bin, and discord.json. Use when user says 'add test for X event', 'create fixture', 'test event payload', or needs to add files to tests/events/. Do NOT use for modifying existing fixtures or writing unit tests that don't involve GitHub webhook payloads.
3+
description: Creates a new test event fixture directory under tests/events/{event_name}/ with payload.json, type.txt, and expected_text.txt. Use when user says 'add test for X event', 'create fixture', 'test event payload', or needs to add files to tests/events/. Do NOT use for modifying existing fixtures or writing unit tests that don't involve GitHub webhook payloads.
44
---
55
# Add Test Fixture
66

77
## Critical
88

9-
- Every fixture directory requires **all four files**`EventTest.php:64` calls `file_get_contents` on all four unconditionally; missing any will cause a fatal test error:
9+
- Every fixture directory requires **three files**`GithubMessageBuilderTest.php` reads all three; missing any will cause a fatal test error:
1010
```
1111
tests/events/deployment/type.txt
1212
tests/events/deployment/payload.json
13-
tests/events/deployment/expected.bin
14-
tests/events/deployment/discord.json
13+
tests/events/deployment/expected_text.txt
1514
```
16-
- `expected.bin` contains IRC color codes (non-printable bytes) **never hand-write it**. Use the generation workflow in Step 4.
17-
- The value in `tests/events/deployment/type.txt` must match the `X-GitHub-Event` header value exactly (e.g. `push`, `pull_request`, `ping`) — no trailing newline issues; `EventTest.php:61` trims it.
15+
- `expected_text.txt` contains plain-text chat message output **generate it by running the test harness**, not by hand.
16+
- The value in `tests/events/deployment/type.txt` must match the `X-GitHub-Event` header value exactly (e.g. `push`, `pull_request`, `ping`) — no trailing newline issues; the test trims it.
1817

1918
## Instructions
2019

2120
1. **Create the fixture directory.**
22-
```bash
23-
mkdir tests/events/deployment
24-
```
2521
Use the GitHub event name as the directory name (e.g. `deployment`, `workflow_dispatch`). For action variants, append `_{action}` (e.g. `pull_request_merged`, `issue_closed`). Verify no existing directory with that name exists under `tests/events/`.
2622

2723
2. **Write the event type file.**
28-
```bash
29-
echo -n 'deployment' > tests/events/deployment/type.txt
30-
```
3124
Content is the bare event type only — no action suffix, no newline required (the test trims it). Matches the value GitHub sends in the `X-GitHub-Event` HTTP header.
25+
Write `deployment` to `tests/events/deployment/type.txt`.
3226

3327
3. **Write the payload file.**
34-
Save a real GitHub webhook payload to `tests/events/deployment/payload.json`. Mirror the formatting of existing fixtures — tabs for indentation, escaped forward-slashes (`\/`), `JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES` style:
28+
Save a real GitHub webhook payload to `tests/events/deployment/payload.json`. Mirror the formatting of existing fixtures — tabs for indentation, `JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES` style:
3529
```json
3630
{
3731
"action": "created",
@@ -55,24 +49,17 @@ description: Creates a new test event fixture directory under tests/events/{even
5549
```
5650
Must print `0`.
5751

58-
4. **Generate the binary and Discord files using the test harness.**
59-
In `tests/EventTest.php`, uncomment the two generation lines (lines 27 and 38):
60-
```php
61-
file_put_contents( $Path . '/expected.bin', $Message . "\n" );
62-
// and
63-
file_put_contents( $Path . '/discord.json', json_encode( $Discord, JSON_PRETTY_PRINT ) . "\n" );
64-
```
65-
Run only the new fixture:
52+
4. **Generate `expected_text.txt` using the test suite.**
53+
Run the tests — the new fixture will fail and print the actual output. Use that output as the content of `expected_text.txt`, then re-run to confirm it passes:
6654
```bash
67-
vendor/bin/phpunit --filter testEvent --group default tests/EventTest.php
55+
vendor/bin/phpunit tests/GithubMessageBuilderTest.php
6856
```
69-
This writes the real IRC-formatted output (with color codes) to `tests/events/deployment/expected.bin` and the Discord embed to `tests/events/deployment/discord.json`. **Re-comment both lines immediately after**; leaving them uncommented will overwrite all fixtures on every test run.
7057

7158
5. **Verify the fixture passes.**
7259
```bash
73-
vendor/bin/phpunit tests/EventTest.php
60+
vendor/bin/phpunit tests/GithubMessageBuilderTest.php
7461
```
75-
All tests must pass. If the new fixture is listed as a failure, inspect the generated `tests/events/deployment/expected.bin` content and compare against `web/github.php`'s handler for that event type.
62+
All tests must pass.
7663

7764
## Examples
7865

@@ -82,19 +69,14 @@ description: Creates a new test event fixture directory under tests/events/{even
8269
1. Create `tests/events/deployment/`
8370
2. Write `tests/events/deployment/type.txt``deployment`
8471
3. Write `tests/events/deployment/payload.json` with a real GitHub deployment payload
85-
4. Uncomment lines 27 & 38 in `tests/EventTest.php`, run `vendor/bin/phpunit tests/EventTest.php`, re-comment
86-
5. Verify `tests/events/deployment/expected.bin` and `tests/events/deployment/discord.json` were written and tests pass
72+
4. Run `vendor/bin/phpunit tests/GithubMessageBuilderTest.php`, capture actual output, write to `tests/events/deployment/expected_text.txt`
73+
5. Re-run tests to verify they pass
8774

88-
**Result:** `tests/events/deployment/` contains all four files; `vendor/bin/phpunit tests/EventTest.php` exits green.
75+
**Result:** `tests/events/deployment/` contains all three files; `vendor/bin/phpunit tests/GithubMessageBuilderTest.php` exits green.
8976

9077
## Common Issues
9178

92-
- **`file_get_contents(...): Failed to open stream`** — one of the four required files is missing. Check `tests/events/deployment/` contains `tests/events/deployment/type.txt`, `tests/events/deployment/payload.json`, `tests/events/deployment/expected.bin`, `tests/events/deployment/discord.json`.
93-
- **`assertEquals failed: expected '' got '[10GitHub-WebHook]...'`**`tests/events/deployment/expected.bin` is empty or was hand-written without IRC codes. Re-run Step 4 generation.
94-
- **`json_decode` returns null for `discord.json`**`tests/events/deployment/discord.json` was hand-written with invalid JSON. Re-run Step 4 or validate:
95-
```bash
96-
php -r "var_dump(json_decode(file_get_contents('tests/events/deployment/discord.json')));"
97-
```
98-
Must not print `NULL`.
99-
- **New fixture not picked up by test runner** — confirm the directory is directly under `tests/events/` (not nested). `EventTest.php:51` uses a single-level `DirectoryIterator`.
79+
- **`file_get_contents(...): Failed to open stream`** — one of the three required files is missing. Check `tests/events/deployment/` contains `type.txt`, `payload.json`, `expected_text.txt`.
80+
- **`assertEquals failed`**`expected_text.txt` content doesn't match actual output. Re-run the test, capture actual output, update the file.
81+
- **New fixture not picked up by test runner** — confirm the directory is directly under `tests/events/` (not nested). The test uses a single-level `DirectoryIterator`.
10082
- **`GetEventType()` assertion fails**`tests/events/deployment/type.txt` contains extra whitespace or wrong casing. The value must exactly match the GitHub `X-GitHub-Event` header (all lowercase, underscores, e.g. `pull_request` not `Pull-Request`).

CALIBER_LEARNINGS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Caliber Learnings
2+
3+
Accumulated patterns and anti-patterns from development sessions.
4+
Auto-managed by [caliber](https://github.com/caliber-ai-org/ai-setup) — do not edit manually.
5+
6+
- **[gotcha:project]** The existing test files (`tests/EventTest.php`, `tests/IgnoredActionsThrowTest.php`, `tests/UnknownActionTest.php`, `tests/IgnoredEventTest.php`) all reference `IrcConverter` and `DiscordConverter` classes that no longer exist in `src/` — running `vendor/bin/phpunit` produces 61 errors about missing classes. These tests are stale and need to be rewritten against `GithubWebhook` directly.
7+
- **[fix:project]** `vendor/bin/phpunit` fails with "No such file or directory" if `vendor/` is not present — always run `composer install` first. The vendor directory is gitignored and absent after a fresh clone.
8+
- **[gotcha:project]** `composer.json` has no `autoload`, `autoload-dev`, or `scripts` sections — there is no PSR-4 autoloader and no `composer test` shortcut. Classes (`GithubWebhook`, `IgnoredEventException`, etc.) are loaded via manual `require` statements. Tests must bootstrap these manually or via a PHPUnit bootstrap file.
9+
- **[pattern:project]** Real GitHub webhook payloads live in `log/` as JSON files with structure `{"repo": "...", "event": "...", "data": {...payload...}}`. The `data` key holds the raw webhook payload — use these as authoritative source material when creating new fixtures under `tests/events/`.
10+
- **[gotcha:project]** In the `push` event handler, `$Msg['alias']` is set from `$Message['head_commit']['author']['name']` (commit author name), **not** `$Message['pusher']['name']`. These differ when CI or bots push commits authored by a human. Code that compares commit authors against the pusher must use `$Msg['alias']`, not `$Message['pusher']['name']`.

CLAUDE.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ 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/IgnoredEventException.php` · `src/NotImplementedException.php`
18+
- **Core**: `src/GithubWebhook.php` · `src/GithubMessageBuilder.php` · `src/IgnoredEventException.php` · `src/NotImplementedException.php`
1919
- **Config**: `src/config.php` (gitignored) — defines `GITHUB_WEBHOOKS_SECRET` and `$chatChannels['rocketchat']` / `$chatChannels['teams']`
2020
- **Logs**: `log/` — JSON files named `Ymd_His_eventtype_action_user_repo.json`
2121
- **Tests**: `tests/` via `phpunit.xml` · fixtures in `tests/events/{event_name}/`
@@ -67,8 +67,9 @@ SendToChat(string $Where, array $Payload, bool $useRC = true, bool $useTeams = t
6767
## Test Fixtures
6868

6969
Each event type has a directory under `tests/events/{event_name}/` containing:
70-
- A raw GitHub webhook payload JSON file
71-
- `type.txt` with the event name (see `tests/events/commit_comment/type.txt`)
70+
- `payload.json` — raw GitHub webhook payload
71+
- `type.txt` — event name (e.g. `tests/events/commit_comment/type.txt`)
72+
- `expected_text.txt` — expected chat message text output from `GithubMessageBuilder`
7273

7374
## Code Style
7475

composer.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,11 @@
22
"require-dev": {
33
"phpunit/phpunit": "^9.0",
44
"phpstan/phpstan": "^0.12.53"
5+
},
6+
"scripts": {
7+
"test": "vendor/bin/phpunit",
8+
"analyse": "vendor/bin/phpstan analyse",
9+
"cs-fix": "vendor/bin/php-cs-fixer fix",
10+
"cs-check": "vendor/bin/php-cs-fixer fix --dry-run"
511
}
612
}

phpunit.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" colors="true" bootstrap="tests/bootstrap.php" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
33
<testsuites>
44
<testsuite name="Tests">
55
<directory>tests</directory>

0 commit comments

Comments
 (0)