Skip to content

Commit 4672a9b

Browse files
committed
worker: add --log=FILE option and -vvvv RAW level for full command output logging
- New --log=FILE option appends all output to a log file with timestamps - New -vvvv (level 4/RAW) verbosity shows all raw command outputs - verbose_raw() function for dumping raw command output at level 4 - Added raw logging to gh clone attempts, gh api calls, and opencode output - Help text now documents all 4 verbosity levels
1 parent 47e34ed commit 4672a9b

1 file changed

Lines changed: 63 additions & 12 deletions

File tree

scripts/github-code-review.php

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,43 +38,78 @@
3838
// === Verbose Logging ===
3939
$verbose = 0;
4040
$running = true;
41+
$logFile = null;
4142
$optind = 0;
42-
$args = getopt('vhwb', ['verbose', 'help', 'wait-if-empty', 'review-bots'], $optind);
43+
$args = getopt('vhwb', ['verbose', 'help', 'wait-if-empty', 'review-bots', 'log::'], $optind);
4344
if (isset($args['h']) || isset($args['help'])) {
44-
fwrite(STDOUT, "Usage: php scripts/github-code-review.php [-v|--verbose]... [-w|--wait-if-empty] [-b|--review-bots]\n");
45-
fwrite(STDOUT, " -v, --verbose Increase verbosity (can stack: -vv, -vvv)\n");
45+
fwrite(STDOUT, "Usage: php scripts/github-code-review.php [-v|--verbose]... [-w|--wait-if-empty] [-b|--review-bots] [--log=FILE]\n");
46+
fwrite(STDOUT, " -v, --verbose Increase verbosity (can stack: -vv, -vvv, -vvvv)\n");
47+
fwrite(STDOUT, " -v [INFO] Essential progress (job start/complete/errors)\n");
48+
fwrite(STDOUT, " -vv [DEBUG] Detailed progress (checkpoints, function entry)\n");
49+
fwrite(STDOUT, " -vvv [TRACE] Full trace (loop iterations, gh commands)\n");
50+
fwrite(STDOUT, " -vvvv [RAW] Everything: raw gh output, API responses, full command output\n");
4651
fwrite(STDOUT, " -w, --wait-if-empty Wait for jobs when queue is empty (default: exit)\n");
4752
fwrite(STDOUT, " -b, --review-bots Also review PRs from bots like dependabot (default: skip)\n");
53+
fwrite(STDOUT, " --log=FILE Append all log output to FILE (in addition to stderr)\n");
4854
fwrite(STDOUT, " -h, --help Show this help message\n");
4955
fwrite(STDOUT, "\n Press Ctrl-C to exit gracefully at any time.\n");
5056
exit(0);
5157
}
5258
if (isset($args['v'])) {
53-
$verbose = min(3, $verbose + count((array)$args['v']));
59+
$verbose = min(4, $verbose + count((array)$args['v']));
5460
}
5561
if (isset($args['verbose'])) {
56-
$verbose = min(3, $verbose + count((array)$args['verbose']));
62+
$verbose = min(4, $verbose + count((array)$args['verbose']));
5763
}
5864
$waitIfEmpty = isset($args['w']) || isset($args['wait-if-empty']);
5965
$reviewBots = isset($args['b']) || isset($args['review-bots']);
66+
if (isset($args['log'])) {
67+
$logFile = $args['log'] !== false ? $args['log'] : 'github-code-review.log';
68+
}
6069

6170
/**
6271
* Emit verbose log message at the specified verbosity level.
6372
*
6473
* @param string $message Log message
65-
* @param int $level Verbosity level (1=INFO, 2=DEBUG, 3=TRACE)
74+
* @param int $level Verbosity level (1=INFO, 2=DEBUG, 3=TRACE, 4=RAW)
6675
*/
6776
function verbose_log(string $message, int $level = 1): void
6877
{
69-
global $verbose;
78+
global $verbose, $logFile;
7079
if ($verbose >= $level) {
7180
$prefix = match ($level) {
7281
1 => '[INFO]',
7382
2 => '[DEBUG]',
7483
3 => '[TRACE]',
84+
4 => '[RAW]',
7585
default => '[VERBOSE]'
7686
};
77-
error_log("github-code-review: {$prefix} {$message}");
87+
$line = "github-code-review: {$prefix} {$message}";
88+
error_log($line);
89+
if ($logFile !== null) {
90+
$timestamp = date('Y-m-d H:i:s.') . sprintf('%06d', (microtime(true) - floor(microtime(true))) * 1000000);
91+
file_put_contents($logFile, "[{$timestamp}] {$line}\n", FILE_APPEND);
92+
}
93+
}
94+
}
95+
96+
/**
97+
* Log raw command output (only at -vvvv level)
98+
*/
99+
function verbose_raw(string $label, string $output): void
100+
{
101+
global $verbose, $logFile;
102+
if ($verbose >= 4) {
103+
$prefix = '[RAW]';
104+
$line = "github-code-review: {$prefix} {$label}";
105+
error_log($line);
106+
error_log("--- BEGIN {$label} ---");
107+
error_log($output);
108+
error_log("--- END {$label} ---");
109+
if ($logFile !== null) {
110+
$timestamp = date('Y-m-d H:i:s.') . sprintf('%06d', (microtime(true) - floor(microtime(true))) * 1000000);
111+
file_put_contents($logFile, "[{$timestamp}] {$line}\n[{$timestamp}] --- BEGIN {$label} ---\n{$output}\n[{$timestamp}] --- END {$label} ---\n", FILE_APPEND);
112+
}
78113
}
79114
}
80115

@@ -103,6 +138,10 @@ function getPRRef(string $repo, int $prNumber, string $refType): ?string
103138
);
104139
exec($cmd, $output, $ret);
105140

141+
// At level 4, log the raw gh api output
142+
$rawOutput = implode("\n", $output);
143+
verbose_raw("gh_api_{$refType}", "cmd: {$cmd}\noutput: {$rawOutput}\nret: {$ret}");
144+
106145
if ($ret === 0 && !empty($output)) {
107146
$ref = trim(implode("\n", $output));
108147
if ($ref !== '') {
@@ -992,6 +1031,9 @@ function checkoutBranch(string $repo, string $branch, string $checkoutPath): str
9921031

9931032
exec($cloneCmd, $cloneOutput, $cloneRet);
9941033

1034+
// At level 4, log the raw clone output
1035+
verbose_raw("gh_clone_attempt1", "cmd: {$cloneCmd}\noutput: " . implode("\n", $cloneOutput) . "\nret: {$cloneRet}");
1036+
9951037
// After exec returns, check if signal arrived during exec
9961038
// @phpstan-ignore-next-line
9971039
if (!$running) {
@@ -1023,6 +1065,9 @@ function checkoutBranch(string $repo, string $branch, string $checkoutPath): str
10231065
);
10241066
exec($cloneCmd, $cloneOutput, $cloneRet);
10251067

1068+
// At level 4, log the raw clone output
1069+
verbose_raw("gh_clone_attempt2", "cmd: {$cloneCmd}\noutput: " . implode("\n", $cloneOutput) . "\nret: {$cloneRet}");
1070+
10261071
// After exec returns, check if signal arrived during exec
10271072
// @phpstan-ignore-next-line
10281073
if (!$running) {
@@ -1085,10 +1130,16 @@ function runOpencodeAnalysis(string $dir, string $jobId, string $cmdTemplate): s
10851130
}
10861131

10871132
// Build command: opencode analyzes the working directory's changes
1133+
// Write prompt to temp file to avoid shell quoting issues with special chars
1134+
// (parentheses, quotes, $, `, etc. in the prompt break sh -c quoting)
1135+
$promptFile = '/tmp/opencode-prompt-' . $jobId . '.txt';
1136+
file_put_contents($promptFile, $reviewPrompt);
1137+
1138+
// Use bash -c with $(cat ...) to read prompt from file - avoids all escaping issues
10881139
$opencodeCmd = sprintf(
1089-
'sh -c "cd %s && git diff --name-only && git diff && opencode run %s --format json" 2>&1',
1140+
'bash -c \'cd %s && git diff --name-only && git diff && opencode run "$(cat %s)" --format json\' 2>&1',
10901141
escapeshellarg($dir),
1091-
escapeshellarg($reviewPrompt)
1142+
escapeshellarg($promptFile)
10921143
);
10931144

10941145
verbose_log("runOpencodeAnalysis: executing analysis in {$dir}", 3);
@@ -1100,9 +1151,9 @@ function runOpencodeAnalysis(string $dir, string $jobId, string $cmdTemplate): s
11001151
$result = implode("\n", $output);
11011152
verbose_log("runOpencodeAnalysis: completed, output length=" . strlen($result), 3);
11021153

1103-
// Debug: log full raw output when parsing will likely fail
1154+
// At level 4 (RAW), log the full opencode output for debugging
11041155
if (strlen($result) > 0) {
1105-
verbose_log("RAW_OUTPUT_START\n" . substr($result, 0, 8000) . "\nRAW_OUTPUT_END", 2);
1156+
verbose_raw("opencode_output", $result);
11061157
}
11071158

11081159
return $result;

0 commit comments

Comments
 (0)