mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-02 11:45:20 +02:00
test: harden regression test — Bun.Glob, SKILL.md scan, codex review check
Fixes three gaps found by adversarial review: 1. fs.readdirSync recursive hits ELOOP on .claude/skills/gstack symlink. Switched to Bun.Glob with followSymlinks:false. 2. Generated SKILL.md files now scanned (not just .tmpl sources). 3. New test: codex review commands must not use inline git rev-parse (codex review doesn't support -C, so cd "$_REPO_ROOT" is the fix). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1684,14 +1684,8 @@ describe('codex commands must not use inline $(git rev-parse --show-toplevel) fo
|
||||
|
||||
test('no generated SKILL.md has codex exec with inline $(git rev-parse --show-toplevel) in -C flag', () => {
|
||||
const violations: string[] = [];
|
||||
const skillMdFiles = fs.readdirSync(ROOT, { recursive: true })
|
||||
.filter((f): f is string =>
|
||||
typeof f === 'string' &&
|
||||
f.endsWith('SKILL.md') &&
|
||||
!f.includes('node_modules') &&
|
||||
!f.includes('.claude') &&
|
||||
!f.includes('.agents') &&
|
||||
!f.includes('.tmpl'));
|
||||
const skillMdGlob = new Bun.Glob('**/SKILL.md');
|
||||
const skillMdFiles = Array.from(skillMdGlob.scanSync({ cwd: ROOT, followSymlinks: false }));
|
||||
for (const rel of skillMdFiles) {
|
||||
const abs = path.join(ROOT, rel);
|
||||
if (!fs.existsSync(abs)) continue;
|
||||
@@ -1706,4 +1700,38 @@ describe('codex commands must not use inline $(git rev-parse --show-toplevel) fo
|
||||
}
|
||||
expect(violations).toEqual([]);
|
||||
});
|
||||
|
||||
test('codex review commands must be preceded by cd "$_REPO_ROOT" (no -C support)', () => {
|
||||
// codex review does not support -C, so the pattern must be:
|
||||
// _REPO_ROOT=$(git rev-parse --show-toplevel) || { ... }
|
||||
// cd "$_REPO_ROOT"
|
||||
// codex review ...
|
||||
// NOT: codex review ... with inline $(git rev-parse --show-toplevel)
|
||||
const allFiles = [
|
||||
...Array.from(tmplGlob.scanSync({ cwd: ROOT, followSymlinks: false })),
|
||||
...Array.from(new Bun.Glob('**/SKILL.md').scanSync({ cwd: ROOT, followSymlinks: false })),
|
||||
...fs.readdirSync(path.join(ROOT, 'scripts/resolvers'))
|
||||
.filter(f => f.endsWith('.ts'))
|
||||
.map(f => `scripts/resolvers/${f}`),
|
||||
'scripts/gen-skill-docs.ts',
|
||||
];
|
||||
const violations: string[] = [];
|
||||
for (const rel of allFiles) {
|
||||
const abs = path.join(ROOT, rel);
|
||||
if (!fs.existsSync(abs)) continue;
|
||||
const content = fs.readFileSync(abs, 'utf-8');
|
||||
const lines = content.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
// Skip non-executable lines (markdown table cells, prose references)
|
||||
if (line.includes('|') && line.includes('`/codex review`')) continue;
|
||||
if (line.includes('`codex review`')) continue;
|
||||
// Check for codex review with inline $(git rev-parse)
|
||||
if (line.includes('codex review') && line.includes('$(git rev-parse --show-toplevel)')) {
|
||||
violations.push(`${rel}:${i + 1} — inline git rev-parse in codex review`);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect(violations).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user