diff --git a/lefthook.yml b/lefthook.yml index 4cf6470..baab47f 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -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 нашёл утечки в истории коммитов. diff --git a/tools/run-if-exists.mjs b/tools/run-if-exists.mjs new file mode 100644 index 0000000..3656df0 --- /dev/null +++ b/tools/run-if-exists.mjs @@ -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 -- . + */ +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(); diff --git a/tools/run-if-exists.test.mjs b/tools/run-if-exists.test.mjs new file mode 100644 index 0000000..b1b9c8d --- /dev/null +++ b/tools/run-if-exists.test.mjs @@ -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); + }); +});