fix(hooks): gitleaks-full-history чисто пропускается без бинаря (шелл-агностичный guard, без exit-127)
Хрупкий guard `test -f ./bin/gitleaks.exe || exit 0` падал exit-127, когда команда test недоступна в шелле git-хука → шаг pre-push падал вместо чистого пропуска. Новый tools/run-if-exists.mjs (node, всегда доступен в контексте хука): бинарь отсутствует → skip exit 0; присутствует → запуск с пробросом кода. lefthook gitleaks-full-history переведён на него. Разведка: bin/gitleaks.exe и .gitleaks.toml в репо отсутствуют → реальный скан невозможен, наблюдался именно exit-127, не настоящая находка; .gitleaksignore без бинаря/конфига/отпечатков не составить. gitleaks #1 и lychee #14 — тот же паттерн, отдельный инфра-долг. Эпик роутер-реестр этап 3, item 6. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -115,7 +115,7 @@ pre-push:
|
||||
jobs:
|
||||
# 13. Полный gitleaks-скан всей истории.
|
||||
- name: gitleaks-full-history
|
||||
run: test -f ./bin/gitleaks.exe || exit 0; ./bin/gitleaks.exe detect --source . --no-banner --config .gitleaks.toml --redact
|
||||
run: node tools/run-if-exists.mjs bin/gitleaks.exe -- detect --source . --no-banner --config .gitleaks.toml --redact
|
||||
fail_text: |
|
||||
gitleaks нашёл утечки в истории коммитов.
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* run-if-exists — шелл-агностичный guard для lefthook: запустить бинарь, ТОЛЬКО если он есть.
|
||||
* Заменяет хрупкий `test -f ./bin/X.exe || exit 0; ./bin/X.exe …` (падал exit-127, когда команда
|
||||
* `test` недоступна в шелле хука). Бинарь отсутствует → чистый пропуск (exit 0). Присутствует →
|
||||
* запуск с пробросом кода выхода. Использование: node tools/run-if-exists.mjs <binary> -- <args...>.
|
||||
*/
|
||||
import { existsSync } from 'node:fs';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
|
||||
export function shouldRun(binaryPath, fsImpl = { existsSync }) {
|
||||
return !!binaryPath && fsImpl.existsSync(binaryPath);
|
||||
}
|
||||
|
||||
function main() {
|
||||
const argv = process.argv.slice(2);
|
||||
const sep = argv.indexOf('--');
|
||||
const binaryPath = argv[0];
|
||||
const args = sep >= 0 ? argv.slice(sep + 1) : argv.slice(1);
|
||||
if (!shouldRun(binaryPath)) {
|
||||
console.log(`[run-if-exists] ${binaryPath || '(пусто)'} отсутствует — пропуск`);
|
||||
process.exit(0);
|
||||
}
|
||||
try {
|
||||
execFileSync(binaryPath, args, { stdio: 'inherit' });
|
||||
process.exit(0);
|
||||
} catch (e) {
|
||||
process.exit(typeof e.status === 'number' ? e.status : 1);
|
||||
}
|
||||
}
|
||||
|
||||
import { fileURLToPath } from 'node:url';
|
||||
const isCli = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
|
||||
if (isCli) main();
|
||||
@@ -0,0 +1,18 @@
|
||||
// tools/run-if-exists.test.mjs
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { shouldRun } from './run-if-exists.mjs';
|
||||
|
||||
describe('shouldRun (D1) — шелл-агностичный guard', () => {
|
||||
it('несуществующий путь → false (пропуск)', () => {
|
||||
expect(shouldRun('bin/nope.exe', { existsSync: () => false })).toBe(false);
|
||||
});
|
||||
it('существующий путь → true (запуск)', () => {
|
||||
expect(shouldRun('bin/gitleaks.exe', { existsSync: () => true })).toBe(true);
|
||||
});
|
||||
it('пустой путь → false', () => {
|
||||
expect(shouldRun('', { existsSync: () => true })).toBe(false);
|
||||
});
|
||||
it('undefined путь → false', () => {
|
||||
expect(shouldRun(undefined, { existsSync: () => true })).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user