mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-31 06:03:29 +08:00
99 lines
2.5 KiB
JavaScript
Executable File
99 lines
2.5 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/**
|
|
* Quality Gate Hook
|
|
*
|
|
* Runs lightweight quality checks after file edits.
|
|
* - Targets one file when file_path is provided
|
|
* - Falls back to no-op when language/tooling is unavailable
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { spawnSync } = require('child_process');
|
|
|
|
const MAX_STDIN = 1024 * 1024;
|
|
let raw = '';
|
|
|
|
function run(command, args, cwd = process.cwd()) {
|
|
return spawnSync(command, args, {
|
|
cwd,
|
|
encoding: 'utf8',
|
|
env: process.env,
|
|
});
|
|
}
|
|
|
|
function log(msg) {
|
|
process.stderr.write(`${msg}\n`);
|
|
}
|
|
|
|
function maybeRunQualityGate(filePath) {
|
|
if (!filePath || !fs.existsSync(filePath)) {
|
|
return;
|
|
}
|
|
|
|
const ext = path.extname(filePath).toLowerCase();
|
|
const fix = String(process.env.ECC_QUALITY_GATE_FIX || '').toLowerCase() === 'true';
|
|
const strict = String(process.env.ECC_QUALITY_GATE_STRICT || '').toLowerCase() === 'true';
|
|
|
|
if (['.ts', '.tsx', '.js', '.jsx', '.json', '.md'].includes(ext)) {
|
|
// Prefer biome if present
|
|
if (fs.existsSync(path.join(process.cwd(), 'biome.json')) || fs.existsSync(path.join(process.cwd(), 'biome.jsonc'))) {
|
|
const args = ['biome', 'check', filePath];
|
|
if (fix) args.push('--write');
|
|
const result = run('npx', args);
|
|
if (result.status !== 0 && strict) {
|
|
log(`[QualityGate] Biome check failed for ${filePath}`);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Fallback to prettier when installed
|
|
const prettierArgs = ['prettier', '--check', filePath];
|
|
if (fix) {
|
|
prettierArgs[1] = '--write';
|
|
}
|
|
const prettier = run('npx', prettierArgs);
|
|
if (prettier.status !== 0 && strict) {
|
|
log(`[QualityGate] Prettier check failed for ${filePath}`);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (ext === '.go' && fix) {
|
|
run('gofmt', ['-w', filePath]);
|
|
return;
|
|
}
|
|
|
|
if (ext === '.py') {
|
|
const args = ['format'];
|
|
if (!fix) args.push('--check');
|
|
args.push(filePath);
|
|
const r = run('ruff', args);
|
|
if (r.status !== 0 && strict) {
|
|
log(`[QualityGate] Ruff check failed for ${filePath}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
process.stdin.setEncoding('utf8');
|
|
process.stdin.on('data', chunk => {
|
|
if (raw.length < MAX_STDIN) {
|
|
const remaining = MAX_STDIN - raw.length;
|
|
raw += chunk.substring(0, remaining);
|
|
}
|
|
});
|
|
|
|
process.stdin.on('end', () => {
|
|
try {
|
|
const input = JSON.parse(raw);
|
|
const filePath = String(input.tool_input?.file_path || '');
|
|
maybeRunQualityGate(filePath);
|
|
} catch {
|
|
// Ignore parse errors.
|
|
}
|
|
|
|
process.stdout.write(raw);
|
|
});
|