From 0764acaadd70e7a53755afda16a2ba83cb33edf2 Mon Sep 17 00:00:00 2001 From: Andrey Avtomonov Date: Wed, 13 May 2026 18:50:30 +0200 Subject: [PATCH] fix(ingest): hide scan internals from public database ingest --- packages/cli/src/public-ingest.test.ts | 34 +++++++++++++++++++ packages/cli/src/public-ingest.ts | 47 +++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/public-ingest.test.ts b/packages/cli/src/public-ingest.test.ts index b23c7d27..8d596cc7 100644 --- a/packages/cli/src/public-ingest.test.ts +++ b/packages/cli/src/public-ingest.test.ts @@ -365,6 +365,40 @@ describe('runKtxPublicIngest', () => { ); }); + it('suppresses internal scan output for public database ingest summaries', async () => { + const io = makeIo(); + const project = projectWithConnections({ warehouse: { driver: 'postgres' } }); + const runScan = vi.fn(async (_args, scanIo) => { + scanIo.stdout.write('KTX scan completed\n'); + scanIo.stdout.write('Mode: structural\n'); + scanIo.stdout.write('Report: raw-sources/warehouse/live-database/sync-1/scan-report.json\n'); + scanIo.stdout.write('Raw sources: raw-sources/warehouse/live-database/sync-1\n'); + return 0; + }); + + await expect( + runKtxPublicIngest( + { + command: 'run', + projectDir: '/tmp/project', + targetConnectionId: 'warehouse', + all: false, + json: false, + inputMode: 'disabled', + }, + io.io, + { loadProject: vi.fn(async () => project), runScan }, + ), + ).resolves.toBe(0); + + expect(io.stdout()).toContain('Ingest finished\n'); + expect(io.stdout()).toContain('warehouse'); + expect(io.stdout()).not.toContain('KTX scan completed'); + expect(io.stdout()).not.toContain('Mode: structural'); + expect(io.stdout()).not.toContain('Report: raw-sources'); + expect(io.stdout()).not.toContain('live-database'); + }); + it('runs all independent targets and reports partial failures', async () => { const io = makeIo(); const project = projectWithConnections({ diff --git a/packages/cli/src/public-ingest.ts b/packages/cli/src/public-ingest.ts index 61c7819f..2c1b7aea 100644 --- a/packages/cli/src/public-ingest.ts +++ b/packages/cli/src/public-ingest.ts @@ -378,6 +378,7 @@ function markTargetResult( target: KtxPublicIngestPlanTarget, status: 'done' | 'failed', failedOperation?: KtxPublicIngestStepName, + failureDetail?: string, ): KtxPublicIngestTargetResult { const selectedFailedOperation = failedOperation ?? (target.operation === 'database-ingest' ? 'database-schema' : 'source-ingest'); @@ -395,7 +396,7 @@ function markTargetResult( return { ...step, status: 'failed', - detail: `${target.connectionId} failed at ${selectedFailedOperation}.`, + detail: failureDetail ?? `${target.connectionId} failed at ${selectedFailedOperation}.`, }; } return { ...step, status: 'not-run' }; @@ -454,6 +455,37 @@ function sourceIngestOutputMode(args: Extract line.trim()) + .find((line) => line.length > 0 && !line.startsWith('KTX scan completed')); +} + export async function executePublicIngestTarget( target: KtxPublicIngestPlanTarget, args: Extract, @@ -487,11 +519,18 @@ export async function executePublicIngestTarget( dryRun: false, }; const runScan = deps.runScan ?? runKtxScan; + const capturedScanIo = deps.scanProgress ? null : createCapturedPublicIngestIo(); + const scanIo = capturedScanIo ?? io; const scanExitCode = deps.scanProgress - ? await runScan(scanArgs, io, { progress: deps.scanProgress }) - : await runScan(scanArgs, io); + ? await runScan(scanArgs, scanIo, { progress: deps.scanProgress }) + : await runScan(scanArgs, scanIo); if (scanExitCode !== 0) { - return markTargetResult(target, 'failed', 'database-schema'); + return markTargetResult( + target, + 'failed', + 'database-schema', + capturedScanIo ? firstCapturedFailureLine(capturedScanIo.capturedOutput()) : undefined, + ); } if (target.queryHistory?.enabled === true) {