mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-07 07:55:13 +02:00
fix(scripts): make package artifacts pnpm launch work on Windows
Fix Windows package artifact script invocation under pnpm.
This commit is contained in:
parent
56985b7e09
commit
2a6fb19ba4
2 changed files with 226 additions and 125 deletions
|
|
@ -28,6 +28,20 @@ export const NPM_ARTIFACT_PACKAGES = [{ name: PUBLIC_NPM_PACKAGE_NAME, packageRo
|
|||
|
||||
export const CLI_PYTHON_ASSET_MANIFEST = 'manifest.json';
|
||||
|
||||
function pnpmCommand(args) {
|
||||
if (process.platform === 'win32') {
|
||||
return {
|
||||
command: 'cmd.exe',
|
||||
args: ['/d', '/s', '/c', 'pnpm', ...args],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
command: 'pnpm',
|
||||
args,
|
||||
};
|
||||
}
|
||||
|
||||
function scriptRootDir() {
|
||||
return resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
||||
}
|
||||
|
|
@ -70,8 +84,7 @@ export function packageArtifactLayout(rootDir = scriptRootDir(), version = publi
|
|||
export function buildArtifactCommands(layout) {
|
||||
return [
|
||||
{
|
||||
command: 'pnpm',
|
||||
args: ['--filter', PUBLIC_NPM_PACKAGE_NAME, 'run', 'build'],
|
||||
...pnpmCommand(['--filter', PUBLIC_NPM_PACKAGE_NAME, 'run', 'build']),
|
||||
cwd: layout.rootDir,
|
||||
},
|
||||
{
|
||||
|
|
@ -80,8 +93,7 @@ export function buildArtifactCommands(layout) {
|
|||
cwd: layout.rootDir,
|
||||
},
|
||||
{
|
||||
command: 'pnpm',
|
||||
args: ['pack', '--out', layout.cliTarball],
|
||||
...pnpmCommand(['pack', '--out', layout.cliTarball]),
|
||||
cwd: join(layout.rootDir, 'packages', 'cli'),
|
||||
},
|
||||
];
|
||||
|
|
@ -460,11 +472,19 @@ import { createRequire } from 'node:module';
|
|||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { DatabaseSync } from 'node:sqlite';
|
||||
import { setTimeout as delay } from 'node:timers/promises';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
function pnpmCommand(args) {
|
||||
if (process.platform === 'win32') {
|
||||
return { command: 'cmd.exe', args: ['/d', '/s', '/c', 'pnpm', ...args] };
|
||||
}
|
||||
return { command: 'pnpm', args };
|
||||
}
|
||||
|
||||
async function run(command, args, options = {}) {
|
||||
process.stdout.write('$ ' + command + ' ' + args.join(' ') + '\\n');
|
||||
try {
|
||||
|
|
@ -551,6 +571,21 @@ function requireIncludes(values, expected, label) {
|
|||
assert.ok(values.includes(expected), label + ' did not include ' + expected + ': ' + values.join(', '));
|
||||
}
|
||||
|
||||
async function rmWithRetry(path) {
|
||||
for (let attempt = 0; ; attempt += 1) {
|
||||
try {
|
||||
await rm(path, { recursive: true, force: true });
|
||||
return;
|
||||
} catch (error) {
|
||||
const code = typeof error?.code === 'string' ? error.code : '';
|
||||
if (attempt >= 4 || !['EBUSY', 'ENOTEMPTY', 'EPERM'].includes(code)) {
|
||||
throw error;
|
||||
}
|
||||
await delay(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function writeSqliteWarehouse(projectDir) {
|
||||
const database = new DatabaseSync(join(projectDir, 'warehouse.db'));
|
||||
try {
|
||||
|
|
@ -575,50 +610,58 @@ let daemonStarted = false;
|
|||
try {
|
||||
const projectDir = join(root, 'project');
|
||||
|
||||
const version = await run('pnpm', ['exec', 'ktx', '--version']);
|
||||
const version = await run(...Object.values(pnpmCommand(['exec', 'ktx', '--version'])));
|
||||
requireSuccess('ktx public package version', version);
|
||||
requireOutput('ktx public package version', version, await installedPackageVersionPattern());
|
||||
|
||||
const runtimeStatusBefore = parseJsonResultWithExitCode(
|
||||
'ktx admin runtime status missing',
|
||||
await run('pnpm', ['exec', 'ktx', 'admin', 'runtime', 'status', '--json']),
|
||||
await run(...Object.values(pnpmCommand(['exec', 'ktx', 'admin', 'runtime', 'status', '--json']))),
|
||||
1,
|
||||
);
|
||||
assert.equal(runtimeStatusBefore.kind, 'missing');
|
||||
assert.equal(runtimeStatusBefore.layout.runtimeRoot, process.env.KTX_RUNTIME_ROOT);
|
||||
process.stdout.write('ktx managed runtime starts missing in isolated root\\n');
|
||||
|
||||
const init = await run('pnpm', [
|
||||
'exec',
|
||||
'ktx',
|
||||
'setup',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
'--no-input',
|
||||
'--yes',
|
||||
'--skip-llm',
|
||||
'--skip-embeddings',
|
||||
'--skip-databases',
|
||||
'--skip-sources',
|
||||
'--skip-agents',
|
||||
]);
|
||||
const init = await run(
|
||||
...Object.values(
|
||||
pnpmCommand([
|
||||
'exec',
|
||||
'ktx',
|
||||
'setup',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
'--no-input',
|
||||
'--yes',
|
||||
'--skip-llm',
|
||||
'--skip-embeddings',
|
||||
'--skip-databases',
|
||||
'--skip-sources',
|
||||
'--skip-agents',
|
||||
]),
|
||||
),
|
||||
);
|
||||
requireSuccess('ktx setup', init);
|
||||
|
||||
const emptyProjectDir = join(root, 'empty-project');
|
||||
const emptyInit = await run('pnpm', [
|
||||
'exec',
|
||||
'ktx',
|
||||
'setup',
|
||||
'--project-dir',
|
||||
emptyProjectDir,
|
||||
'--no-input',
|
||||
'--yes',
|
||||
'--skip-llm',
|
||||
'--skip-embeddings',
|
||||
'--skip-databases',
|
||||
'--skip-sources',
|
||||
'--skip-agents',
|
||||
]);
|
||||
const emptyInit = await run(
|
||||
...Object.values(
|
||||
pnpmCommand([
|
||||
'exec',
|
||||
'ktx',
|
||||
'setup',
|
||||
'--project-dir',
|
||||
emptyProjectDir,
|
||||
'--no-input',
|
||||
'--yes',
|
||||
'--skip-llm',
|
||||
'--skip-embeddings',
|
||||
'--skip-databases',
|
||||
'--skip-sources',
|
||||
'--skip-agents',
|
||||
]),
|
||||
),
|
||||
);
|
||||
requireSuccess('ktx setup empty project', emptyInit);
|
||||
await writeFile(
|
||||
join(projectDir, 'ktx.yaml'),
|
||||
|
|
@ -658,17 +701,21 @@ try {
|
|||
'utf-8',
|
||||
);
|
||||
|
||||
const wikiSearch = await run('pnpm', [
|
||||
'exec',
|
||||
'ktx',
|
||||
'wiki',
|
||||
'revenue',
|
||||
'--json',
|
||||
'--limit',
|
||||
'5',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
]);
|
||||
const wikiSearch = await run(
|
||||
...Object.values(
|
||||
pnpmCommand([
|
||||
'exec',
|
||||
'ktx',
|
||||
'wiki',
|
||||
'revenue',
|
||||
'--json',
|
||||
'--limit',
|
||||
'5',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
]),
|
||||
),
|
||||
);
|
||||
const wikiSearchJson = parseJsonResult('ktx wiki search', wikiSearch);
|
||||
assert.equal(wikiSearchJson.kind, 'list');
|
||||
assert.equal(wikiSearchJson.data.items.length, 1);
|
||||
|
|
@ -700,17 +747,21 @@ try {
|
|||
await mkdir(join(projectDir, 'semantic-layer', 'warehouse'), { recursive: true });
|
||||
await writeFile(join(projectDir, 'semantic-layer', 'warehouse', 'orders.yaml'), slYaml, 'utf-8');
|
||||
|
||||
const slSearch = await run('pnpm', [
|
||||
'exec',
|
||||
'ktx',
|
||||
'sl',
|
||||
'orders',
|
||||
'--json',
|
||||
'--connection-id',
|
||||
'warehouse',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
]);
|
||||
const slSearch = await run(
|
||||
...Object.values(
|
||||
pnpmCommand([
|
||||
'exec',
|
||||
'ktx',
|
||||
'sl',
|
||||
'orders',
|
||||
'--json',
|
||||
'--connection-id',
|
||||
'warehouse',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
]),
|
||||
),
|
||||
);
|
||||
const slSearchJson = parseJsonResult('ktx sl search', slSearch);
|
||||
assert.equal(slSearchJson.kind, 'list');
|
||||
assert.equal(slSearchJson.data.items.length, 1);
|
||||
|
|
@ -720,17 +771,25 @@ try {
|
|||
requireIncludes(slSearchJson.data.items[0].matchReasons, 'lexical', 'sl search match reasons');
|
||||
process.stdout.write('ktx sl search hybrid metadata verified\\n');
|
||||
|
||||
const slQuery = await run('pnpm', ['exec', 'ktx', 'sl', 'query',
|
||||
'--connection-id',
|
||||
'warehouse',
|
||||
'--measure',
|
||||
'orders.order_count',
|
||||
'--format',
|
||||
'json',
|
||||
'--yes',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
]);
|
||||
const slQuery = await run(
|
||||
...Object.values(
|
||||
pnpmCommand([
|
||||
'exec',
|
||||
'ktx',
|
||||
'sl',
|
||||
'query',
|
||||
'--connection-id',
|
||||
'warehouse',
|
||||
'--measure',
|
||||
'orders.order_count',
|
||||
'--format',
|
||||
'json',
|
||||
'--yes',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
]),
|
||||
),
|
||||
);
|
||||
requireSuccessWithStderr(
|
||||
'ktx sl query first managed runtime install',
|
||||
slQuery,
|
||||
|
|
@ -741,27 +800,35 @@ try {
|
|||
|
||||
const runtimeStatusAfter = parseJsonResult(
|
||||
'ktx admin runtime status ready',
|
||||
await run('pnpm', ['exec', 'ktx', 'admin', 'runtime', 'status', '--json']),
|
||||
await run(...Object.values(pnpmCommand(['exec', 'ktx', 'admin', 'runtime', 'status', '--json']))),
|
||||
);
|
||||
assert.equal(runtimeStatusAfter.kind, 'ready');
|
||||
assert.deepEqual(runtimeStatusAfter.manifest.features, ['core']);
|
||||
assert.equal(runtimeStatusAfter.layout.runtimeRoot, process.env.KTX_RUNTIME_ROOT);
|
||||
process.stdout.write('ktx managed runtime lazy install verified\\n');
|
||||
|
||||
const sqliteSlQuery = await run('pnpm', ['exec', 'ktx', 'sl', 'query',
|
||||
'--connection-id',
|
||||
'warehouse',
|
||||
'--measure',
|
||||
'orders.order_count',
|
||||
'--format',
|
||||
'json',
|
||||
'--execute',
|
||||
'--max-rows',
|
||||
'100',
|
||||
'--yes',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
]);
|
||||
const sqliteSlQuery = await run(
|
||||
...Object.values(
|
||||
pnpmCommand([
|
||||
'exec',
|
||||
'ktx',
|
||||
'sl',
|
||||
'query',
|
||||
'--connection-id',
|
||||
'warehouse',
|
||||
'--measure',
|
||||
'orders.order_count',
|
||||
'--format',
|
||||
'json',
|
||||
'--execute',
|
||||
'--max-rows',
|
||||
'100',
|
||||
'--yes',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
]),
|
||||
),
|
||||
);
|
||||
requireSuccess('ktx sl query sqlite execute', sqliteSlQuery);
|
||||
requireOutput('ktx sl query sqlite execute', sqliteSlQuery, /"dialect": "sqlite"/);
|
||||
requireOutput('ktx sl query sqlite execute', sqliteSlQuery, /"mode": "executed"/);
|
||||
|
|
@ -769,36 +836,35 @@ try {
|
|||
requireOutput('ktx sl query sqlite execute', sqliteSlQuery, /"rows": \\[\\s*\\[\\s*3\\s*\\]\\s*\\]/);
|
||||
process.stdout.write('ktx sl query sqlite execute verified\\n');
|
||||
|
||||
const runtimeDoctor = await run('pnpm', ['exec', 'ktx', 'admin', 'runtime', 'status']);
|
||||
const runtimeDoctor = await run(...Object.values(pnpmCommand(['exec', 'ktx', 'admin', 'runtime', 'status'])));
|
||||
requireSuccess('ktx admin runtime status', runtimeDoctor);
|
||||
requireOutput('ktx admin runtime status', runtimeDoctor, /KTX Python runtime/);
|
||||
requireOutput('ktx admin runtime status', runtimeDoctor, /status: ready/);
|
||||
process.stdout.write('ktx admin runtime status verified\\n');
|
||||
|
||||
const runtimeStart = await run('pnpm', ['exec', 'ktx', 'admin', 'runtime', 'start']);
|
||||
const runtimeStart = await run(...Object.values(pnpmCommand(['exec', 'ktx', 'admin', 'runtime', 'start'])));
|
||||
requireSuccess('ktx admin runtime start', runtimeStart);
|
||||
daemonStarted = true;
|
||||
requireOutput('ktx admin runtime start', runtimeStart, /Started KTX daemon/);
|
||||
requireOutput('ktx admin runtime start', runtimeStart, /url: http:\\/\\/127\\.0\\.0\\.1:\\d+/);
|
||||
requireOutput('ktx admin runtime start', runtimeStart, /features: core/);
|
||||
|
||||
const runtimeStartReuse = await run('pnpm', ['exec', 'ktx', 'admin', 'runtime', 'start']);
|
||||
const runtimeStartReuse = await run(...Object.values(pnpmCommand(['exec', 'ktx', 'admin', 'runtime', 'start'])));
|
||||
requireSuccess('ktx admin runtime start reuse', runtimeStartReuse);
|
||||
requireOutput('ktx admin runtime start reuse', runtimeStartReuse, /Using existing KTX daemon/);
|
||||
requireOutput('ktx admin runtime start reuse', runtimeStartReuse, /features: core/);
|
||||
|
||||
const runtimeStop = await run('pnpm', ['exec', 'ktx', 'admin', 'runtime', 'stop']);
|
||||
const runtimeStop = await run(...Object.values(pnpmCommand(['exec', 'ktx', 'admin', 'runtime', 'stop'])));
|
||||
requireSuccess('ktx admin runtime stop', runtimeStop);
|
||||
daemonStarted = false;
|
||||
requireOutput('ktx admin runtime stop', runtimeStop, /Stopped KTX daemon/);
|
||||
process.stdout.write('ktx admin runtime daemon lifecycle verified\\n');
|
||||
|
||||
const structuralScan = await run('pnpm', ['exec', 'ktx', 'ingest', 'warehouse',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
'--fast',
|
||||
'--no-input',
|
||||
]);
|
||||
const structuralScan = await run(
|
||||
...Object.values(
|
||||
pnpmCommand(['exec', 'ktx', 'ingest', 'warehouse', '--project-dir', projectDir, '--fast', '--no-input']),
|
||||
),
|
||||
);
|
||||
requireSuccessWithProjectStderr('ktx ingest fast', structuralScan, projectDir);
|
||||
requireOutput('ktx ingest fast', structuralScan, /Ingest finished/);
|
||||
requireOutput('ktx ingest fast', structuralScan, /Database schema/);
|
||||
|
|
@ -806,12 +872,11 @@ try {
|
|||
await access(join(projectDir, 'semantic-layer', 'warehouse', '_schema', 'public.yaml'));
|
||||
process.stdout.write('ktx ingest fast verified\\n');
|
||||
|
||||
const enrichedScan = await run('pnpm', ['exec', 'ktx', 'ingest', 'warehouse',
|
||||
'--project-dir',
|
||||
projectDir,
|
||||
'--deep',
|
||||
'--no-input',
|
||||
]);
|
||||
const enrichedScan = await run(
|
||||
...Object.values(
|
||||
pnpmCommand(['exec', 'ktx', 'ingest', 'warehouse', '--project-dir', projectDir, '--deep', '--no-input']),
|
||||
),
|
||||
);
|
||||
requireExitCodeWithProjectStderr('ktx ingest deep readiness guard', enrichedScan, projectDir, 1);
|
||||
requireOutput('ktx ingest deep readiness guard', enrichedScan, /Ingest finished with partial failures/);
|
||||
requireOutput('ktx ingest deep readiness guard', enrichedScan, /requires deep ingest readiness/);
|
||||
|
|
@ -821,14 +886,15 @@ try {
|
|||
process.stdout.write('ktx ingest state verified\\n');
|
||||
} finally {
|
||||
if (daemonStarted) {
|
||||
await run('pnpm', ['exec', 'ktx', 'admin', 'runtime', 'stop']);
|
||||
await run(...Object.values(pnpmCommand(['exec', 'ktx', 'admin', 'runtime', 'stop'])));
|
||||
await delay(500);
|
||||
}
|
||||
if (previousRuntimeRoot === undefined) {
|
||||
delete process.env.KTX_RUNTIME_ROOT;
|
||||
} else {
|
||||
process.env.KTX_RUNTIME_ROOT = previousRuntimeRoot;
|
||||
}
|
||||
await rm(root, { recursive: true, force: true });
|
||||
await rmWithRetry(root);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
|
@ -844,6 +910,13 @@ import { promisify } from 'node:util';
|
|||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
function pnpmCommand(args) {
|
||||
if (process.platform === 'win32') {
|
||||
return { command: 'cmd.exe', args: ['/d', '/s', '/c', 'pnpm', ...args] };
|
||||
}
|
||||
return { command: 'pnpm', args };
|
||||
}
|
||||
|
||||
async function run(command, args, options = {}) {
|
||||
process.stdout.write('$ ' + command + ' ' + args.join(' ') + '\\n');
|
||||
try {
|
||||
|
|
@ -880,17 +953,17 @@ try {
|
|||
const packageJson = JSON.parse(await readFile(join(process.cwd(), 'package.json'), 'utf8'));
|
||||
assert.deepEqual(Object.keys(packageJson.dependencies), ['@kaelio/ktx']);
|
||||
|
||||
const help = await run('pnpm', ['exec', 'ktx', '--help']);
|
||||
const help = await run(...Object.values(pnpmCommand(['exec', 'ktx', '--help'])));
|
||||
requireSuccess('ktx --help', help);
|
||||
requireStdout('ktx --help', help, /Usage: ktx/);
|
||||
requireStdout('ktx --help', help, /setup/);
|
||||
|
||||
const setupHelp = await run('pnpm', ['exec', 'ktx', 'setup', '--help']);
|
||||
const setupHelp = await run(...Object.values(pnpmCommand(['exec', 'ktx', 'setup', '--help'])));
|
||||
requireSuccess('ktx setup --help', setupHelp);
|
||||
requireStdout('ktx setup --help', setupHelp, /Usage: ktx setup/);
|
||||
requireStdout('ktx setup --help', setupHelp, /--no-input/);
|
||||
|
||||
const doctor = await run('pnpm', ['exec', 'ktx', 'status', '--verbose', '--no-input']);
|
||||
const doctor = await run(...Object.values(pnpmCommand(['exec', 'ktx', 'status', '--verbose', '--no-input'])));
|
||||
assert.ok([0, 1].includes(doctor.code), 'ktx status setup exit code must be 0 or 1');
|
||||
requireStdout('ktx status setup', doctor, /KTX status/);
|
||||
requireStdout('ktx status setup', doctor, /No project here yet\\./);
|
||||
|
|
@ -949,10 +1022,19 @@ async function verifyNpmArtifacts(layout, tmpRoot) {
|
|||
await writeFile(join(projectDir, 'verify-installed-cli.mjs'), npmRuntimeSmokeSource());
|
||||
await writeFile(join(projectDir, 'verify-installed-cli-commands.mjs'), npmCliSmokeSource());
|
||||
|
||||
await runCommand('pnpm', ['install'], { cwd: projectDir });
|
||||
await runCommand('pnpm', ['rebuild', 'better-sqlite3'], { cwd: projectDir });
|
||||
{
|
||||
const pnpmInstall = pnpmCommand(['install']);
|
||||
await runCommand(pnpmInstall.command, pnpmInstall.args, { cwd: projectDir });
|
||||
}
|
||||
{
|
||||
const pnpmRebuild = pnpmCommand(['rebuild', 'better-sqlite3']);
|
||||
await runCommand(pnpmRebuild.command, pnpmRebuild.args, { cwd: projectDir });
|
||||
}
|
||||
await runCommand('node', ['verify-npm.mjs'], { cwd: projectDir });
|
||||
await runCommand('pnpm', ['exec', 'ktx', '--version'], { cwd: projectDir });
|
||||
{
|
||||
const pnpmExecVersion = pnpmCommand(['exec', 'ktx', '--version']);
|
||||
await runCommand(pnpmExecVersion.command, pnpmExecVersion.args, { cwd: projectDir });
|
||||
}
|
||||
await runCommand('node', ['verify-installed-cli.mjs'], { cwd: projectDir });
|
||||
await runCommand('node', ['verify-installed-cli-commands.mjs'], { cwd: projectDir });
|
||||
}
|
||||
|
|
@ -968,7 +1050,10 @@ async function verifyNpmCliArtifacts(layout, tmpRoot) {
|
|||
await writeFile(join(projectDir, 'pnpm-workspace.yaml'), npmSmokePnpmWorkspaceYaml());
|
||||
await writeFile(join(projectDir, 'verify-installed-cli-commands.mjs'), npmCliSmokeSource());
|
||||
|
||||
await runCommand('pnpm', ['install'], { cwd: projectDir });
|
||||
{
|
||||
const pnpmInstall = pnpmCommand(['install']);
|
||||
await runCommand(pnpmInstall.command, pnpmInstall.args, { cwd: projectDir });
|
||||
}
|
||||
await runCommand('node', ['verify-installed-cli-commands.mjs'], { cwd: projectDir });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,12 +97,12 @@ describe('packageArtifactLayout', () => {
|
|||
it('uses stable artifact paths under ktx/dist/artifacts', () => {
|
||||
const layout = packageArtifactLayout('/repo/ktx', PUBLIC_NPM_PACKAGE_VERSION);
|
||||
|
||||
assert.equal(layout.artifactDir, '/repo/ktx/dist/artifacts');
|
||||
assert.equal(layout.npmDir, '/repo/ktx/dist/artifacts/npm');
|
||||
assert.equal(layout.pythonDir, '/repo/ktx/dist/artifacts/python');
|
||||
assert.equal(layout.artifactDir, join('/repo/ktx', 'dist', 'artifacts'));
|
||||
assert.equal(layout.npmDir, join('/repo/ktx', 'dist', 'artifacts', 'npm'));
|
||||
assert.equal(layout.pythonDir, join('/repo/ktx', 'dist', 'artifacts', 'python'));
|
||||
assert.equal(
|
||||
layout.cliTarball,
|
||||
`/repo/ktx/dist/artifacts/npm/kaelio-ktx-${PUBLIC_NPM_PACKAGE_VERSION}.tgz`,
|
||||
join('/repo/ktx', 'dist', 'artifacts', 'npm', `kaelio-ktx-${PUBLIC_NPM_PACKAGE_VERSION}.tgz`),
|
||||
);
|
||||
assert.deepEqual(Object.keys(layout.npmTarballs), ['@kaelio/ktx']);
|
||||
});
|
||||
|
|
@ -112,17 +112,21 @@ describe('buildArtifactCommands', () => {
|
|||
it('builds the CLI package, then the runtime wheel, then packs the npm tarball directly', () => {
|
||||
const layout = packageArtifactLayout('/repo/ktx', PUBLIC_NPM_PACKAGE_VERSION);
|
||||
const commands = buildArtifactCommands(layout);
|
||||
const expectedBuildCommand =
|
||||
process.platform === 'win32'
|
||||
? ['cmd.exe', ['/d', '/s', '/c', 'pnpm', '--filter', '@kaelio/ktx', 'run', 'build'], layout.rootDir]
|
||||
: ['pnpm', ['--filter', '@kaelio/ktx', 'run', 'build'], layout.rootDir];
|
||||
const expectedPackCommand =
|
||||
process.platform === 'win32'
|
||||
? ['cmd.exe', ['/d', '/s', '/c', 'pnpm', 'pack', '--out', layout.cliTarball], join('/repo/ktx', 'packages', 'cli')]
|
||||
: ['pnpm', ['pack', '--out', layout.cliTarball], join('/repo/ktx', 'packages', 'cli')];
|
||||
|
||||
assert.deepEqual(
|
||||
commands.map((command) => [command.command, command.args, command.cwd]),
|
||||
[
|
||||
['pnpm', ['--filter', '@kaelio/ktx', 'run', 'build'], '/repo/ktx'],
|
||||
[process.execPath, ['scripts/build-python-runtime-wheel.mjs'], '/repo/ktx'],
|
||||
[
|
||||
'pnpm',
|
||||
['pack', '--out', `/repo/ktx/dist/artifacts/npm/kaelio-ktx-${PUBLIC_NPM_PACKAGE_VERSION}.tgz`],
|
||||
'/repo/ktx/packages/cli',
|
||||
],
|
||||
expectedBuildCommand,
|
||||
[process.execPath, ['scripts/build-python-runtime-wheel.mjs'], layout.rootDir],
|
||||
expectedPackCommand,
|
||||
],
|
||||
);
|
||||
});
|
||||
|
|
@ -476,18 +480,27 @@ describe('verification snippets', () => {
|
|||
it('runs installed CLI commands through the public package runtime', () => {
|
||||
const source = npmRuntimeSmokeSource();
|
||||
|
||||
assert.match(source, /function pnpmCommand\(args\)/);
|
||||
assert.match(source, /process\.platform === 'win32'/);
|
||||
assert.match(source, /command: 'cmd\.exe'/);
|
||||
assert.match(source, /args: \['\/d', '\/s', '\/c', 'pnpm', \.\.\.args\]/);
|
||||
assert.match(source, /import \{ setTimeout as delay \} from 'node:timers\/promises';/);
|
||||
assert.match(source, /async function rmWithRetry\(path\)/);
|
||||
assert.match(source, /await delay\(500\)/);
|
||||
assert.match(source, /await rmWithRetry\(root\)/);
|
||||
assert.match(source, /ktx public package version/);
|
||||
assert.match(source, /installedPackageVersionPattern/);
|
||||
assert.doesNotMatch(source, /@kaelio\\\/ktx 0\\\.1\\\.0/);
|
||||
assert.match(source, /'ktx', 'sl', 'query'/);
|
||||
assert.match(source, /pnpmCommand\(\[\s*'exec',\s*'ktx',\s*'sl',\s*'query'/);
|
||||
assert.doesNotMatch(source, /@ktx\/context/);
|
||||
assert.doesNotMatch(source, /@modelcontextprotocol/);
|
||||
assert.doesNotMatch(source, /startSemanticDaemon/);
|
||||
assert.match(source, /run\('pnpm', \[\s*'exec',\s*'ktx',\s*'setup'/);
|
||||
assert.doesNotMatch(source, /run\('pnpm',/);
|
||||
assert.match(source, /pnpmCommand\(\[\s*'exec',\s*'ktx',\s*'setup'/);
|
||||
assert.match(source, /wiki', 'global', 'revenue\.md'/);
|
||||
assert.match(source, /run\('pnpm', \[\s*'exec',\s*'ktx',\s*'wiki',\s*'revenue'/);
|
||||
assert.match(source, /pnpmCommand\(\[\s*'exec',\s*'ktx',\s*'wiki',\s*'revenue'/);
|
||||
assert.match(source, /semantic-layer', 'warehouse', 'orders\.yaml'/);
|
||||
assert.match(source, /run\('pnpm', \[\s*'exec',\s*'ktx',\s*'sl',\s*'orders'/);
|
||||
assert.match(source, /pnpmCommand\(\[\s*'exec',\s*'ktx',\s*'sl',\s*'orders'/);
|
||||
assert.match(source, /orders\.order_count/);
|
||||
assert.match(source, /node:sqlite/);
|
||||
assert.match(source, /driver: sqlite/);
|
||||
|
|
@ -516,7 +529,7 @@ describe('verification snippets', () => {
|
|||
assert.match(source, /ktx admin runtime stop/);
|
||||
assert.doesNotMatch(source, /ktx admin runtime prune/);
|
||||
assert.doesNotMatch(source, /staleRuntimeDir/);
|
||||
assert.match(source, /run\('pnpm', \[\s*'exec',\s*'ktx',\s*'ingest',\s*'warehouse'/);
|
||||
assert.match(source, /pnpmCommand\(\['exec', 'ktx', 'ingest', 'warehouse'/);
|
||||
assert.match(source, /'--deep'/);
|
||||
assert.doesNotMatch(source, /'--enrich'/);
|
||||
assert.match(source, /ktx ingest fast verified/);
|
||||
|
|
@ -534,8 +547,11 @@ describe('verification snippets', () => {
|
|||
it('exercises supported public package CLI commands', () => {
|
||||
const source = npmCliSmokeSource();
|
||||
|
||||
assert.match(source, /pnpm', \['exec', 'ktx', '--help'\]/);
|
||||
assert.match(source, /pnpm', \['exec', 'ktx', 'setup', '--help'\]/);
|
||||
assert.match(source, /function pnpmCommand\(args\)/);
|
||||
assert.match(source, /process\.platform === 'win32'/);
|
||||
assert.doesNotMatch(source, /run\('pnpm',/);
|
||||
assert.match(source, /pnpmCommand\(\['exec', 'ktx', '--help'\]\)/);
|
||||
assert.match(source, /pnpmCommand\(\['exec', 'ktx', 'setup', '--help'\]\)/);
|
||||
assert.match(source, /Usage: ktx setup/);
|
||||
assert.doesNotMatch(source, new RegExp(["'demo'", "'--mode'", "'deterministic'"].join(', ')));
|
||||
assert.match(source, /'status', '--verbose', '--no-input'/);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue