mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const os = require('node:os');
|
||||
const path = require('node:path');
|
||||
const test = require('node:test');
|
||||
|
||||
const {
|
||||
auditLocalImageContract,
|
||||
} = require('../../scripts/ql3-local-image-audit.cjs');
|
||||
|
||||
const root = path.resolve(__dirname, '../..');
|
||||
const source = path.join(root, 'deploy/containers/ql3-local-application');
|
||||
|
||||
function fixture() {
|
||||
const temporaryRoot = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'ql3-local-image-audit-'),
|
||||
);
|
||||
const target = path.join(
|
||||
temporaryRoot,
|
||||
'deploy/containers/ql3-local-application',
|
||||
);
|
||||
fs.mkdirSync(path.dirname(target), { recursive: true });
|
||||
fs.cpSync(source, target, { recursive: true });
|
||||
const workflowTarget = path.join(
|
||||
temporaryRoot,
|
||||
'.github/workflows/ql3-ci.yml',
|
||||
);
|
||||
fs.mkdirSync(path.dirname(workflowTarget), { recursive: true });
|
||||
fs.copyFileSync(
|
||||
path.join(root, '.github/workflows/ql3-ci.yml'),
|
||||
workflowTarget,
|
||||
);
|
||||
return {
|
||||
root: temporaryRoot,
|
||||
target,
|
||||
close() {
|
||||
fs.rmSync(temporaryRoot, { recursive: true, force: true });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test('accepts the exact AI-excluded local application image contract', () => {
|
||||
const report = auditLocalImageContract(root);
|
||||
assert.equal(report.compatible, true);
|
||||
assert.deepEqual(report.findings, []);
|
||||
assert.deepEqual(report.runtimePackages, [
|
||||
'@qinglong/local-admin',
|
||||
'@qinglong/local-application',
|
||||
'@qinglong/local-command-file',
|
||||
'@qinglong/local-execution',
|
||||
'@qinglong/local-process',
|
||||
'@qinglong/local-secret',
|
||||
'@qinglong/local-sqlite',
|
||||
'@qinglong/runtime-core',
|
||||
'croner',
|
||||
'semver',
|
||||
]);
|
||||
});
|
||||
|
||||
test('rejects a mutable or build-argument-controlled base image', () => {
|
||||
const current = fixture();
|
||||
try {
|
||||
const dockerfilePath = path.join(current.target, 'Dockerfile');
|
||||
const dockerfile = fs.readFileSync(dockerfilePath, 'utf8');
|
||||
fs.writeFileSync(
|
||||
dockerfilePath,
|
||||
`ARG NODE_IMAGE=node:24-bookworm-slim\n${dockerfile.replaceAll(
|
||||
/node:24\.18\.0-bookworm-slim@sha256:[0-9a-f]{64}/g,
|
||||
'${NODE_IMAGE}',
|
||||
)}`,
|
||||
);
|
||||
const report = auditLocalImageContract(current.root);
|
||||
assert.equal(report.compatible, false);
|
||||
assert.ok(
|
||||
report.findings.some(
|
||||
({ code }) => code === 'BASE_IMAGE_NOT_EXACTLY_PINNED',
|
||||
),
|
||||
);
|
||||
assert.ok(
|
||||
report.findings.some(
|
||||
({ code }) => code === 'BASE_IMAGE_OVERRIDE_AUTHORITY',
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
current.close();
|
||||
}
|
||||
});
|
||||
|
||||
test('rejects AI or an unreviewed dependency in the runtime closure', () => {
|
||||
const current = fixture();
|
||||
try {
|
||||
const dockerfilePath = path.join(current.target, 'Dockerfile');
|
||||
fs.appendFileSync(
|
||||
dockerfilePath,
|
||||
'\nCOPY --from=workspace /workspace/packages/ql3-ai/dist node_modules/@qinglong/ai/dist\n',
|
||||
);
|
||||
const runtimeManifestPath = path.join(
|
||||
current.target,
|
||||
'runtime-dependencies/package.json',
|
||||
);
|
||||
const runtimeManifest = JSON.parse(
|
||||
fs.readFileSync(runtimeManifestPath, 'utf8'),
|
||||
);
|
||||
runtimeManifest.dependencies['drizzle-orm'] = '1.0.0-rc.4';
|
||||
fs.writeFileSync(
|
||||
runtimeManifestPath,
|
||||
`${JSON.stringify(runtimeManifest, null, 2)}\n`,
|
||||
);
|
||||
const report = auditLocalImageContract(current.root);
|
||||
assert.equal(report.compatible, false);
|
||||
assert.ok(
|
||||
report.findings.some(
|
||||
({ code }) => code === 'AI_PRESENT_IN_RUNTIME_STAGE',
|
||||
),
|
||||
);
|
||||
assert.ok(
|
||||
report.findings.some(({ code }) => code === 'RUNTIME_DEPENDENCY_DRIFT'),
|
||||
);
|
||||
} finally {
|
||||
current.close();
|
||||
}
|
||||
});
|
||||
|
||||
test('rejects retaining npm bin links, debug maps or declarations in the production image', () => {
|
||||
const current = fixture();
|
||||
try {
|
||||
const dockerfilePath = path.join(current.target, 'Dockerfile');
|
||||
const dockerfile = fs
|
||||
.readFileSync(dockerfilePath, 'utf8')
|
||||
.replace(
|
||||
'RUN rm -rf node_modules/.bin \\\n' +
|
||||
' && node /tmp/ql3-prune-runtime-artifact.cjs node_modules/@qinglong \\\n' +
|
||||
' @qinglong/local-application \\\n' +
|
||||
' @qinglong/local-application/process \\\n' +
|
||||
' @qinglong/local-application/plugin-package-recovery-catalog \\\n' +
|
||||
' --exclude=@qinglong/ai \\\n' +
|
||||
' && rm /tmp/ql3-prune-runtime-artifact.cjs\n\n',
|
||||
'',
|
||||
);
|
||||
fs.writeFileSync(dockerfilePath, dockerfile);
|
||||
const report = auditLocalImageContract(current.root);
|
||||
assert.equal(report.compatible, false);
|
||||
assert.ok(
|
||||
report.findings.some(
|
||||
({ code }) => code === 'RUNTIME_NONESSENTIAL_FILES_NOT_REMOVED',
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
current.close();
|
||||
}
|
||||
});
|
||||
|
||||
test('rejects removal of the SQLite rollout compatibility labels', () => {
|
||||
const current = fixture();
|
||||
try {
|
||||
const dockerfilePath = path.join(current.target, 'Dockerfile');
|
||||
const dockerfile = fs
|
||||
.readFileSync(dockerfilePath, 'utf8')
|
||||
.replace(' io.qinglong.local.sqlite-write-contract="43" \\\n', '');
|
||||
fs.writeFileSync(dockerfilePath, dockerfile);
|
||||
const report = auditLocalImageContract(current.root);
|
||||
assert.equal(report.compatible, false);
|
||||
assert.ok(
|
||||
report.findings.some(
|
||||
({ code }) => code === 'RUNTIME_IDENTITY_OR_LABEL_DRIFT',
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
current.close();
|
||||
}
|
||||
});
|
||||
|
||||
test('rejects runtime lifecycle scripts or closure lock drift', () => {
|
||||
const current = fixture();
|
||||
try {
|
||||
const lockPath = path.join(
|
||||
current.target,
|
||||
'runtime-dependencies/package-lock.json',
|
||||
);
|
||||
const lock = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
|
||||
lock.packages['node_modules/croner'].hasInstallScript = true;
|
||||
lock.packages['node_modules/unreviewed'] = {
|
||||
version: '1.0.0',
|
||||
resolved: 'file:../unreviewed',
|
||||
integrity: 'sha512-invalid',
|
||||
};
|
||||
fs.writeFileSync(lockPath, `${JSON.stringify(lock, null, 2)}\n`);
|
||||
const report = auditLocalImageContract(current.root);
|
||||
assert.equal(report.compatible, false);
|
||||
assert.ok(
|
||||
report.findings.some(({ code }) => code === 'LOCKED_PACKAGE_UNSAFE'),
|
||||
);
|
||||
assert.ok(
|
||||
report.findings.some(({ code }) => code === 'RUNTIME_LOCK_CLOSURE_DRIFT'),
|
||||
);
|
||||
} finally {
|
||||
current.close();
|
||||
}
|
||||
});
|
||||
|
||||
test('rejects removal of either Profile from the native image CI gate', () => {
|
||||
const current = fixture();
|
||||
try {
|
||||
const workflowPath = path.join(
|
||||
current.root,
|
||||
'.github/workflows/ql3-ci.yml',
|
||||
);
|
||||
const workflow = fs
|
||||
.readFileSync(workflowPath, 'utf8')
|
||||
.replace(
|
||||
' node scripts/ql3-local-image-live-contract.cjs --image="${IMAGE}" --profile=standalone\n',
|
||||
'',
|
||||
);
|
||||
fs.writeFileSync(workflowPath, workflow);
|
||||
const report = auditLocalImageContract(current.root);
|
||||
assert.equal(report.compatible, false);
|
||||
assert.ok(
|
||||
report.findings.some(
|
||||
({ code }) => code === 'LOCAL_IMAGE_CI_CONTRACT_DRIFT',
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
current.close();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user