feat(FN-4742): complete Step 4 — migrate pool and self-healing removals
Fusion-Task-Id: FN-4742 Fusion-Task-Lineage: 59bca56e-c9d9-4066-9f5a-6d8ee252a100
This commit is contained in:
committed by
gsxdsm
parent
5104553cfc
commit
e2de8fed6d
@@ -113,7 +113,7 @@ describe("self-healing completion fan-out", () => {
|
||||
|
||||
const first = await mgr.reconcileCompletedTask("FN-B", { worktreeHint: "/wt/fn-b" });
|
||||
expect(first.worktreeRemoved).toBe(true);
|
||||
expect(execMock.mock.calls.some((c) => String(c[0]).includes("git worktree remove --force '/wt/fn-b'"))).toBe(true);
|
||||
expect(execMock.mock.calls.some((c) => String(c[0]).includes("git worktree remove --force") && String(c[0]).includes("/wt/fn-b"))).toBe(true);
|
||||
|
||||
existsSyncMock.mockReturnValue(false);
|
||||
execMock.mockImplementation((cmd: string, _opts: unknown, cb: (err: unknown, stdout: string, stderr: string) => void) => {
|
||||
@@ -122,7 +122,7 @@ describe("self-healing completion fan-out", () => {
|
||||
});
|
||||
const second = await mgr.reconcileCompletedTask("FN-B");
|
||||
expect(second.worktreeRemoved).toBe(false);
|
||||
const rmCalls = execMock.mock.calls.filter((c) => String(c[0]).includes("git worktree remove --force"));
|
||||
const rmCalls = execMock.mock.calls.filter((c) => String(c[0]).includes("git worktree remove --force") && String(c[0]).includes("/wt/fn-b"));
|
||||
expect(rmCalls).toHaveLength(1);
|
||||
});
|
||||
|
||||
@@ -138,7 +138,7 @@ describe("self-healing completion fan-out", () => {
|
||||
const mgr = new SelfHealingManager(store, { rootDir: "/repo" });
|
||||
vi.spyOn(mgr as any, "findWorktreePathForBranch").mockResolvedValue("/wt/fn-c");
|
||||
const out = await mgr.reconcileCompletedTask("FN-C");
|
||||
expect(execMock.mock.calls.some((c) => String(c[0]).includes("git worktree remove --force '/wt/fn-c'"))).toBe(true);
|
||||
expect(execMock.mock.calls.some((c) => String(c[0]).includes("git worktree remove --force") && String(c[0]).includes("/wt/fn-c"))).toBe(true);
|
||||
expect(out.branchRemoved).toBe(false);
|
||||
expect(execMock.mock.calls.some((c) => String(c[0]).includes("git branch -D"))).toBe(false);
|
||||
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining("skip deletion"));
|
||||
|
||||
@@ -55,6 +55,7 @@ vi.mock("../worktree-pool.js", () => ({
|
||||
cleanupOrphanedWorktrees: vi.fn().mockResolvedValue(0),
|
||||
scanOrphanedBranches: vi.fn().mockResolvedValue([]),
|
||||
isUsableTaskWorktree: vi.fn().mockResolvedValue(true),
|
||||
removeWorktree: vi.fn().mockResolvedValue(undefined),
|
||||
resolveWorktreeBackend: vi.fn(),
|
||||
}));
|
||||
|
||||
@@ -83,7 +84,7 @@ import { existsSync, readdirSync } from "node:fs";
|
||||
import { mkdtemp, readdir, readFile, rm } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { isUsableTaskWorktree, resolveWorktreeBackend, scanIdleWorktrees, scanOrphanedBranches } from "../worktree-pool.js";
|
||||
import { isUsableTaskWorktree, removeWorktree, resolveWorktreeBackend, scanIdleWorktrees, scanOrphanedBranches } from "../worktree-pool.js";
|
||||
import * as branchConflictModule from "../branch-conflicts.js";
|
||||
import { createLogger } from "../logger.js";
|
||||
import { NotificationService } from "../notification/notification-service.js";
|
||||
@@ -93,6 +94,7 @@ const mockedExecSync = vi.mocked(execSync);
|
||||
const mockedExistsSync = vi.mocked(existsSync);
|
||||
const mockedScanOrphanedBranches = vi.mocked(scanOrphanedBranches);
|
||||
const mockedIsUsableTaskWorktree = vi.mocked(isUsableTaskWorktree);
|
||||
const mockedRemoveWorktree = vi.mocked(removeWorktree);
|
||||
const mockedResolveWorktreeBackend = vi.mocked(resolveWorktreeBackend);
|
||||
const mockedScanIdleWorktrees = vi.mocked(scanIdleWorktrees);
|
||||
const mockedReaddirSync = vi.mocked(readdirSync);
|
||||
@@ -152,6 +154,7 @@ describe("SelfHealingManager", () => {
|
||||
vi.useFakeTimers({ shouldAdvanceTime: true });
|
||||
store = createMockStore();
|
||||
manager = new SelfHealingManager(store, { rootDir: "/tmp/test-project" });
|
||||
mockedRemoveWorktree.mockResolvedValue(undefined);
|
||||
mockedClassifyOwnedLandedEvidence.mockResolvedValue({ kind: "proven-no-op", baseRef: "main", ownDiffEmpty: true });
|
||||
});
|
||||
|
||||
@@ -1251,10 +1254,8 @@ describe("SelfHealingManager", () => {
|
||||
|
||||
mockedExistsSync.mockReset();
|
||||
mockedExistsSync.mockReturnValueOnce(true);
|
||||
mockedExecSync.mockReset();
|
||||
mockedExecSync.mockImplementationOnce(() => {
|
||||
throw new Error("cannot remove worktree");
|
||||
});
|
||||
mockedRemoveWorktree.mockReset();
|
||||
mockedRemoveWorktree.mockRejectedValueOnce(new Error("cannot remove worktree"));
|
||||
|
||||
await (manager as any).cleanupInterruptedMergeArtifacts(task);
|
||||
|
||||
@@ -1264,7 +1265,7 @@ describe("SelfHealingManager", () => {
|
||||
),
|
||||
);
|
||||
|
||||
mockedExecSync.mockClear();
|
||||
mockedRemoveWorktree.mockClear();
|
||||
mockedExistsSync.mockReset();
|
||||
});
|
||||
|
||||
@@ -3803,9 +3804,10 @@ describe("SelfHealingManager", () => {
|
||||
mergeDetails: expect.objectContaining({ commitSha: "abc12345", mergeConfirmed: true }),
|
||||
}));
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-dep", { blockedBy: null });
|
||||
expect(
|
||||
mockedExecSync.mock.calls.some((call) => String(call[0]).includes("git worktree remove '/tmp/wt' --force")),
|
||||
).toBe(true);
|
||||
expect(mockedRemoveWorktree).toHaveBeenCalledWith(expect.objectContaining({
|
||||
rootDir: "/tmp/test-project",
|
||||
worktreePath: "/tmp/wt",
|
||||
}));
|
||||
expect(getSelfHealingLogger().log).toHaveBeenCalledWith(expect.stringContaining("self-heal:deadlock-recovered"));
|
||||
|
||||
managerWithRecovery.stop();
|
||||
|
||||
Reference in New Issue
Block a user