feat(FN-4740): persist github tracking enabled state in dashboard

Adds persistence for the GitHub tracking enabled state with test coverage in the dashboard hook, and includes a changeset for the `@runfusion/fusion` package.

Fusion-Task-Id: FN-4740
This commit is contained in:
Fusion (runfusion.ai)
2026-05-16 09:30:28 -07:00
committed by gsxdsm
parent aa87799516
commit b1209b1859
3 changed files with 130 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
---
"@runfusion/fusion": patch
---
Persist GitHub tracking `enabled: true` on task records as soon as project/task settings resolve tracking to enabled, even when issue creation is deferred. This keeps API-created tasks aligned with default tracking state in dashboard UI and prevents redundant enabled-state rewrites.

View File

@@ -283,6 +283,124 @@ describe("registerGithubTrackingHook", () => {
);
});
it("persists enabled=true from project default when repo is missing", async () => {
registerGithubTrackingHook();
await store.updateSettings({
githubTrackingEnabledByDefault: true,
githubAuthMode: "token",
githubAuthToken: "tok",
});
const created = await store.createTask({
description: "default tracking without repo",
title: "Default tracking without repo",
});
const persisted = await store.getTask(created.id);
expect(persisted?.githubTracking?.enabled).toBe(true);
expect(mockCreateIssue).not.toHaveBeenCalled();
});
it("persists enabled=true from project default when no title is available", async () => {
registerGithubTrackingHook();
await store.updateSettings({
githubTrackingEnabledByDefault: true,
githubTrackingDefaultRepo: "owner/repo",
githubAuthMode: "token",
githubAuthToken: "tok",
titleSummarizerProvider: undefined,
titleSummarizerModelId: undefined,
titleSummarizerFallbackProvider: undefined,
titleSummarizerFallbackModelId: undefined,
});
const created = await store.createTask({
description: "```ts\nconst value = 1;\n```",
});
const persisted = await store.getTask(created.id);
expect(persisted?.githubTracking?.enabled).toBe(true);
expect(persisted?.githubTracking?.issue).toBeUndefined();
expect(mockCreateIssue).not.toHaveBeenCalled();
});
it("creates issue and keeps enabled=true when project default tracking is on", async () => {
registerGithubTrackingHook();
await store.updateSettings({
githubTrackingEnabledByDefault: true,
githubTrackingDefaultRepo: "owner/repo",
githubAuthMode: "token",
githubAuthToken: "tok",
});
const created = await store.createTask({
description: "default tracking with repo",
title: "Default tracking with repo",
});
const persisted = await store.getTask(created.id);
expect(mockCreateIssue).toHaveBeenCalledTimes(1);
expect(persisted?.githubTracking?.enabled).toBe(true);
expect(persisted?.githubTracking?.issue).toEqual(
expect.objectContaining({ owner: "owner", repo: "repo", number: 42 }),
);
});
it("keeps inline enabled=false without flipping back on", async () => {
registerGithubTrackingHook();
await store.updateSettings({
githubTrackingEnabledByDefault: true,
githubTrackingDefaultRepo: "owner/repo",
githubAuthMode: "token",
githubAuthToken: "tok",
});
const created = await store.createTask({
description: "tracking explicitly disabled",
title: "Tracking explicitly disabled",
githubTracking: { enabled: false },
});
const persisted = await store.getTask(created.id);
const enabledLogs = persisted?.log.filter((entry) => entry.action === "GitHub tracking enabled") ?? [];
expect(persisted?.githubTracking?.enabled).toBe(false);
expect(enabledLogs).toHaveLength(0);
expect(mockCreateIssue).not.toHaveBeenCalled();
});
it("avoids redundant enabled writes when inline enabled=true already set", async () => {
registerGithubTrackingHook();
await store.updateSettings({
githubTrackingEnabledByDefault: true,
githubAuthMode: "token",
githubAuthToken: "tok",
});
const created = await store.createTask({
description: "tracking already enabled",
title: "Tracking already enabled",
githubTracking: { enabled: true },
});
const afterHook = await store.getTask(created.id);
const enabledLogsBefore = afterHook?.log.filter((entry) => entry.action === "GitHub tracking enabled").length ?? 0;
await createTrackingIssueForTask(store, created);
const afterSecondPass = await store.getTask(created.id);
const enabledLogsAfter = afterSecondPass?.log.filter((entry) => entry.action === "GitHub tracking enabled").length ?? 0;
expect(enabledLogsBefore).toBe(0);
expect(enabledLogsAfter).toBe(0);
expect(mockCreateIssue).not.toHaveBeenCalled();
});
it("creates issue during createTask await when summarization is disabled", async () => {
registerGithubTrackingHook();

View File

@@ -209,6 +209,13 @@ export async function maybeCreateTrackingIssue(
return { created: false, reason: "issue_already_linked" };
}
if (tracking?.enabled !== true) {
latestTask = await deps.taskStore.updateGithubTracking(task.id, {
...(tracking ?? {}),
enabled: true,
});
}
const repo = resolvedTracking.repo;
if (!repo) {