From ddaaaa27be9ae3c275bd466311731c717b3ca6cf Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Sun, 19 Jul 2026 00:29:50 +0200 Subject: [PATCH] fix(desktop): flush migration output before completion --- .../src/integrations/migrations/process.test.ts | 16 +++++++++++++++- .../src/integrations/migrations/process.ts | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/desktop/src/integrations/migrations/process.test.ts b/packages/desktop/src/integrations/migrations/process.test.ts index 83e6971b92..ff2b0795a1 100644 --- a/packages/desktop/src/integrations/migrations/process.test.ts +++ b/packages/desktop/src/integrations/migrations/process.test.ts @@ -50,6 +50,8 @@ test("launches the exact version-matched bundled command and streams completion" child.stdout.write("Found one project\n"); child.stderr.write("warning\n"); child.emitExit(0); + child.stdout.write("Migration complete\n"); + child.emitClose(0); expect(invocations).toEqual([ { @@ -64,6 +66,7 @@ test("launches the exact version-matched bundled command and streams completion" expect(outputs).toEqual([ { runId, stream: "stdout", chunk: "Found one project\n" }, { runId, stream: "stderr", chunk: "warning\n" }, + { runId, stream: "stdout", chunk: "Migration complete\n" }, { runId, stream: "status", exitCode: 0 }, ]); expect(invocations[0]?.env.PASEO_PASSWORD).toBeUndefined(); @@ -81,6 +84,10 @@ test("allows only one migration process at a time", async () => { "A migration is already running.", ); child.emitExit(0); + await expect(migrations.run("source-fixture", () => undefined)).rejects.toThrow( + "A migration is already running.", + ); + child.emitClose(0); await expect(migrations.run("source-fixture", () => undefined)).resolves.toEqual( expect.any(String), ); @@ -186,11 +193,18 @@ function fakeChild(): { stdout: PassThrough; stderr: PassThrough; emitExit(code: number): void; + emitClose(code: number): void; } { const events = new EventEmitter(); const stdout = new PassThrough(); const stderr = new PassThrough(); const process = events as ChildProcess; Object.assign(process, { stdout, stderr }); - return { process, stdout, stderr, emitExit: (code) => events.emit("exit", code, null) }; + return { + process, + stdout, + stderr, + emitExit: (code) => events.emit("exit", code, null), + emitClose: (code) => events.emit("close", code, null), + }; } diff --git a/packages/desktop/src/integrations/migrations/process.ts b/packages/desktop/src/integrations/migrations/process.ts index 2a42c1e403..d9ce4c72a3 100644 --- a/packages/desktop/src/integrations/migrations/process.ts +++ b/packages/desktop/src/integrations/migrations/process.ts @@ -114,7 +114,7 @@ export class DesktopMigrationProcess { emit({ runId, stream: "stderr", chunk: `${error.message}\n` }); emit({ runId, stream: "status", exitCode: 1 }); }); - child.once("exit", (code) => { + child.once("close", (code) => { if (settled) return; settled = true; this.activeRunId = null;