mirror of
https://github.com/glittercowboy/get-shit-done
synced 2026-04-25 17:25:23 +02:00
Before registering each .sh hook (validate-commit, session-state, phase-boundary), check that the target file was actually copied. If the .sh file is missing (e.g. omitted from the npm package as in v1.32.0), skip registration and emit a warning instead of writing a broken hook entry that errors on every tool invocation. Closes #1817 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
64 lines
2.4 KiB
JavaScript
64 lines
2.4 KiB
JavaScript
/**
|
|
* Regression tests for bug #1817
|
|
*
|
|
* The installer must NOT register .sh hook entries in settings.json when the
|
|
* corresponding .sh file does not exist at the target path. The original bug:
|
|
* v1.32.0's npm package omitted the .sh files from hooks/dist/, so the copy
|
|
* step produced no files, yet the registration step ran unconditionally —
|
|
* leaving users with hook errors on every tool invocation.
|
|
*
|
|
* Defensive guard: before registering each .sh hook in settings.json,
|
|
* install.js must verify the target file exists. If it doesn't, skip
|
|
* registration and emit a warning.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const { describe, test } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const INSTALL_SRC = path.join(__dirname, '..', 'bin', 'install.js');
|
|
|
|
const SH_HOOKS = [
|
|
{ name: 'gsd-validate-commit.sh', settingsVar: 'validateCommitCommand' },
|
|
{ name: 'gsd-session-state.sh', settingsVar: 'sessionStateCommand' },
|
|
{ name: 'gsd-phase-boundary.sh', settingsVar: 'phaseBoundaryCommand' },
|
|
];
|
|
|
|
describe('bug #1817: .sh hook registration guards', () => {
|
|
let src;
|
|
|
|
// Read once — all tests in this suite share the same source snapshot.
|
|
try {
|
|
src = fs.readFileSync(INSTALL_SRC, 'utf-8');
|
|
} catch {
|
|
src = '';
|
|
}
|
|
|
|
for (const { name, settingsVar } of SH_HOOKS) {
|
|
describe(`${name} registration`, () => {
|
|
test(`install.js checks file existence before registering ${name}`, () => {
|
|
// Find the block where this .sh hook is registered.
|
|
// Each registration block is preceded by the command variable declaration
|
|
// and followed by the next hook or end of registration section.
|
|
const varIdx = src.indexOf(settingsVar);
|
|
assert.ok(varIdx !== -1, `${settingsVar} variable not found in install.js`);
|
|
|
|
// Extract ~900 chars around the variable to find the registration block
|
|
const blockStart = Math.max(0, varIdx - 50);
|
|
const blockEnd = Math.min(src.length, varIdx + 900);
|
|
const block = src.slice(blockStart, blockEnd);
|
|
|
|
assert.ok(
|
|
block.includes('fs.existsSync') || block.includes('existsSync'),
|
|
`install.js must call fs.existsSync on the target path before registering ${name} in settings.json. ` +
|
|
`Without this guard, hooks are registered even when the .sh file was never copied ` +
|
|
`(the root cause of #1817).`
|
|
);
|
|
});
|
|
});
|
|
}
|
|
});
|