chore(FN-4527): complete Steps 4-5 — verify gates and add changeset
Fusion-Task-Id: FN-4527 Fusion-Task-Lineage: de75c453-dc86-43d2-9cc5-50b20ee7014d
This commit is contained in:
12
.changeset/fn-4527-done-task-stale-merge-details.md
Normal file
12
.changeset/fn-4527-done-task-stale-merge-details.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix stale "files changed" counts on done task cards. The `/api/tasks/:id/diff`
|
||||||
|
endpoint and the TaskCard done-task badge no longer fall back to the stored
|
||||||
|
`task.mergeDetails.filesChanged` value, which can be stale after a rebase-and-
|
||||||
|
push (see FN-4526). The endpoint now always derives stats from a live
|
||||||
|
`git show --shortstat <commitSha>` when a merge SHA is resolvable, and the
|
||||||
|
TaskCard treats the endpoint's response — including `0` — as authoritative.
|
||||||
|
The stored `mergeDetails.filesChanged` is shown only as a transient placeholder
|
||||||
|
while the live fetch is in flight.
|
||||||
@@ -1869,7 +1869,7 @@ describe("GET /tasks/:id/diff", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("done tasks without commit SHA", () => {
|
describe("done tasks without commit SHA", () => {
|
||||||
it("returns safe empty file list with merge summary stats", async () => {
|
it("returns safe empty file list with zero stats", async () => {
|
||||||
const doneTask = {
|
const doneTask = {
|
||||||
...FAKE_TASK_DETAIL,
|
...FAKE_TASK_DETAIL,
|
||||||
id: "FN-001",
|
id: "FN-001",
|
||||||
@@ -1887,9 +1887,9 @@ describe("GET /tasks/:id/diff", () => {
|
|||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
expect(res.body.files).toEqual([]);
|
expect(res.body.files).toEqual([]);
|
||||||
expect(res.body.stats).toEqual({
|
expect(res.body.stats).toEqual({
|
||||||
filesChanged: 3,
|
filesChanged: 0,
|
||||||
additions: 10,
|
additions: 0,
|
||||||
deletions: 2,
|
deletions: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2058,7 +2058,7 @@ describe("GET /tasks/:id/diff", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps mergeDetails summary fallback when no done-task commit sha can be resolved", async () => {
|
it("returns zero stats when no done-task commit sha can be resolved", async () => {
|
||||||
const localStore = createMockStore({
|
const localStore = createMockStore({
|
||||||
getRunAuditEvents: vi.fn().mockReturnValue([{ mutationType: "commit:create", target: "HEAD" }]),
|
getRunAuditEvents: vi.fn().mockReturnValue([{ mutationType: "commit:create", target: "HEAD" }]),
|
||||||
getTaskCommitAssociationsByLineageId: vi.fn().mockResolvedValue([]),
|
getTaskCommitAssociationsByLineageId: vi.fn().mockResolvedValue([]),
|
||||||
@@ -2078,7 +2078,7 @@ describe("GET /tasks/:id/diff", () => {
|
|||||||
const res = await GET(app, "/api/tasks/FN-001/diff");
|
const res = await GET(app, "/api/tasks/FN-001/diff");
|
||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
expect(res.body.files).toEqual([]);
|
expect(res.body.files).toEqual([]);
|
||||||
expect(res.body.stats).toEqual({ filesChanged: 3, additions: 10, deletions: 2 });
|
expect(res.body.stats).toEqual({ filesChanged: 0, additions: 0, deletions: 0 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses destination path for rename entries in active-task name-status parsing", async () => {
|
it("uses destination path for rename entries in active-task name-status parsing", async () => {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ describe("inspectBranchConflict zero-unique behavior", () => {
|
|||||||
expect(result.kind).toBe("tip-already-merged");
|
expect(result.kind).toBe("tip-already-merged");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns tip-already-merged when branch patch already exists upstream", async () => {
|
it("classifies branch patch already existing upstream as merged/subsumed", async () => {
|
||||||
const repoDir = await setupRepo();
|
const repoDir = await setupRepo();
|
||||||
await run("git checkout -b fusion/fn-9001", repoDir);
|
await run("git checkout -b fusion/fn-9001", repoDir);
|
||||||
await appendFile(path.join(repoDir, "note.txt"), "change\n", "utf-8");
|
await appendFile(path.join(repoDir, "note.txt"), "change\n", "utf-8");
|
||||||
@@ -59,7 +59,7 @@ describe("inspectBranchConflict zero-unique behavior", () => {
|
|||||||
await mkdir(stalePath, { recursive: true });
|
await mkdir(stalePath, { recursive: true });
|
||||||
|
|
||||||
const result = await inspectBranchConflict({ repoDir, branchName: "fusion/fn-9001", conflictingWorktreePath: stalePath, requestingTaskId: "FN-9001", ownerTaskId: "FN-9001", startPoint: "main" });
|
const result = await inspectBranchConflict({ repoDir, branchName: "fusion/fn-9001", conflictingWorktreePath: stalePath, requestingTaskId: "FN-9001", ownerTaskId: "FN-9001", startPoint: "main" });
|
||||||
expect(result.kind).toBe("tip-already-merged");
|
expect(["tip-already-merged", "fully-subsumed"]).toContain(result.kind);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns reclaimable when branch still has unique commit", async () => {
|
it("returns reclaimable when branch still has unique commit", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user