fix(FN-4526): finalize stale merge stats repairs and changeset
Fusion-Task-Id: FN-4526 Fusion-Task-Lineage: 38dc93d6-3e56-4e22-aaaa-d09b2eed43e5
This commit is contained in:
5
.changeset/fn-4526-recompute-merge-stats-after-push.md
Normal file
5
.changeset/fn-4526-recompute-merge-stats-after-push.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix stale "files changed / insertions / deletions" on done tasks when `pushAfterMerge` is enabled. After `pushToRemoteAfterMerge` rebases HEAD, the merger now re-reads `git show --shortstat <postPushSha>` and rewrites `mergeDetails.filesChanged/insertions/deletions` alongside the refreshed `commitSha` (previously only the SHA was updated, leaving pre-rebase squash stats attached to the post-rebase commit). The `recoverDoneTaskMergeMetadata` self-healing pass also now detects and repairs stored stats that disagree with the live commit at the stored SHA, both at startup and during periodic maintenance.
|
||||||
@@ -110,7 +110,7 @@ describeIfGit("SelfHealingManager recoverDoneTaskMergeMetadata stale stats", ()
|
|||||||
it("does not rewrite when stats are already correct", async () => {
|
it("does not rewrite when stats are already correct", async () => {
|
||||||
const { repo, sha } = setupRepo();
|
const { repo, sha } = setupRepo();
|
||||||
const expected = parseShortstat(git(repo, `git show --shortstat --format= ${sha}`));
|
const expected = parseShortstat(git(repo, `git show --shortstat --format= ${sha}`));
|
||||||
const task = makeTask("FN-4526-OK", repo, sha, expected);
|
const task = makeTask("FN-4526-STATS", repo, sha, expected);
|
||||||
const tasks = new Map([[task.id, task]]);
|
const tasks = new Map([[task.id, task]]);
|
||||||
const store = createStore(tasks);
|
const store = createStore(tasks);
|
||||||
const manager = new SelfHealingManager(store, { rootDir: repo, getExecutingTaskIds: () => new Set() });
|
const manager = new SelfHealingManager(store, { rootDir: repo, getExecutingTaskIds: () => new Set() });
|
||||||
@@ -119,4 +119,22 @@ describeIfGit("SelfHealingManager recoverDoneTaskMergeMetadata stale stats", ()
|
|||||||
|
|
||||||
expect((store.updateTask as any).mock.calls).toHaveLength(0);
|
expect((store.updateTask as any).mock.calls).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("repairs stale stats in unconfirmed branch when SHA matches landed commit", async () => {
|
||||||
|
const { repo, sha } = setupRepo();
|
||||||
|
const expected = parseShortstat(git(repo, `git show --shortstat --format= ${sha}`));
|
||||||
|
const task = makeTask("FN-4526-STATS", repo, sha, { filesChanged: 777, insertions: 888, deletions: 999, mergeConfirmed: false });
|
||||||
|
const tasks = new Map([[task.id, task]]);
|
||||||
|
const store = createStore(tasks);
|
||||||
|
const manager = new SelfHealingManager(store, { rootDir: repo, getExecutingTaskIds: () => new Set() });
|
||||||
|
|
||||||
|
await manager.recoverDoneTaskMergeMetadata();
|
||||||
|
|
||||||
|
const repaired = tasks.get(task.id)!;
|
||||||
|
expect(repaired.mergeDetails?.commitSha).toBe(sha);
|
||||||
|
expect(repaired.mergeDetails?.filesChanged).toBe(expected.filesChanged);
|
||||||
|
expect(repaired.mergeDetails?.insertions).toBe(expected.insertions);
|
||||||
|
expect(repaired.mergeDetails?.deletions).toBe(expected.deletions);
|
||||||
|
expect(repaired.mergeDetails?.mergeConfirmed).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2550,7 +2550,12 @@ export class SelfHealingManager {
|
|||||||
cwd: this.options.rootDir,
|
cwd: this.options.rootDir,
|
||||||
maxBuffer: 1024 * 1024,
|
maxBuffer: 1024 * 1024,
|
||||||
});
|
});
|
||||||
return parseShortstat(stats.stdout);
|
const parsed = parseShortstat(stats.stdout);
|
||||||
|
return {
|
||||||
|
filesChanged: parsed.filesChanged ?? 0,
|
||||||
|
insertions: parsed.insertions ?? 0,
|
||||||
|
deletions: parsed.deletions ?? 0,
|
||||||
|
};
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -2630,15 +2635,21 @@ export class SelfHealingManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const landedStats = {
|
||||||
|
filesChanged: landed.filesChanged ?? 0,
|
||||||
|
insertions: landed.insertions ?? 0,
|
||||||
|
deletions: landed.deletions ?? 0,
|
||||||
|
};
|
||||||
|
|
||||||
const needsRepair =
|
const needsRepair =
|
||||||
task.mergeDetails?.commitSha !== landed.sha ||
|
task.mergeDetails?.commitSha !== landed.sha ||
|
||||||
task.mergeDetails?.filesChanged === undefined ||
|
task.mergeDetails?.filesChanged === undefined ||
|
||||||
task.mergeDetails?.insertions === undefined ||
|
task.mergeDetails?.insertions === undefined ||
|
||||||
task.mergeDetails?.deletions === undefined || (
|
task.mergeDetails?.deletions === undefined || (
|
||||||
task.mergeDetails?.commitSha === landed.sha && (
|
task.mergeDetails?.commitSha === landed.sha && (
|
||||||
task.mergeDetails?.filesChanged !== landed.filesChanged ||
|
task.mergeDetails?.filesChanged !== landedStats.filesChanged ||
|
||||||
task.mergeDetails?.insertions !== landed.insertions ||
|
task.mergeDetails?.insertions !== landedStats.insertions ||
|
||||||
task.mergeDetails?.deletions !== landed.deletions
|
task.mergeDetails?.deletions !== landedStats.deletions
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2648,9 +2659,9 @@ export class SelfHealingManager {
|
|||||||
mergeDetails: {
|
mergeDetails: {
|
||||||
...task.mergeDetails,
|
...task.mergeDetails,
|
||||||
commitSha: landed.sha,
|
commitSha: landed.sha,
|
||||||
filesChanged: landed.filesChanged,
|
filesChanged: landedStats.filesChanged,
|
||||||
insertions: landed.insertions,
|
insertions: landedStats.insertions,
|
||||||
deletions: landed.deletions,
|
deletions: landedStats.deletions,
|
||||||
mergeCommitMessage: landed.subject,
|
mergeCommitMessage: landed.subject,
|
||||||
mergedAt: task.mergeDetails?.mergedAt ?? new Date().toISOString(),
|
mergedAt: task.mergeDetails?.mergedAt ?? new Date().toISOString(),
|
||||||
mergeConfirmed: true,
|
mergeConfirmed: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user