mirror of
https://github.com/Jeuners/ECC.git
synced 2026-09-09 15:02:30 +02:00
fix(hooks,lib): fix hook detection and parsing edge cases (#2405)
* fix(hooks,lib): fix hook detection and parsing edge cases
- auto-tmux-dev: dev\b -> dev(?![\w-]) so one-shot dev-build/dev-docs scripts
are not detached into tmux; align command shapes (yarn run dev, bun dev) with
pre-bash-dev-server-block.js DEV_PATTERN.
- pre-bash-commit-quality: skip obvious non-secret placeholders (env refs,
${...}, <...>, whitelisted tokens) in the api-key rule without suppressing
real high-entropy secrets; make -m message extraction quote- and
escaped-quote-aware so `-m "fix: \"x\""` / apostrophes are not truncated.
- pre-compact: annotate the CURRENT worktree's session (match **Worktree:** /
legacy **Project:**) instead of the newest *-session.tmp across all projects,
layered onto the LLM-summary flow from #2388; a present-but-blank Worktree
header is treated as non-legacy (no foreign project fallback).
- shell-substitution: stop double-appending a trailing backslash in an
unterminated backtick span.
- utils readStdinJson: on overflow, settle and resolve {} immediately (clear
timer + listeners) instead of waiting for end/timeout and parsing a partial
prefix; surface the overflow on stderr.
Regression tests added/extended (new tests/hooks/pre-compact.test.js).
Addresses review feedback on #2405. The earlier block-no-verify change was
dropped: its message-value skip on merge/cherry-pick/am/rebase would let
`git rebase -m --no-verify` bypass the hook (rebase's -m is the boolean
--merge), a false-negative worse than the contrived false-positive it fixed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(ci): align hook fixtures and drain oversized stdin
---------
Co-authored-by: djpjronline-netizen <276112803+djpjronline-netizen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: haelyra <49814733+haelyra@users.noreply.github.com>
This commit is contained in:
parent
6be87a56ae
commit
837acaf20b
11 changed files with 517 additions and 53 deletions
|
|
@ -1114,16 +1114,90 @@ function runTests() {
|
|||
return true;
|
||||
}
|
||||
const { execFileSync } = require('child_process');
|
||||
// maxSize is a chunk-level guard: once data.length >= maxSize, no MORE chunks are added.
|
||||
// A single small chunk that arrives when data.length < maxSize is added in full.
|
||||
// To test multi-chunk behavior, we send >64KB (Node default highWaterMark=16KB)
|
||||
// which should arrive in multiple chunks. With maxSize=100, only the first chunk(s)
|
||||
// totaling under 100 bytes should be captured; subsequent chunks are dropped.
|
||||
// Send enough data to cross the chunk-level cap. The child must keep
|
||||
// draining stdin until EOF so the parent does not see EPIPE on macOS.
|
||||
const script = 'const u=require("./scripts/lib/utils");u.readStdinJson({timeoutMs:2000,maxSize:100}).then(d=>{process.stdout.write(JSON.stringify(d))})';
|
||||
// Generate 100KB of data (arrives in multiple chunks)
|
||||
const bigInput = '{"k":"' + 'X'.repeat(100000) + '"}';
|
||||
const result = execFileSync('node', ['-e', script], { ...stdinOpts, input: bigInput });
|
||||
// Truncated mid-string → invalid JSON → resolves to {}
|
||||
// Oversized input is rejected rather than parsing a partial JSON prefix.
|
||||
assert.deepStrictEqual(JSON.parse(result), {});
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('readStdinJson overflow drain still exits when the writer never closes stdin', () => {
|
||||
const { execFileSync } = require('child_process');
|
||||
const childScript = [
|
||||
'const u=require("./scripts/lib/utils");',
|
||||
'u.readStdinJson({timeoutMs:100,maxSize:100})',
|
||||
'.then(d=>process.stdout.write(JSON.stringify(d)));'
|
||||
].join('');
|
||||
const harness = `
|
||||
const { spawn } = require('child_process');
|
||||
const child = spawn(process.execPath, ['-e', ${JSON.stringify(childScript)}], {
|
||||
cwd: process.cwd(),
|
||||
stdio: ['pipe', 'pipe', 'inherit']
|
||||
});
|
||||
let stdout = '';
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', chunk => { stdout += chunk; });
|
||||
child.stdin.write('X'.repeat(100000));
|
||||
const deadline = setTimeout(() => {
|
||||
child.kill();
|
||||
process.exit(2);
|
||||
}, 1000);
|
||||
child.on('exit', code => {
|
||||
clearTimeout(deadline);
|
||||
if (code !== 0) process.exit(code || 1);
|
||||
process.stdout.write(stdout);
|
||||
});
|
||||
`;
|
||||
const result = execFileSync('node', ['-e', harness], {
|
||||
...stdinOpts,
|
||||
timeout: 2000
|
||||
});
|
||||
assert.deepStrictEqual(JSON.parse(result), {});
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('readStdinJson drains a slow finite oversized writer without EPIPE', () => {
|
||||
const { execFileSync } = require('child_process');
|
||||
const childScript = [
|
||||
'const u=require("./scripts/lib/utils");',
|
||||
'u.readStdinJson({timeoutMs:500,maxSize:100})',
|
||||
'.then(d=>process.stdout.write(JSON.stringify(d)));'
|
||||
].join('');
|
||||
const harness = `
|
||||
const { spawn } = require('child_process');
|
||||
const child = spawn(process.execPath, ['-e', ${JSON.stringify(childScript)}], {
|
||||
cwd: process.cwd(),
|
||||
stdio: ['pipe', 'pipe', 'inherit']
|
||||
});
|
||||
let stdout = '';
|
||||
let writes = 0;
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', chunk => { stdout += chunk; });
|
||||
child.stdin.on('error', () => process.exit(3));
|
||||
const writer = setInterval(() => {
|
||||
writes += 1;
|
||||
child.stdin.write('X'.repeat(5000));
|
||||
if (writes === 20) {
|
||||
clearInterval(writer);
|
||||
child.stdin.end();
|
||||
}
|
||||
}, 5);
|
||||
const deadline = setTimeout(() => {
|
||||
child.kill();
|
||||
process.exit(2);
|
||||
}, 1500);
|
||||
child.on('exit', code => {
|
||||
clearInterval(writer);
|
||||
clearTimeout(deadline);
|
||||
if (code !== 0) process.exit(code || 1);
|
||||
process.stdout.write(stdout);
|
||||
});
|
||||
`;
|
||||
const result = execFileSync('node', ['-e', harness], {
|
||||
...stdinOpts,
|
||||
timeout: 2000
|
||||
});
|
||||
assert.deepStrictEqual(JSON.parse(result), {});
|
||||
})) passed++; else failed++;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue