FN-5794: run worktree init for fresh merge workspaces
Run merge worktree initialization automatically when a merge workspace is newly created. - detect when integration worktree creation is fresh and invoke the configured init command - preserve existing behavior for already-initialized worktrees while improving setup reliability - add integration tests covering init command execution paths for merge worktree setup Files changed: .changeset/fn-5794-merge-worktree-init.md | 5 +++ .../__tests__/merger-integration-worktree.test.ts | 16 +++++++++ packages/engine/src/merger.ts | 39 +++++++++++++++++++++- 3 files changed, 59 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-5794 Fusion-Task-Lineage: f368099f-a179-466e-b994-2a503167112c
This commit is contained in:
5
.changeset/fn-5794-merge-worktree-init.md
Normal file
5
.changeset/fn-5794-merge-worktree-init.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
Run the configured `worktreeInitCommand` when the merger has to create a fresh merge worktree during reuse-worktree reacquisition. This bootstraps newly created merge workspaces before merge verification/workflow steps run, while leaving pooled/reused existing worktrees unchanged.
|
||||
@@ -1,4 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
import {
|
||||
createMockStore,
|
||||
@@ -222,6 +223,21 @@ describe("probeIntegrationWorktreeState", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("merger fresh reacquire init wiring", () => {
|
||||
it("wires fresh acquireTaskWorktree calls with init command execution", () => {
|
||||
const mergerSource = readFileSync(new URL("../merger.ts", import.meta.url), "utf-8");
|
||||
const freshAcquireBlock = mergerSource.match(/const acquisition = await acquireTaskWorktree\(\{[\s\S]*?\n\s*\}\);/);
|
||||
expect(freshAcquireBlock?.[0]).toContain("runInitCommand: true");
|
||||
expect(freshAcquireBlock?.[0]).toContain("runConfiguredCommand:");
|
||||
expect(freshAcquireBlock?.[0]).toContain("runConfiguredMergeWorktreeCommand");
|
||||
});
|
||||
|
||||
it("keeps direct-reuse shortcut on existing registrations", () => {
|
||||
const mergerSource = readFileSync(new URL("../merger.ts", import.meta.url), "utf-8");
|
||||
expect(mergerSource).toContain("Skip acquireTaskWorktree's");
|
||||
});
|
||||
});
|
||||
|
||||
describe("acquireReuseHandoff", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
@@ -7781,7 +7781,9 @@ export async function aiMergeTask(
|
||||
logger: mergerLog,
|
||||
audit,
|
||||
runContext: engineRunContext,
|
||||
runInitCommand: false,
|
||||
runInitCommand: true,
|
||||
runConfiguredCommand: async (command, cwd, timeoutMs, env) =>
|
||||
runConfiguredMergeWorktreeCommand(command, cwd, timeoutMs, env, audit),
|
||||
createWorktree: async (branch, path, _taskId, _startPoint, _allowSiblingBranchRename) => {
|
||||
await execAsync(`git worktree add -f ${quoteArg(path)} ${quoteArg(branch)}`, {
|
||||
cwd: projectRootDir,
|
||||
@@ -11929,6 +11931,41 @@ function getPostMergeScriptSandboxBackend(auditor?: RunAuditor): SandboxBackend
|
||||
return resolveSandboxBackend({ auditor });
|
||||
}
|
||||
|
||||
async function runConfiguredMergeWorktreeCommand(
|
||||
command: string,
|
||||
cwd: string,
|
||||
timeoutMs: number,
|
||||
extraEnv?: NodeJS.ProcessEnv,
|
||||
auditor?: RunAuditor,
|
||||
): Promise<{
|
||||
stdout?: string;
|
||||
stderr?: string;
|
||||
exitCode?: number | null;
|
||||
signal?: NodeJS.Signals | null;
|
||||
timedOut?: boolean;
|
||||
bufferExceeded?: boolean;
|
||||
spawnError?: Error;
|
||||
}> {
|
||||
const backend = getPostMergeScriptSandboxBackend(auditor);
|
||||
const result = await backend.run(command, {
|
||||
cwd,
|
||||
encoding: "utf-8",
|
||||
timeoutMs,
|
||||
maxBuffer: 10 * 1024 * 1024,
|
||||
...(extraEnv !== undefined && { env: extraEnv }),
|
||||
});
|
||||
|
||||
return {
|
||||
stdout: result.stdout,
|
||||
stderr: result.stderr,
|
||||
exitCode: result.exitCode,
|
||||
signal: result.signal,
|
||||
timedOut: result.timedOut,
|
||||
bufferExceeded: result.bufferExceeded,
|
||||
spawnError: result.spawnError,
|
||||
};
|
||||
}
|
||||
|
||||
/** Execute a script-mode post-merge workflow step in the provided execution directory. */
|
||||
async function executePostMergeScriptStep(
|
||||
store: TaskStore,
|
||||
|
||||
Reference in New Issue
Block a user