mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-13 08:15:14 +02:00
Fix CI smoke checks
This commit is contained in:
parent
2fd2bfde98
commit
3ee48e0752
8 changed files with 34 additions and 30 deletions
|
|
@ -124,7 +124,7 @@ function deepReadyProject(connections: KtxProjectConfig['connections'], relation
|
|||
connections,
|
||||
llm: {
|
||||
...config.llm,
|
||||
provider: { backend: 'gateway', gateway: { api_key: 'env:KTX_GATEWAY_API_KEY' } },
|
||||
provider: { backend: 'gateway', gateway: { api_key: 'env:KTX_GATEWAY_API_KEY' } }, // pragma: allowlist secret
|
||||
models: { default: 'gpt-test' },
|
||||
},
|
||||
scan: {
|
||||
|
|
@ -785,7 +785,7 @@ Add these tests near the existing setup context build tests:
|
|||
await writeReadyProject(tempDir, {
|
||||
connections: { warehouse: { driver: 'postgres', readonly: true } },
|
||||
llm: {
|
||||
provider: { backend: 'gateway', gateway: { api_key: 'env:KTX_GATEWAY_API_KEY' } },
|
||||
provider: { backend: 'gateway', gateway: { api_key: 'env:KTX_GATEWAY_API_KEY' } }, // pragma: allowlist secret
|
||||
models: { default: 'gpt-test' },
|
||||
},
|
||||
scan: {
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ existing `runContextBuild` tests:
|
|||
warehouse: { driver: 'postgres', context: { depth: 'deep' } },
|
||||
},
|
||||
llm: {
|
||||
provider: { backend: 'gateway', gateway: { api_key: 'env:KTX_GATEWAY_API_KEY' } },
|
||||
provider: { backend: 'gateway', gateway: { api_key: 'env:KTX_GATEWAY_API_KEY' } }, // pragma: allowlist secret
|
||||
models: { default: 'gpt-test' },
|
||||
},
|
||||
scan: {
|
||||
|
|
|
|||
|
|
@ -911,7 +911,7 @@ describe('runContextBuild', () => {
|
|||
warehouse: { driver: 'postgres', context: { depth: 'deep' } },
|
||||
},
|
||||
llm: {
|
||||
provider: { backend: 'gateway', gateway: { api_key: 'env:KTX_GATEWAY_API_KEY' } },
|
||||
provider: { backend: 'gateway', gateway: { api_key: 'env:KTX_GATEWAY_API_KEY' } }, // pragma: allowlist secret
|
||||
models: { default: 'gpt-test' },
|
||||
},
|
||||
scan: {
|
||||
|
|
|
|||
|
|
@ -330,8 +330,8 @@ describe('runKtxDoctor', () => {
|
|||
});
|
||||
|
||||
it('includes Postgres query-history readiness in project doctor output', async () => {
|
||||
process.env.ANTHROPIC_API_KEY = 'test-key';
|
||||
process.env.OPENAI_API_KEY = 'test-key';
|
||||
process.env.ANTHROPIC_API_KEY = 'test-key'; // pragma: allowlist secret
|
||||
process.env.OPENAI_API_KEY = 'test-key'; // pragma: allowlist secret
|
||||
await writeFile(
|
||||
join(tempDir, 'ktx.yaml'),
|
||||
[
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ describe('standalone local warehouse example', () => {
|
|||
'fake',
|
||||
]);
|
||||
expect(ingest).toMatchObject({ code: 1, stdout: '' });
|
||||
expect(ingest.stderr).toContain("unknown command 'run'");
|
||||
expect(ingest.stderr).toContain("unknown option '--connection-id'");
|
||||
}, 30_000);
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,12 +26,13 @@ function isExecFailure(error: unknown): error is ExecFailure {
|
|||
return error instanceof Error && ('stdout' in error || 'stderr' in error || 'code' in error);
|
||||
}
|
||||
|
||||
async function runBuiltCli(args: string[], options: { env?: NodeJS.ProcessEnv } = {}): Promise<CliResult> {
|
||||
async function runBuiltCli(args: string[], options: { cwd?: string; env?: NodeJS.ProcessEnv } = {}): Promise<CliResult> {
|
||||
try {
|
||||
const result = await execFileAsync(process.execPath, [CLI_BIN, ...args], {
|
||||
...(options.cwd ? { cwd: options.cwd } : {}),
|
||||
encoding: 'utf8',
|
||||
timeout: 20_000,
|
||||
...(options.env ? { env: options.env } : {}),
|
||||
env: options.env ?? process.env,
|
||||
});
|
||||
return {
|
||||
code: 0,
|
||||
|
|
@ -166,11 +167,13 @@ describe('standalone built ktx CLI smoke', () => {
|
|||
});
|
||||
|
||||
it('runs doctor setup through the built binary', async () => {
|
||||
const result = await runBuiltCli(['status', '--no-input']);
|
||||
const env = { ...process.env };
|
||||
delete env.KTX_PROJECT_DIR;
|
||||
const result = await runBuiltCli(['status', '--no-input'], { cwd: tempDir, env });
|
||||
|
||||
expect(result.stdout).toMatch(/KTX (setup doctor|project doctor|status)/);
|
||||
if (result.stdout.includes('No project here yet.')) {
|
||||
expect(result.stdout).toContain('Before you can run ktx setup');
|
||||
expect(result.stdout).toContain('ktx setup');
|
||||
} else {
|
||||
expect(result.stdout).toContain('Node 22+');
|
||||
expect(result.stdout).toContain('Workspace-local CLI');
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ function requireSuccess(label, result) {
|
|||
assert.equal(result.stderr, '', label + ' wrote unexpected stderr');
|
||||
}
|
||||
|
||||
function requireProjectStderr(label, result, projectDir) {
|
||||
function requireSuccessWithProjectStderr(label, result, projectDir) {
|
||||
assert.equal(
|
||||
result.code,
|
||||
0,
|
||||
|
|
@ -527,6 +527,15 @@ function requireProjectStderr(label, result, projectDir) {
|
|||
assert.equal(result.stderr, 'Project: ' + projectDir + '\\n', label + ' wrote unexpected stderr');
|
||||
}
|
||||
|
||||
function requireExitCodeWithProjectStderr(label, result, projectDir, expectedCode) {
|
||||
assert.equal(
|
||||
result.code,
|
||||
expectedCode,
|
||||
label + ' failed with code ' + result.code + '\\nstdout:\\n' + result.stdout + '\\nstderr:\\n' + result.stderr,
|
||||
);
|
||||
assert.equal(result.stderr, 'Project: ' + projectDir + '\\n', label + ' wrote unexpected stderr');
|
||||
}
|
||||
|
||||
function requireSuccessWithStderr(label, result, stderrPattern) {
|
||||
assert.equal(
|
||||
result.code,
|
||||
|
|
@ -559,12 +568,6 @@ function requireIncludes(values, expected, label) {
|
|||
assert.ok(values.includes(expected), label + ' did not include ' + expected + ': ' + values.join(', '));
|
||||
}
|
||||
|
||||
function getRunId(stdout) {
|
||||
const match = stdout.match(/^Run: (.+)$/m);
|
||||
assert.ok(match, 'ingest output did not include a run id');
|
||||
return match[1];
|
||||
}
|
||||
|
||||
async function writeSqliteWarehouse(projectDir) {
|
||||
const database = new DatabaseSync(join(projectDir, 'warehouse.db'));
|
||||
try {
|
||||
|
|
@ -618,7 +621,6 @@ try {
|
|||
'--skip-agents',
|
||||
]);
|
||||
requireSuccess('ktx setup', init);
|
||||
requireOutput('ktx setup', init, /Project: /);
|
||||
|
||||
const emptyProjectDir = join(root, 'empty-project');
|
||||
const emptyInit = await run('pnpm', [
|
||||
|
|
@ -819,13 +821,12 @@ try {
|
|||
'--fast',
|
||||
'--no-input',
|
||||
]);
|
||||
requireProjectStderr('ktx ingest fast', structuralScan, projectDir);
|
||||
requireSuccessWithProjectStderr('ktx ingest fast', structuralScan, projectDir);
|
||||
requireOutput('ktx ingest fast', structuralScan, /Ingest finished/);
|
||||
requireOutput('ktx ingest fast', structuralScan, /Database schema/);
|
||||
requireOutput('ktx ingest fast', structuralScan, /warehouse\\s+done/);
|
||||
const structuralScanRunId = getRunId(structuralScan.stdout);
|
||||
await access(join(projectDir, 'semantic-layer', 'warehouse', '_schema', 'public.yaml'));
|
||||
process.stdout.write('ktx ingest fast verified: ' + structuralScanRunId + '\\n');
|
||||
process.stdout.write('ktx ingest fast verified\\n');
|
||||
|
||||
const enrichedScan = await run('pnpm', ['exec', 'ktx', 'ingest', 'warehouse',
|
||||
'--project-dir',
|
||||
|
|
@ -833,12 +834,10 @@ try {
|
|||
'--deep',
|
||||
'--no-input',
|
||||
]);
|
||||
requireProjectStderr('ktx ingest deep', enrichedScan, projectDir);
|
||||
requireOutput('ktx ingest deep', enrichedScan, /Ingest finished/);
|
||||
requireOutput('ktx ingest deep', enrichedScan, /Database schema/);
|
||||
requireOutput('ktx ingest deep', enrichedScan, /warehouse\\s+done/);
|
||||
const enrichedScanRunId = getRunId(enrichedScan.stdout);
|
||||
process.stdout.write('ktx ingest deep verified: ' + enrichedScanRunId + '\\n');
|
||||
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/);
|
||||
process.stdout.write('ktx ingest deep readiness guard verified\\n');
|
||||
|
||||
await access(join(projectDir, '.ktx', 'db.sqlite'));
|
||||
process.stdout.write('ktx ingest state verified\\n');
|
||||
|
|
@ -917,7 +916,7 @@ try {
|
|||
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\\./);
|
||||
requireStdout('ktx status setup', doctor, /Before you can run ktx setup/);
|
||||
requireStdout('ktx status setup', doctor, /ktx setup/);
|
||||
assert.equal(doctor.stderr, '', 'ktx status setup wrote unexpected stderr');
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true });
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ describe('verification snippets', () => {
|
|||
assert.match(source, /'--deep'/);
|
||||
assert.doesNotMatch(source, /'--enrich'/);
|
||||
assert.match(source, /ktx ingest fast verified/);
|
||||
assert.match(source, /ktx ingest deep verified/);
|
||||
assert.match(source, /ktx ingest deep readiness guard verified/);
|
||||
assert.match(source, /enrichment:/);
|
||||
assert.match(source, /mode: deterministic/);
|
||||
assert.doesNotMatch(source, /run\('pnpm', \['exec', 'ktx', 'ingest', 'run'/);
|
||||
|
|
@ -511,6 +511,8 @@ describe('verification snippets', () => {
|
|||
assert.match(source, /Usage: ktx setup/);
|
||||
assert.doesNotMatch(source, new RegExp(["'demo'", "'--mode'", "'deterministic'"].join(', ')));
|
||||
assert.match(source, /'status', '--no-input'/);
|
||||
assert.match(source, /KTX status/);
|
||||
assert.match(source, /No project here yet/);
|
||||
assert.doesNotMatch(source, /function requireProjectStderr/);
|
||||
assert.match(source, /Object\.keys\(packageJson\.dependencies\)/);
|
||||
assert.match(source, /'@kaelio\/ktx'/);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue