docs(GOV-001): 建立工程治理与追溯规范
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
import {
|
||||
getFeatureDirectory,
|
||||
getRequiredFeatureFiles,
|
||||
validateFeatureId,
|
||||
} from './feature-record.mjs';
|
||||
|
||||
const [featureId, slug] = process.argv.slice(2);
|
||||
const repositoryRoot = process.cwd();
|
||||
|
||||
if (!featureId || !slug || !validateFeatureId(featureId)) {
|
||||
throw new Error('用法:npm run governance:finish -- <功能编号> <英文短名称>');
|
||||
}
|
||||
|
||||
const featureDirectory = getFeatureDirectory(repositoryRoot, featureId, slug);
|
||||
if (!existsSync(featureDirectory)) {
|
||||
throw new Error(`功能档案不存在:${featureDirectory}`);
|
||||
}
|
||||
|
||||
function run(command, args) {
|
||||
return execFileSync(command, args, {
|
||||
cwd: repositoryRoot,
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
}).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成门禁先验证仓库自身的治理测试,再刷新 GitNexus。业务项目接入后,
|
||||
* 根目录 verify 脚本会继续串联前端和后端测试,而不需要改变本门禁入口。
|
||||
*/
|
||||
run('npm', ['run', 'test:governance']);
|
||||
run('npx', ['gitnexus', 'analyze']);
|
||||
|
||||
const status = run('npx', ['gitnexus', 'status']);
|
||||
const diffSummary = run('git', ['diff', '--stat']) || '(没有未提交差异)';
|
||||
const worktreeSummary = run('git', ['status', '--short']) || '(工作区干净)';
|
||||
const afterReport = path.join(featureDirectory, 'gitnexus', 'after.md');
|
||||
|
||||
if (!existsSync(afterReport) || readFileSync(afterReport, 'utf8').trim().length === 0) {
|
||||
writeFileSync(
|
||||
afterReport,
|
||||
`# GitNexus 开发后基线\n\n` +
|
||||
`## GitNexus 状态\n\n\`\`\`text\n${status}\n\`\`\`\n\n` +
|
||||
`## Git 已跟踪变更摘要\n\n\`\`\`text\n${diffSummary}\n\`\`\`\n\n` +
|
||||
`## Git 工作区摘要\n\n\`\`\`text\n${worktreeSummary}\n\`\`\`\n`,
|
||||
'utf8',
|
||||
);
|
||||
}
|
||||
|
||||
const missingFiles = getRequiredFeatureFiles().filter((relativeFile) => {
|
||||
const file = path.join(featureDirectory, relativeFile);
|
||||
return !existsSync(file) || readFileSync(file, 'utf8').trim().length === 0;
|
||||
});
|
||||
|
||||
if (missingFiles.length > 0) {
|
||||
throw new Error(`完成门禁未通过,缺少或为空:\n- ${missingFiles.join('\n- ')}`);
|
||||
}
|
||||
|
||||
process.stdout.write(
|
||||
`基础门禁已通过。提交前仍须人工确认 GitNexus 影响报告、业务测试、视觉 QA 和回退说明。\n`,
|
||||
);
|
||||
Reference in New Issue
Block a user