feat(web): T-WEB-010 部署脚本(Docker Compose,不含 MySQL)
This commit is contained in:
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 校验代码内的契约版本常量与 contracts/VERSION 一致。
|
||||
* 在构建前执行:不一致则退出码 1,阻止契约漂移。
|
||||
*
|
||||
* 用法:node scripts/check-contracts.mjs
|
||||
*/
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const versionFile = join(here, '..', '..', 'contracts', 'VERSION');
|
||||
const constantFile = join(here, '..', 'src', 'config', 'contract-versions.ts');
|
||||
|
||||
function parseVersionFile(content) {
|
||||
const out = {};
|
||||
for (const rawLine of content.split(/\r?\n/)) {
|
||||
const line = rawLine.trim();
|
||||
if (!line || line.startsWith('#')) continue;
|
||||
const idx = line.indexOf(':');
|
||||
if (idx <= 0) continue;
|
||||
out[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function parseConstants(content) {
|
||||
const block = /CONTRACT_VERSIONS[^=]*=\s*Object\.freeze\(\{([\s\S]*?)\}\)/.exec(content);
|
||||
if (!block) throw new Error('无法在 contract-versions.ts 中定位 CONTRACT_VERSIONS');
|
||||
const out = {};
|
||||
// 键可能是带引号的 'rest-api',也可能是不带引号的 database
|
||||
for (const match of block[1].matchAll(/['"]?([\w-]+)['"]?\s*:\s*['"]([^'"]+)['"]/g)) {
|
||||
out[match[1]] = match[2];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
let fileVersions;
|
||||
let codeVersions;
|
||||
try {
|
||||
fileVersions = parseVersionFile(readFileSync(versionFile, 'utf8'));
|
||||
} catch (error) {
|
||||
console.error(`✗ 无法读取 ${versionFile}:${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
try {
|
||||
codeVersions = parseConstants(readFileSync(constantFile, 'utf8'));
|
||||
} catch (error) {
|
||||
console.error(`✗ 无法解析 ${constantFile}:${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const keys = new Set([...Object.keys(fileVersions), ...Object.keys(codeVersions)]);
|
||||
const problems = [];
|
||||
for (const key of [...keys].sort()) {
|
||||
const a = fileVersions[key];
|
||||
const b = codeVersions[key];
|
||||
if (a === undefined) problems.push(` ${key}: 仅存在于代码常量(${b})`);
|
||||
else if (b === undefined) problems.push(` ${key}: 仅存在于 contracts/VERSION(${a})`);
|
||||
else if (a !== b) problems.push(` ${key}: contracts/VERSION=${a} vs 代码常量=${b}`);
|
||||
}
|
||||
|
||||
if (problems.length > 0) {
|
||||
console.error('✗ 契约版本不一致:');
|
||||
console.error(problems.join('\n'));
|
||||
console.error('\n请同步 contracts/VERSION 与 web-server/src/config/contract-versions.ts');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`✓ 契约版本一致(${Object.keys(fileVersions).length} 项):${JSON.stringify(fileVersions)}`);
|
||||
Reference in New Issue
Block a user