fix: invalidate PR diff cache on git refresh button click (#23974)

This commit is contained in:
Danielle Maywood
2026-04-02 14:39:04 +01:00
committed by GitHub
parent fce05d0428
commit 00217fefa5
2 changed files with 82 additions and 2 deletions
@@ -283,6 +283,70 @@ index abc1234..def5678 100644
},
};
/**
* Clicking the refresh button in the git panel invalidates the
* cached PR diff contents so that React Query re-fetches from
* the server.
*/
export const RefreshInvalidatesPRDiff: Story = {
render: () => (
<StoryAgentChatPageView
showSidebarPanel
prNumber={123}
diffStatusData={
{
chat_id: AGENT_ID,
url: "https://github.com/coder/coder/pull/123",
pull_request_title: "fix: resolve race condition in workspace builds",
pull_request_draft: false,
changes_requested: false,
additions: 42,
deletions: 7,
changed_files: 5,
} satisfies ChatDiffStatus
}
/>
),
beforeEach: () => {
spyOn(API.experimental, "getChatDiffContents").mockResolvedValue({
chat_id: AGENT_ID,
diff: `diff --git a/src/main.ts b/src/main.ts
index abc1234..def5678 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,3 +1,5 @@
import { start } from "./server";
+import { logger } from "./logger";
const port = 3000;
+logger.info("Starting server...");
start(port);`,
});
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
// Wait for the initial diff fetch triggered by React Query.
await waitFor(() => {
expect(API.experimental.getChatDiffContents).toHaveBeenCalled();
});
const callsBefore = (
API.experimental.getChatDiffContents as ReturnType<typeof fn>
).mock.calls.length;
// Click the refresh button in the git panel toolbar.
const refreshButton = canvas.getByRole("button", { name: "Refresh" });
await userEvent.click(refreshButton);
// The query should be re-fetched, resulting in an additional call.
await waitFor(() => {
expect(
(API.experimental.getChatDiffContents as ReturnType<typeof fn>).mock
.calls.length,
).toBeGreaterThan(callsBefore);
});
},
};
/** Left sidebar is collapsed. */
export const SidebarCollapsed: Story = {
render: () => <StoryAgentChatPageView isSidebarCollapsed />,
@@ -1,9 +1,10 @@
import { ArchiveIcon } from "lucide-react";
import { type FC, type RefObject, useRef, useState } from "react";
import { useQueryClient } from "react-query";
import type { UrlTransform } from "streamdown";
import { chatDiffContentsKey } from "#/api/queries/chats";
import type * as TypesGen from "#/api/typesGenerated";
import type { ChatDiffStatus, ChatMessagePart } from "#/api/typesGenerated";
import { cn } from "#/utils/cn";
import { pageTitle } from "#/utils/page";
import {
@@ -208,6 +209,21 @@ export const AgentChatPageView: FC<AgentChatPageViewProps> = ({
desktopChatId,
lastInjectedContext,
}) => {
const queryClient = useQueryClient();
// Wrap the git watcher refresh to also invalidate the cached
// remote/PR diff contents so the panel re-fetches from GitHub.
const handleRefresh = () => {
const sent = gitWatcher.refresh();
if (sent && agentId) {
void queryClient.invalidateQueries({
queryKey: chatDiffContentsKey(agentId),
exact: true,
});
}
return sent;
};
const [isRightPanelExpanded, setIsRightPanelExpanded] = useState(false);
const [dragVisualExpanded, setDragVisualExpanded] = useState<boolean | null>(
null,
@@ -389,7 +405,7 @@ export const AgentChatPageView: FC<AgentChatPageViewProps> = ({
: undefined
}
repositories={gitWatcher.repositories}
onRefresh={gitWatcher.refresh}
onRefresh={handleRefresh}
onCommit={handleCommit}
isExpanded={visualExpanded}
remoteDiffStats={diffStatusData}