From 608fb374139bc083137c31defd17b61b7aecd9a2 Mon Sep 17 00:00:00 2001 From: Ryan Westfall Date: Sun, 25 Oct 2026 06:20:00 -0700 Subject: [PATCH] Fix beta build: satisfy MessageContext hook deps (#140) ## Summary - Closes #139. - [Deploy Beta run 1025](https://git.aimloperations.com/ai_ml_operations/chat_web_app/actions/runs/1025/jobs/1743) failed `npm run build:beta` on `ai-server-4080` because `CI=true` turns `react-hooks/exhaustive-deps` warnings into errors. - `GetConversationDetails` is a `useCallback` and is listed on the post-stream refetch, the selected-conversation effect, and the reconnect effect. `setConversationDetails` stays stable, so those effects still run only when their real inputs change. - Adds a project rule to lint changed `llm-fe` files with warnings as errors before pushing a merge request. ## Test plan - [x] `CI=true ./node_modules/.bin/eslint --max-warnings 0 src/llm-fe/contexts/MessageContext.tsx` - [x] `MessageContext.test.tsx` and `MessageContext.order.test.tsx` (8 passed) - [ ] Deploy Beta `build:beta` succeeds on `ai-server-4080` after merge Reviewed-on: https://git.aimloperations.com/ai_ml_operations/chat_web_app/pulls/140 --- .cursor/rules/eslint-before-mr.mdc | 23 +++++++++++++++++++ llm-fe/src/llm-fe/contexts/MessageContext.tsx | 14 +++++------ 2 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 .cursor/rules/eslint-before-mr.mdc diff --git a/.cursor/rules/eslint-before-mr.mdc b/.cursor/rules/eslint-before-mr.mdc new file mode 100644 index 0000000..941e1b7 --- /dev/null +++ b/.cursor/rules/eslint-before-mr.mdc @@ -0,0 +1,23 @@ +--- +description: Run ESLint with warnings as errors before pushing a merge request +alwaysApply: true +--- + +# ESLint before push + +Beta deploy runs `npm run build:beta` with `CI=true`. Create React App turns ESLint warnings into build errors. Unit tests do not catch this. The failure shows up only on the deploy runner (`ai-server-4080`), where `CI=true` is set. + +Before `git push` or opening a pull request that changes `llm-fe`: + +1. From `llm-fe`, lint every changed file under `src` with warnings as errors: + +```bash +CI=true ./node_modules/.bin/eslint --max-warnings 0 path/to/ChangedFile.tsx +``` + +2. Fix every warning in those files. Do not push while that command exits non-zero. +3. Do not set `DISABLE_ESLINT_PLUGIN` or `CI=false` to get the deploy through. + +A full `eslint src` run reports warnings in files the production build does not compile. Those do not fail deploy. The gate is warnings in files the build compiles. + +`react-hooks/exhaustive-deps` is the usual failure. Wrap the function in `useCallback` and list it in the dependency array. An empty dependency array that calls a component function fails the beta build. diff --git a/llm-fe/src/llm-fe/contexts/MessageContext.tsx b/llm-fe/src/llm-fe/contexts/MessageContext.tsx index 8b27c47..e5cd896 100644 --- a/llm-fe/src/llm-fe/contexts/MessageContext.tsx +++ b/llm-fe/src/llm-fe/contexts/MessageContext.tsx @@ -95,7 +95,7 @@ const MessageProvider = ( {children}: MessageProviderProps) => { setActivityHistory([]) } - async function GetConversationDetails(conversationId: number | undefined) { + const GetConversationDetails = useCallback(async (conversationId: number | undefined) => { if (!conversationId) { setConversationDetails([]) return @@ -134,7 +134,7 @@ const MessageProvider = ( {children}: MessageProviderProps) => { } catch (err) { console.log('Failed to refetch conversation after reconnect', err) } - } + }, [setConversationDetails]) const schedulePostStreamRefetch = useCallback(() => { if (refetchTimerRef.current) clearTimeout(refetchTimerRef.current) @@ -145,11 +145,11 @@ const MessageProvider = ( {children}: MessageProviderProps) => { refetchTimerRef.current = setTimeout(() => { void GetConversationDetails(conversationId) }, 800) - }, []) + }, [GetConversationDetails]) useEffect(() => { - GetConversationDetails(selectedConversation) - }, [selectedConversation]) + void GetConversationDetails(selectedConversation) + }, [selectedConversation, GetConversationDetails]) useEffect(() => { return () => { @@ -198,9 +198,9 @@ const MessageProvider = ( {children}: MessageProviderProps) => { } if (selectedConversationRef.current) { - GetConversationDetails(selectedConversationRef.current) + void GetConversationDetails(selectedConversationRef.current) } - }, [reconnectGeneration]) + }, [reconnectGeneration, GetConversationDetails, setConversationDetails]) useEffect(() => { /* register a consistent channel name for identifing this chat messages */