FN-5782: wire branch groups into merge routing
Connect branch_group metadata through planning and merge execution for grouped integration branches. - propagate `branchGroup` and `branchGroupName` through core store types, merge metadata, and CLI task lifecycle APIs - add merge coordination that computes branch-group plans and routes grouped tasks via `group-merge-coordinator` - extend finalize-plan, merger, and reliability tests to cover grouped merge routing and integration behavior - document the architecture update and add a patch changeset for `@runfusion/fusion` Files changed: .changeset/fn-5782-branch-group-merge.md | 7 + docs/architecture.md | 2 + packages/cli/src/commands/__tests__/task-lifecycle.test.ts | 64 ++++++++- packages/cli/src/commands/task-lifecycle.ts | 4 + packages/core/src/__tests__/branch-group-store.test.ts | 20 +++ packages/core/src/__tests__/task-merge.test.ts | 64 +++++++++ packages/core/src/store.ts | 22 ++- packages/core/src/task-merge.ts | 26 +++- packages/core/src/types.ts | 2 +- packages/engine/src/__tests__/experiment-finalize-plan.test.ts | 33 ++++- packages/engine/src/__tests__/group-merge-coordinator.test.ts | 62 +++++++++ packages/engine/src/__tests__/reliability-interactions/branch-group-merge-routing.test.ts | 153 +++++++++++++++++++++ packages/engine/src/experiment/finalize-plan.ts | 62 +++++++-- packages/engine/src/group-merge-coordinator.ts | 51 +++++++ packages/engine/src/index.ts | 4 + packages/engine/src/merger.ts | 47 ++++++- 16 files changed, 601 insertions(+), 22 deletions(-) Fusion-Task-Id: FN-5782 Fusion-Task-Lineage: 0a70cfaa-2379-4955-b295-64de1f3093c8
This commit is contained in:
@@ -67,6 +67,7 @@ function makeStore(task: MockTask, settings: Record<string, unknown> = {}) {
|
||||
moveTask: vi.fn(async (_id: string, column: string) => ({ ...task, column })),
|
||||
logEntry: vi.fn().mockResolvedValue(undefined),
|
||||
getActiveMergingTask: vi.fn().mockReturnValue(null),
|
||||
getBranchGroup: vi.fn().mockReturnValue(null),
|
||||
_updates: updates,
|
||||
});
|
||||
}
|
||||
@@ -90,6 +91,7 @@ function makeStatefulStore(task: MockTask, settings: Record<string, unknown> = {
|
||||
}),
|
||||
logEntry: vi.fn().mockResolvedValue(undefined),
|
||||
getActiveMergingTask: vi.fn().mockReturnValue(null),
|
||||
getBranchGroup: vi.fn().mockReturnValue(null),
|
||||
_getState: () => state,
|
||||
});
|
||||
}
|
||||
@@ -175,6 +177,17 @@ describe("processPullRequestMergeTask", () => {
|
||||
};
|
||||
const branch = getTaskBranchName(task.id);
|
||||
const store = makeStore(task, { baseBranch: "main" });
|
||||
(store.getBranchGroup as ReturnType<typeof vi.fn>).mockReturnValue({
|
||||
id: "BG-1",
|
||||
sourceType: "planning",
|
||||
sourceId: "planning:abc",
|
||||
branchName: "fusion/groups/planning-abc",
|
||||
autoMerge: false,
|
||||
prState: "none",
|
||||
status: "open",
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
execMock.mockImplementation(() => "");
|
||||
|
||||
const github = {
|
||||
@@ -184,7 +197,7 @@ describe("processPullRequestMergeTask", () => {
|
||||
url: "https://github.com/x/y/pull/7",
|
||||
status: "open" as const,
|
||||
headBranch: branch,
|
||||
baseBranch: "develop",
|
||||
baseBranch: "fusion/groups/planning-abc",
|
||||
})),
|
||||
getPrMergeStatus: vi.fn(async () => ({
|
||||
prInfo: { number: 7, status: "open" as const, url: "https://github.com/x/y/pull/7" },
|
||||
@@ -205,7 +218,54 @@ describe("processPullRequestMergeTask", () => {
|
||||
);
|
||||
|
||||
expect(github.createPr).toHaveBeenCalledWith(expect.objectContaining({
|
||||
base: "develop",
|
||||
base: "fusion/groups/planning-abc",
|
||||
}));
|
||||
});
|
||||
|
||||
it("keeps per-task-derived members on the project default PR base", async () => {
|
||||
const task: MockTask = {
|
||||
id: "FN-9002",
|
||||
title: "test",
|
||||
description: "desc",
|
||||
column: "in-review",
|
||||
branchContext: {
|
||||
groupId: "planning:abc",
|
||||
source: "planning",
|
||||
assignmentMode: "per-task-derived",
|
||||
},
|
||||
};
|
||||
const store = makeStore(task, { baseBranch: "main" });
|
||||
execMock.mockImplementation(() => "");
|
||||
|
||||
const github = {
|
||||
findPrForBranch: vi.fn(async () => null),
|
||||
createPr: vi.fn(async () => ({
|
||||
number: 7,
|
||||
url: "https://github.com/x/y/pull/7",
|
||||
status: "open" as const,
|
||||
headBranch: getTaskBranchName(task.id),
|
||||
baseBranch: "main",
|
||||
})),
|
||||
getPrMergeStatus: vi.fn(async () => ({
|
||||
prInfo: { number: 7, status: "open" as const, url: "https://github.com/x/y/pull/7" },
|
||||
reviewDecision: null,
|
||||
checks: [],
|
||||
mergeReady: false,
|
||||
blockingReasons: [],
|
||||
})),
|
||||
mergePr: vi.fn(),
|
||||
};
|
||||
|
||||
await processPullRequestMergeTask(
|
||||
store as never,
|
||||
"/repo",
|
||||
task.id,
|
||||
github as never,
|
||||
() => undefined,
|
||||
);
|
||||
|
||||
expect(github.createPr).toHaveBeenCalledWith(expect.objectContaining({
|
||||
base: "main",
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user