fix(GOV-009): 完成仅源码部署最终复审

This commit is contained in:
2026-08-13 21:33:38 +08:00
parent 47d0e0d248
commit c75665446b
13 changed files with 191 additions and 50 deletions
+39 -1
View File
@@ -1,4 +1,4 @@
import { access, readFile } from 'node:fs/promises';
import { access, readFile, readdir } from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
@@ -32,6 +32,16 @@ const serverProcesses = Object.freeze([
['worker', 'Worker'],
]);
const ignoredScanDirectories = new Set([
'.git',
'.gitnexus',
'.local',
'dist',
'node_modules',
'playwright-report',
'test-results',
]);
function resolveRoot(repositoryRoot) {
return repositoryRoot instanceof URL
? fileURLToPath(repositoryRoot)
@@ -54,6 +64,34 @@ async function assertDockerArtifactsAbsent(repositoryRoot) {
throw new Error(`禁止存在 Docker 活动文件:${relativePath}`);
}
}
const pendingDirectories = [repositoryRoot];
while (pendingDirectories.length > 0) {
const currentDirectory = pendingDirectories.pop();
const entries = await readdir(currentDirectory, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory() && ignoredScanDirectories.has(entry.name)) continue;
const absolutePath = path.join(currentDirectory, entry.name);
if (entry.isDirectory()) {
pendingDirectories.push(absolutePath);
continue;
}
if (!entry.isFile()) continue;
const relativePath = path.relative(repositoryRoot, absolutePath).split(path.sep).join('/');
const segments = relativePath.split('/');
const fileName = segments.at(-1);
const isDockerfile = /^Dockerfile(?:\..+)?$/i.test(fileName);
const isDockerIgnore = fileName === '.dockerignore';
const isDockerCompose = /^docker-compose.*\.ya?ml$/i.test(fileName);
const isComposeYaml = segments.includes('compose') && /\.ya?ml$/i.test(fileName);
if (isDockerfile || isDockerIgnore || isDockerCompose || isComposeYaml) {
throw new Error(`禁止存在 Docker 活动文件:${relativePath}`);
}
}
}
}
async function assertBuildOutputsPresent(repositoryRoot) {
@@ -81,6 +81,20 @@ test('任一 Docker 活动文件会阻断源码发布', async () => {
await assert.rejects(() => verifySourceDeployment(root), /禁止存在 Docker 活动文件.*Dockerfile/);
});
test('未预先列举的 Dockerfile 和 Compose 文件仍会阻断源码发布', async () => {
for (const relativePath of ['ops/Dockerfile', 'deploy/compose/extra.yml']) {
const root = await createSourceReleaseFixture();
const absolutePath = path.join(root, relativePath);
await mkdir(path.dirname(absolutePath), { recursive: true });
await writeFile(absolutePath, 'services: {}\n');
await assert.rejects(
() => verifySourceDeployment(root),
new RegExp(`禁止存在 Docker 活动文件.*${relativePath.replace('/', '\\/')}`),
);
}
});
test('Server 构建入口缺失会阻断源码发布', async () => {
const root = await createSourceReleaseFixture({ omit: 'server/dist/apps/worker/main.js' });