fix(qa): clean failed Parallels package locks

This commit is contained in:
Vincent Koc 2026-06-20 19:20:11 +02:00
parent dafd98dd98
commit 85f552bf37
No known key found for this signature in database
2 changed files with 28 additions and 2 deletions

View file

@ -194,18 +194,27 @@ async function withPackageLock<T>(lockDir: string, fn: () => Promise<T>): Promis
}
}
async function acquirePackageLock(lockDir: string, ownerToken: string): Promise<void> {
async function acquirePackageLock(
lockDir: string,
ownerToken: string,
params: { writeOwner?: (lockDir: string, ownerToken: string) => Promise<void> } = {},
): Promise<void> {
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<void> {
}
export const testing = {
acquirePackageLock,
removeStalePackageLock,
readLockOwner,
};

View file

@ -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);