From 85f552bf376c338d96a3f522600d880f776c8cde Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 20 Jun 2026 19:20:11 +0200 Subject: [PATCH] fix(qa): clean failed Parallels package locks --- scripts/e2e/parallels/package-artifact.ts | 14 ++++++++++++-- test/scripts/parallels-smoke-model.test.ts | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/scripts/e2e/parallels/package-artifact.ts b/scripts/e2e/parallels/package-artifact.ts index 5251bfe2ab2..1eb1da4cff0 100644 --- a/scripts/e2e/parallels/package-artifact.ts +++ b/scripts/e2e/parallels/package-artifact.ts @@ -194,18 +194,27 @@ async function withPackageLock(lockDir: string, fn: () => Promise): Promis } } -async function acquirePackageLock(lockDir: string, ownerToken: string): Promise { +async function acquirePackageLock( + lockDir: string, + ownerToken: string, + params: { writeOwner?: (lockDir: string, ownerToken: string) => Promise } = {}, +): Promise { const timeoutMs = readPositiveIntEnv("OPENCLAW_PARALLELS_PACKAGE_LOCK_TIMEOUT_MS", 30 * 60_000); const staleMs = readPositiveIntEnv("OPENCLAW_PARALLELS_PACKAGE_LOCK_STALE_MS", 2 * 60 * 60_000); const startedAt = Date.now(); let waitAnnouncementBudget = 1; const consumeWaitAnnouncement = () => waitAnnouncementBudget-- > 0; while (Date.now() - startedAt < timeoutMs) { + let createdLockDir = false; try { await mkdir(lockDir); - await writeLockOwner(lockDir, ownerToken); + createdLockDir = true; + await (params.writeOwner ?? writeLockOwner)(lockDir, ownerToken); return; } catch (error) { + if (createdLockDir) { + await rm(lockDir, { force: true, recursive: true }).catch(() => undefined); + } if (!isErrorCode(error, "EEXIST")) { throw error; } @@ -292,6 +301,7 @@ async function delay(ms: number): Promise { } export const testing = { + acquirePackageLock, removeStalePackageLock, readLockOwner, }; diff --git a/test/scripts/parallels-smoke-model.test.ts b/test/scripts/parallels-smoke-model.test.ts index 21acd0cf9e4..b75cf588001 100644 --- a/test/scripts/parallels-smoke-model.test.ts +++ b/test/scripts/parallels-smoke-model.test.ts @@ -474,6 +474,22 @@ describe("Parallels smoke model selection", () => { expect(existsSync(lockDir)).toBe(false); }); + it("removes a just-created package lock when owner writing fails", async () => { + const parentDir = makeTempDir(tempDirs, "openclaw-parallels-package-lock-parent-"); + const lockDir = join(parentDir, "package.lock"); + const error = new Error("failed to write owner"); + + await expect( + packageArtifactTesting.acquirePackageLock(lockDir, "owner-token", { + writeOwner: async () => { + throw error; + }, + }), + ).rejects.toBe(error); + + expect(existsSync(lockDir)).toBe(false); + }); + it("keeps JSON-mode progress off stdout", async () => { const stdoutWrite = vi.spyOn(process.stdout, "write").mockImplementation(() => true); const stderrWrite = vi.spyOn(process.stderr, "write").mockImplementation(() => true);