Skip to content

Commit ccfddee

Browse files
committed
update
1 parent 7599e38 commit ccfddee

9 files changed

Lines changed: 214 additions & 23 deletions

.claude/settings.json

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,6 @@
5151
"description": "Caliber: finalizing session learnings"
5252
}
5353
]
54-
},
55-
{
56-
"matcher": "",
57-
"hooks": [
58-
{
59-
"type": "command",
60-
"command": "caliber refresh --quiet",
61-
"description": "Caliber: auto-refreshing docs based on code changes"
62-
}
63-
]
6454
}
6555
]
6656
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"require-dev": {
88
"phpunit/phpunit": "^9.0",
9-
"phpstan/phpstan": "^0.12.53"
9+
"phpstan/phpstan": "^1.8"
1010
},
1111
"autoload": {
1212
"classmap": ["src/"]

phpstan.neon

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
parameters:
2-
checkMissingIterableValueType: false
32
level: 6
43
bootstrapFiles:
54
- phpstan-bootstrap.php
65
paths:
76
- .
8-
excludes_analyse:
7+
excludePaths:
98
- vendor
109
- examples
1110
- public
11+
treatPhpDocTypesAsCertain: false
12+
ignoreErrors:
13+
- identifier: missingType.iterableValue
14+
- identifier: missingType.generics
15+
-
16+
message: "~While loop condition is always true~"
17+
path: scripts/github-code-review.php
18+
reportUnmatchedIgnoredErrors: false

scripts/analyze_fields.php

100644100755
File mode changed.

scripts/filter_webhook.php

100644100755
File mode changed.
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* GitHub PR Code Review Queue — Listing CLI
6+
*
7+
* Read-only peek into the `codereview:queue` Redis list. Does NOT consume
8+
* (uses LRANGE, not RPOP). Safe to run while the worker is processing.
9+
*
10+
* Usage:
11+
* php scripts/github-code-review-list.php
12+
* php scripts/github-code-review-list.php --limit 20
13+
* php scripts/github-code-review-list.php --json
14+
* php scripts/github-code-review-list.php --verbose
15+
* php scripts/github-code-review-list.php --repo owner/name
16+
* php scripts/github-code-review-list.php --metrics
17+
*/
18+
19+
require_once __DIR__ . '/../vendor/autoload.php';
20+
require_once __DIR__ . '/../src/CodeReviewQueue.php';
21+
22+
$envFile = __DIR__ . '/../.env';
23+
if (file_exists($envFile)) {
24+
$dotenv = \Dotenv\Dotenv::createImmutable(dirname(__DIR__));
25+
$dotenv->load();
26+
}
27+
28+
$opts = parseArgs($argv);
29+
if (!empty($opts['help'])) {
30+
printUsage();
31+
exit(0);
32+
}
33+
34+
$host = getenv('REDIS_HOST') ?: '67.217.60.234';
35+
$port = (int)(getenv('REDIS_PORT') ?: 6379);
36+
37+
try {
38+
$redis = new \Predis\Client([
39+
'scheme' => 'tcp',
40+
'host' => $host,
41+
'port' => $port,
42+
'timeout' => 2.0,
43+
]);
44+
$redis->connect();
45+
} catch (\Throwable $e) {
46+
fwrite(STDERR, "Redis connect failed ({$host}:{$port}): {$e->getMessage()}\n");
47+
exit(2);
48+
}
49+
50+
$queueLen = (int)$redis->llen(CodeReviewQueue::QUEUE_KEY);
51+
$enqueued = (int)($redis->get(CodeReviewQueue::METRICS_KEY) ?? 0);
52+
53+
if (!empty($opts['metrics'])) {
54+
echo json_encode([
55+
'queue_key' => CodeReviewQueue::QUEUE_KEY,
56+
'queue_depth' => $queueLen,
57+
'total_enqueued' => $enqueued,
58+
'redis_host' => $host,
59+
'redis_port' => $port,
60+
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
61+
exit(0);
62+
}
63+
64+
// LRANGE 0 N-1 — newest-first because workers RPOP and producers LPUSH
65+
$limit = isset($opts['limit']) ? max(1, (int)$opts['limit']) : 50;
66+
$stop = $limit - 1;
67+
$raw = $redis->lrange(CodeReviewQueue::QUEUE_KEY, 0, $stop);
68+
69+
$entries = [];
70+
foreach ($raw as $idx => $json) {
71+
$env = json_decode($json, true);
72+
if (!is_array($env)) {
73+
fwrite(STDERR, "skip: index {$idx} is not valid JSON\n");
74+
continue;
75+
}
76+
if (!empty($opts['repo']) && ($env['repo'] ?? '') !== $opts['repo']) {
77+
continue;
78+
}
79+
$entries[] = $env;
80+
}
81+
82+
if (!empty($opts['json'])) {
83+
echo json_encode([
84+
'queue_depth' => $queueLen,
85+
'total_enqueued' => $enqueued,
86+
'shown' => count($entries),
87+
'limit' => $limit,
88+
'entries' => $entries,
89+
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "\n";
90+
exit(0);
91+
}
92+
93+
printf("Queue: %s depth=%d total_enqueued=%d shown=%d/%d\n",
94+
CodeReviewQueue::QUEUE_KEY, $queueLen, $enqueued, count($entries), $limit);
95+
echo str_repeat('-', 100) . "\n";
96+
97+
if ($entries === []) {
98+
echo "(no entries)\n";
99+
exit(0);
100+
}
101+
102+
foreach ($entries as $i => $e) {
103+
$ts = (int)($e['ts'] ?? 0);
104+
$when = $ts > 0 ? date('Y-m-d H:i:s', $ts) : '?';
105+
$age = $ts > 0 ? humanAge(time() - $ts) : '?';
106+
$action = $e['action'] ?? '?';
107+
$repo = $e['repo'] ?? '?';
108+
$prNum = $e['pr_number'] ?? '?';
109+
$head = $e['head_branch'] ?? '?';
110+
$base = $e['base_branch'] ?? '?';
111+
$author = $e['author'] ?? '?';
112+
$sha = substr((string)($e['sha'] ?? ''), 0, 7);
113+
$retries = (int)($e['retry_count'] ?? 0);
114+
$id = $e['id'] ?? '?';
115+
116+
printf("[%2d] %s (%s ago)\n", $i, $when, $age);
117+
printf(" %s#%s %s %s -> %s by %s%s\n",
118+
$repo, $prNum, $action, $head, $base, $author,
119+
$sha !== '' ? " sha={$sha}" : '');
120+
if ($retries > 0) {
121+
printf(" retry_count=%d\n", $retries);
122+
}
123+
if (!empty($opts['verbose'])) {
124+
printf(" id=%s\n", $id);
125+
if (!empty($e['pr_url'])) {
126+
printf(" %s\n", $e['pr_url']);
127+
}
128+
}
129+
echo "\n";
130+
}
131+
132+
// ---------- helpers ----------
133+
134+
function parseArgs(array $argv): array
135+
{
136+
$o = [];
137+
for ($i = 1, $n = count($argv); $i < $n; $i++) {
138+
$a = $argv[$i];
139+
switch ($a) {
140+
case '-h':
141+
case '--help':
142+
$o['help'] = true;
143+
break;
144+
case '--json':
145+
$o['json'] = true;
146+
break;
147+
case '--verbose':
148+
case '-v':
149+
$o['verbose'] = true;
150+
break;
151+
case '--metrics':
152+
$o['metrics'] = true;
153+
break;
154+
case '--limit':
155+
$o['limit'] = $argv[++$i] ?? '';
156+
break;
157+
case '--repo':
158+
$o['repo'] = $argv[++$i] ?? '';
159+
break;
160+
default:
161+
fwrite(STDERR, "unknown option: {$a}\n");
162+
printUsage();
163+
exit(1);
164+
}
165+
}
166+
return $o;
167+
}
168+
169+
function printUsage(): void
170+
{
171+
echo <<<TXT
172+
Usage: php scripts/github-code-review-list.php [options]
173+
174+
Peek (non-destructive) at the codereview:queue Redis list.
175+
176+
Options:
177+
--limit N Show at most N entries (default 50, newest first).
178+
--repo OWNER/REPO
179+
Filter to a single repository.
180+
--json Output the full envelopes as JSON (machine-readable).
181+
--metrics Print only queue depth + total_enqueued counter.
182+
-v, --verbose Include envelope id and PR URL in the human output.
183+
-h, --help Show this help.
184+
185+
Env: REDIS_HOST, REDIS_PORT (defaults match CodeReviewQueue).
186+
187+
TXT;
188+
}
189+
190+
function humanAge(int $secs): string
191+
{
192+
if ($secs < 60) return $secs . 's';
193+
if ($secs < 3600) return intdiv($secs, 60) . 'm';
194+
if ($secs < 86400) return intdiv($secs, 3600) . 'h';
195+
return intdiv($secs, 86400) . 'd';
196+
}

scripts/github-code-review.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
* while true; do php scripts/github-code-review.php; sleep 1; done
2121
*/
2222

23-
declare(strict_types=1);
24-
2523
require_once __DIR__ . '/../vendor/autoload.php';
2624
require_once __DIR__ . '/../src/CodeReviewQueue.php';
2725

web/github-old.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
}
7272
// no break
7373
case 'push':
74-
$Branch = isset($Message['ref']) && !is_null($Message['ref']) ? str_replace('refs/heads/', '', $Message['ref']) : '';
74+
$Branch = isset($Message['ref']) && $Message['ref'] !== null ? str_replace('refs/heads/', '', $Message['ref']) : '';
7575
if (isset($Message['head_commit']['message'])) {
7676
$CommitMsg = $Message['head_commit']['message'];
7777
} elseif (isset($Message['data']['issue']['title'])) {

web/github.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ function addUniversalRepoFields(array $whitelist): array
127127
$Builder = new GithubMessageBuilder($EventType, $Payload);
128128
try {
129129
$Built = $Builder->build();
130-
$text = $Built['text'] ?? '';
130+
$text = $Built['text'];
131131
} catch (\Throwable $e) {
132132
// Builder may not handle every event; carry an empty text and let
133133
// the bot decide what to do with the raw data.
@@ -188,7 +188,7 @@ function addUniversalRepoFields(array $whitelist): array
188188
function pickRoom(string $repo): string
189189
{
190190
if (strpos($repo, 'sugarcraft/') === 0
191-
|| in_array($repo, ['detain/CandyCore', 'detain/scoop-emulators', 'detain/detain', 'detain/sugarcraft', 'detain/watchable', 'detain/php-dup-finder'], true)) {
191+
|| in_array($repo, ['detain/CandyCore', 'detain/scoop-emulators', 'detain/detain', 'detain/sugarcraft', 'detain/watchable', 'detain/php-dup-finder', 'interserver/interserver-api-samples'], true)) {
192192
return 'int-dev-announce';
193193
}
194194
return 'notifications';
@@ -325,7 +325,7 @@ function filterWebhookPayload(array $data, array $whitelist, string $event): arr
325325
$childWl[substr($wlPath, strlen($currentPath) + 1)] = true;
326326
}
327327
}
328-
$childResult = filterRecursive($value, $childWl);
328+
$childResult = githubFilterRecursive($value, $childWl);
329329
if (!empty($childResult)) {
330330
$result[$key] = $childResult;
331331
}
@@ -341,7 +341,7 @@ function filterWebhookPayload(array $data, array $whitelist, string $event): arr
341341
}
342342
}
343343
if (!empty($childWl)) {
344-
$childResult = filterRecursive($value, $childWl);
344+
$childResult = githubFilterRecursive($value, $childWl);
345345
if (!empty($childResult)) {
346346
$result[$key] = $childResult;
347347
}
@@ -355,7 +355,7 @@ function filterWebhookPayload(array $data, array $whitelist, string $event): arr
355355
/**
356356
* Recursively filter array with stripped whitelist (prefix already removed)
357357
*/
358-
function filterRecursive(array $data, array $whitelist): array
358+
function githubFilterRecursive(array $data, array $whitelist): array
359359
{
360360
$result = [];
361361

@@ -408,7 +408,7 @@ function filterRecursive(array $data, array $whitelist): array
408408
$childWl[substr($wlPath, strlen($currentPath) + 1)] = true;
409409
}
410410
}
411-
$childResult = filterRecursive($value, $childWl);
411+
$childResult = githubFilterRecursive($value, $childWl);
412412
if (!empty($childResult)) {
413413
$result[$key] = $childResult;
414414
}
@@ -424,7 +424,7 @@ function filterRecursive(array $data, array $whitelist): array
424424
}
425425
}
426426
if (!empty($childWl)) {
427-
$childResult = filterRecursive($value, $childWl);
427+
$childResult = githubFilterRecursive($value, $childWl);
428428
if (!empty($childResult)) {
429429
$result[$key] = $childResult;
430430
}

0 commit comments

Comments
 (0)