mirror of
https://gh-proxy.org/https://github.com/klinsmaya/workdsh.git
synced 2026-11-09 09:57:05 +08:00
86 lines
4.6 KiB
JavaScript
86 lines
4.6 KiB
JavaScript
#!/usr/bin/env node
|
|
// Keep optional native test dependencies and database files out of the product workspace.
|
|
import { cp, mkdir, mkdtemp, readFile, readdir, lstat, writeFile } from 'node:fs/promises';
|
|
import { createHash } from 'node:crypto';
|
|
import { spawn } from 'node:child_process';
|
|
import { tmpdir } from 'node:os';
|
|
import { dirname, join, relative } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const bridge = fileURLToPath(new URL('../', import.meta.url));
|
|
const sources = { 'model-adapter': join(bridge, '../model-adapter'), 'plugin-agent-bridge': bridge };
|
|
const output = await mkdtemp(join(tmpdir(), 'afos-sql-validation-'));
|
|
const evidence = join(output, 'evidence');
|
|
await mkdir(evidence);
|
|
console.log(`Isolated SQL evidence: ${evidence}`);
|
|
const names = new Set(['package.json', 'pnpm-lock.yaml', 'tsconfig.json', 'tsconfig.core.json', 'src', 'scripts']);
|
|
const hashes = {};
|
|
async function hashFiles(root, file) {
|
|
const stat = await lstat(file);
|
|
if (stat.isSymbolicLink()) throw Error('SQL validation source must not contain symbolic links');
|
|
if (stat.isDirectory()) {
|
|
for (const name of (await readdir(file)).sort()) await hashFiles(root, join(file, name));
|
|
} else if (stat.isFile()) {
|
|
hashes[relative(dirname(root), file)] = createHash('sha256').update(await readFile(file)).digest('hex');
|
|
}
|
|
}
|
|
for (const [name, source] of Object.entries(sources)) {
|
|
const target = join(output, 'enterprise', name);
|
|
await mkdir(target, { recursive: true });
|
|
for (const child of (await readdir(source)).filter(name => names.has(name)).sort()) {
|
|
await hashFiles(source, join(source, child));
|
|
await cp(join(source, child), join(target, child), { recursive: true, errorOnExist: true, force: false });
|
|
}
|
|
}
|
|
await writeFile(join(output, 'SOURCE_SHA256.json'), `${JSON.stringify(hashes, null, 2)}\n`);
|
|
const configFile = join(output, 'enterprise/plugin-agent-bridge/package.json');
|
|
const config = JSON.parse(await readFile(configFile, 'utf8'));
|
|
config.devDependencies = { ...config.devDependencies, sqlite3: '5.1.7' };
|
|
config.pnpm = { ...config.pnpm, onlyBuiltDependencies: ['sqlite3'] };
|
|
await writeFile(configFile, `${JSON.stringify(config, null, 2)}\n`);
|
|
const env = {
|
|
...process.env,
|
|
COREPACK_HOME: join(output, 'corepack'),
|
|
XDG_CACHE_HOME: join(output, 'cache'),
|
|
XDG_DATA_HOME: join(output, 'data'),
|
|
XDG_CONFIG_HOME: join(output, 'config'),
|
|
npm_config_cache: join(output, 'npm-cache'),
|
|
};
|
|
const store = `--store-dir=${join(output, 'pnpm-store')}`;
|
|
const registry = '--registry=https://registry.npmjs.org';
|
|
const results = [];
|
|
async function run(name, cwd, command, args) {
|
|
const started = Date.now(), stdout = [], stderr = [];
|
|
const child = spawn(command, args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
child.stdout.on('data', chunk => stdout.push(chunk));
|
|
child.stderr.on('data', chunk => stderr.push(chunk));
|
|
const status = await new Promise((resolve, reject) => {
|
|
child.once('error', error => {
|
|
stderr.push(Buffer.from(`${error.message}\n`));
|
|
resolve({ code: 1, signal: null });
|
|
});
|
|
child.once('exit', (code, signal) => resolve({ code, signal }));
|
|
});
|
|
await writeFile(join(evidence, `${name}.stdout.txt`), Buffer.concat(stdout));
|
|
await writeFile(join(evidence, `${name}.stderr.txt`), Buffer.concat(stderr));
|
|
const result = { name, command: [command, ...args], cwd, exitCode: status.code,
|
|
signal: status.signal, durationMs: Date.now() - started };
|
|
results.push(result);
|
|
await writeFile(join(evidence, 'RESULTS.json'), `${JSON.stringify({ node: process.version, platform: process.platform,
|
|
architecture: process.arch, results }, null, 2)}\n`);
|
|
console.log(JSON.stringify(result));
|
|
if (status.code !== 0) {
|
|
console.error(`SQL validation stopped; failed evidence remains in ${evidence}`);
|
|
process.exit(status.code ?? 1);
|
|
}
|
|
}
|
|
const modelRoot = join(output, 'enterprise/model-adapter');
|
|
const bridgeRoot = join(output, 'enterprise/plugin-agent-bridge');
|
|
await run('model-install', modelRoot, 'corepack', ['pnpm', 'install', '--frozen-lockfile', '--ignore-scripts', store, registry]);
|
|
await run('model-build', modelRoot, 'corepack', ['pnpm', 'build']);
|
|
await run('bridge-install-with-test-driver', bridgeRoot, 'corepack', ['pnpm', 'install', '--no-frozen-lockfile', '--ignore-scripts', store, registry]);
|
|
await run('sqlite-driver-build', bridgeRoot, 'corepack', ['pnpm', 'rebuild', 'sqlite3', store]);
|
|
await run('bridge-build', bridgeRoot, 'corepack', ['pnpm', 'build']);
|
|
await run('sql-integration', bridgeRoot, process.execPath, ['--test', 'src/server/__tests__/sql-flow.integration.mjs']);
|
|
console.log(`SQL integration passed; retained source, generated lock and raw evidence: ${output}`);
|