feat(FN-4855): complete Step 1 — merge githubTracking patch updates

Fusion-Task-Id: FN-4855
Fusion-Task-Lineage: 47f093b7-dffc-4c1a-8dee-2fe01d0c9ed6
This commit is contained in:
Fusion (runfusion.ai)
2026-05-17 00:53:34 -07:00
committed by gsxdsm
parent 7a6a3d0d22
commit 5a584640d0
2 changed files with 130 additions and 1 deletions

View File

@@ -95,6 +95,83 @@ describe("TaskStore github tracking", () => {
});
});
it("disables tracking via updateTask by unlinking issue and preserving repoOverride", async () => {
const task = await store.createTask({ description: "Disable tracking patch" });
await store.updateGithubTracking(task.id, {
enabled: true,
repoOverride: "octocat/hello-world",
issue,
});
await store.updateTask(task.id, {
githubTracking: { enabled: false },
});
const updated = await store.getTask(task.id);
expect(updated?.githubTracking?.enabled).toBe(false);
expect(updated?.githubTracking?.issue).toBeUndefined();
expect(updated?.githubTracking?.repoOverride).toBe("octocat/hello-world");
expect(updated?.githubTracking?.unlinkedAt).toBeTruthy();
});
it("re-enables tracking via updateTask without dropping repoOverride", async () => {
const task = await store.createTask({ description: "Enable tracking patch" });
await store.updateGithubTracking(task.id, {
enabled: false,
repoOverride: "octocat/hello-world",
});
await store.updateTask(task.id, {
githubTracking: { enabled: true },
});
const updated = await store.getTask(task.id);
expect(updated?.githubTracking).toEqual({
enabled: true,
repoOverride: "octocat/hello-world",
});
});
it("updates repoOverride via updateTask without dropping enabled state or issue", async () => {
const task = await store.createTask({ description: "Repo override patch" });
await store.updateGithubTracking(task.id, {
enabled: true,
repoOverride: "octocat/hello-world",
issue,
});
await store.updateTask(task.id, {
githubTracking: { repoOverride: "runfusion/fusion" },
});
const updated = await store.getTask(task.id);
expect(updated?.githubTracking).toEqual({
enabled: true,
repoOverride: "runfusion/fusion",
issue,
});
});
it("clears githubTracking completely when updateTask receives null", async () => {
const task = await store.createTask({ description: "Clear tracking patch" });
await store.updateGithubTracking(task.id, {
enabled: true,
repoOverride: "octocat/hello-world",
issue,
});
await store.updateTask(task.id, {
githubTracking: null,
});
const updated = await store.getTask(task.id);
expect(updated?.githubTracking).toBeUndefined();
});
it("links and unlinks tracked issue while preserving other tracking fields", async () => {
const task = await store.createTask({ description: "Link issue" });

View File

@@ -4691,7 +4691,59 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
if (updates.githubTracking === null) {
task.githubTracking = undefined;
} else if (updates.githubTracking !== undefined) {
task.githubTracking = updates.githubTracking;
const previousTracking = task.githubTracking;
const previousIssue = previousTracking?.issue;
const nextTracking: import("./types.js").TaskGithubTracking = {
...(previousTracking ?? {}),
...updates.githubTracking,
};
if (updates.githubTracking.repoOverride === null) {
nextTracking.repoOverride = undefined;
}
if (updates.githubTracking.enabled === false) {
nextTracking.enabled = false;
if (previousIssue) {
nextTracking.issue = undefined;
nextTracking.unlinkedAt = new Date().toISOString();
task.log.push({
timestamp: new Date().toISOString(),
action: "GitHub issue unlinked",
outcome: `${previousIssue.owner}/${previousIssue.repo}#${previousIssue.number}`,
...(runContext ? { runContext } : {}),
});
}
task.log.push({
timestamp: new Date().toISOString(),
action: "GitHub tracking disabled",
...(runContext ? { runContext } : {}),
});
}
if (updates.githubTracking.enabled === true) {
nextTracking.enabled = true;
task.log.push({
timestamp: new Date().toISOString(),
action: "GitHub tracking enabled",
...(runContext ? { runContext } : {}),
});
}
if (updates.githubTracking.issue === null) {
if (previousIssue) {
task.log.push({
timestamp: new Date().toISOString(),
action: "GitHub issue unlinked",
outcome: `${previousIssue.owner}/${previousIssue.repo}#${previousIssue.number}`,
...(runContext ? { runContext } : {}),
});
}
nextTracking.issue = undefined;
nextTracking.unlinkedAt = new Date().toISOString();
}
task.githubTracking = nextTracking;
}
if (updates.tokenUsage === null) {
task.tokenUsage = undefined;