feat(FN-3868): add changeset for github tracking settings

Adds a changeset for the GitHub tracking settings feature (FN-3868), preparing it for the next release. The feature itself was implemented in earlier steps; this changeset marks it for publication to npm.

Fusion-Task-Id: FN-3868
This commit is contained in:
Fusion
2026-05-09 12:07:05 -07:00
committed by gsxdsm
parent a2a3f8ad08
commit 25dd8cbb34
9 changed files with 244 additions and 3 deletions

View File

@@ -1600,6 +1600,8 @@ export function SettingsModal({
...form,
worktreeInitCommand: form.worktreeInitCommand?.trim() || undefined,
taskPrefix: form.taskPrefix?.trim() || undefined,
githubTrackingDefaultRepo: form.githubTrackingDefaultRepo?.trim() || undefined,
githubAuthToken: form.githubAuthToken?.trim() || undefined,
overlapIgnorePaths: (form.overlapIgnorePaths ?? []).map((path) => path.trim()).filter((path) => path.length > 0),
experimentalFeatures: normalizeExperimentalFeaturesForSave(form.experimentalFeatures),
};
@@ -1988,6 +1990,20 @@ export function SettingsModal({
it hidden even before clicking.
</small>
</div>
<div className="form-group">
<label htmlFor="globalGithubTrackingDefaultRepo">Global default tracking repo</label>
<input
id="globalGithubTrackingDefaultRepo"
type="text"
className="input"
placeholder="owner/repo"
value={form.githubTrackingDefaultRepo ?? ""}
onChange={(e) =>
setForm((f) => ({ ...f, githubTrackingDefaultRepo: e.target.value || undefined }))
}
/>
<small>Projects inherit this value when they do not set a project default tracking repo.</small>
</div>
<CliBinaryPanel />
<div className="form-group">
<label htmlFor="persistAgentToolOutput" className="checkbox-label">
@@ -3563,6 +3579,61 @@ export function SettingsModal({
</details>
</div>
)}
<h4 className="settings-section-heading settings-section-heading--spaced">GitHub Issue Tracking</h4>
<div className="form-group">
<label htmlFor="githubTrackingEnabledByDefault" className="checkbox-label">
<input
id="githubTrackingEnabledByDefault"
type="checkbox"
checked={form.githubTrackingEnabledByDefault ?? false}
onChange={(e) =>
setForm((f) => ({ ...f, githubTrackingEnabledByDefault: e.target.checked }))
}
/>
Default GitHub tracking ON for new tasks
</label>
</div>
<div className="form-group">
<label htmlFor="projectGithubTrackingDefaultRepo">Project default tracking repo</label>
<input
id="projectGithubTrackingDefaultRepo"
type="text"
className="input"
placeholder="owner/repo"
value={form.githubTrackingDefaultRepo ?? ""}
onChange={(e) =>
setForm((f) => ({ ...f, githubTrackingDefaultRepo: e.target.value || undefined }))
}
/>
</div>
<div className="form-group">
<label htmlFor="githubAuthMode">GitHub auth mode</label>
<select
id="githubAuthMode"
className="select"
value={form.githubAuthMode ?? "gh-cli"}
onChange={(e) =>
setForm((f) => ({ ...f, githubAuthMode: e.target.value as "gh-cli" | "token" }))
}
>
<option value="gh-cli">GitHub CLI (gh auth)</option>
<option value="token">Personal access token</option>
</select>
</div>
{(form.githubAuthMode ?? "gh-cli") === "token" && (
<div className="form-group">
<label htmlFor="githubAuthToken">GitHub personal access token</label>
<input
id="githubAuthToken"
type="password"
className="input"
value={form.githubAuthToken ?? ""}
onChange={(e) =>
setForm((f) => ({ ...f, githubAuthToken: e.target.value || undefined }))
}
/>
</div>
)}
<div className="form-group">
<label htmlFor="includeTaskIdInCommit" className="checkbox-label">
<input

View File

@@ -530,6 +530,15 @@ describe("SettingsModal", () => {
expect(projectPayload.persistAgentToolOutput).toBeUndefined();
}
});
it("renders global default tracking repo control", async () => {
renderModal({ initialSection: "global-general" });
await waitForSettingsModalReady();
const input = screen.getByLabelText("Global default tracking repo") as HTMLInputElement;
expect(input.value).toBe("");
expect(screen.getByText(/Projects inherit this value when they do not set a project default tracking repo/i)).toBeInTheDocument();
});
});
describe("Project General", () => {
@@ -1855,6 +1864,35 @@ describe("SettingsModal", () => {
expect(payload.pushAfterMerge).toBe(true);
expect(payload.pushRemote).toBe("upstream main");
});
it("renders and saves github issue tracking controls", async () => {
renderModal({ initialSection: "merge" });
await waitForSettingsModalReady();
expect(screen.getByRole("heading", { name: "GitHub Issue Tracking" })).toBeInTheDocument();
expect(screen.getByRole("checkbox", { name: "Default GitHub tracking ON for new tasks" })).not.toBeChecked();
expect(screen.getByLabelText("Project default tracking repo")).toBeInTheDocument();
const authModeSelect = screen.getByLabelText("GitHub auth mode") as HTMLSelectElement;
expect(authModeSelect.value).toBe("gh-cli");
expect(screen.queryByLabelText("GitHub personal access token")).not.toBeInTheDocument();
await userEvent.click(screen.getByRole("checkbox", { name: "Default GitHub tracking ON for new tasks" }));
await userEvent.type(screen.getByLabelText("Project default tracking repo"), "octo/repo");
await userEvent.selectOptions(authModeSelect, "token");
await userEvent.type(screen.getByLabelText("GitHub personal access token"), "ghp_test_token");
await userEvent.click(screen.getByRole("button", { name: "Save" }));
await waitFor(() => {
expect(mockUpdateSettings).toHaveBeenCalled();
});
const payload = mockUpdateSettings.mock.calls[0][0] as Record<string, unknown>;
expect(payload.githubTrackingEnabledByDefault).toBe(true);
expect(payload.githubTrackingDefaultRepo).toBe("octo/repo");
expect(payload.githubAuthMode).toBe("token");
expect(payload.githubAuthToken).toBe("ghp_test_token");
});
});
describe("Experimental Features section", () => {