Conversation
# Conflicts: # spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.py
📝 WalkthroughWalkthroughBackend: message model responses now include primary Changes
Sequence DiagramsequenceDiagram
participant User
participant Frontend as MessageEditor
participant API as Backend API
participant DB as Database
User->>Frontend: Open message editor
activate Frontend
Frontend->>API: GET /process-groups/{id}
Frontend->>API: GET /message-models/{id}
activate API
API->>DB: Query process group
API->>DB: Query message models (include id, location)
DB-->>API: Process group + message models
API-->>Frontend: Return process group + message models
deactivate API
Frontend->>Frontend: Build shared message options\nfindNearestAncestorLocation\nprefill form state
User->>Frontend: Select shared message option / edit form
Frontend->>Frontend: Merge correlation properties\nset schema / id / location as needed
User->>Frontend: Submit update
Frontend->>API: PATCH /process-groups/{id} (sanitized messages payload)
activate API
API->>API: _strip_message_model_metadata(payload)
API->>DB: Lookup MessageModel by (identifier, location)
DB-->>API: existing message (optional)
API->>DB: db.session.merge(message_model) -> flush -> obtain id
API->>DB: delete & recreate correlation properties for message_id
DB-->>API: commit/flush results
API-->>Frontend: Updated process group
deactivate API
deactivate Frontend
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
spiffworkflow-frontend/src/interfaces.ts (1)
245-247: Sync the fetched message-model type too.These new fields update the saved message definition shape, but
MessageModellater in this file still omitsid. That leaves the/message-modelsresponse under-typed even though this PR now depends on that field.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spiffworkflow-frontend/src/interfaces.ts` around lines 245 - 247, The MessageModel type is missing the new fields added to MessageDefinition, causing the /message-models response to be under-typed; update the MessageModel interface to include the same optional properties (e.g., add id?: number and location?: string to the MessageModel declaration) so its shape matches MessageDefinition and the fetched response is correctly typed.spiffworkflow-frontend/src/components/messages/MessageEditor.tsx (1)
310-344: Consider adding cleanup to prevent state updates on unmounted components.The coordination pattern using closure variables works, but if the component unmounts before both API calls complete, the callbacks will attempt to update state on an unmounted component. While React handles this gracefully, adding an abort signal or mounted flag improves robustness.
♻️ Optional improvement with mounted flag
useEffect(() => { + let isMounted = true; const currentGroupLocation = unModifyProcessIdentifierForPathParam( modifiedProcessGroupIdentifier, ); // ... existing code ... const maybeFinalize = () => { - if (processGroupLoaded && messageModelsLoaded && processGroupResult) { + if (isMounted && processGroupLoaded && messageModelsLoaded && processGroupResult) { processResult(processGroupResult, messageModelsResult); } }; // ... API calls ... + + return () => { + isMounted = false; + }; }, [modifiedProcessGroupIdentifier, correlationProperties, messageId]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spiffworkflow-frontend/src/components/messages/MessageEditor.tsx` around lines 310 - 344, The component makes two HttpService.makeCallToBackend calls and uses closure vars (processGroupResult, messageModelsResult, processGroupLoaded, messageModelsLoaded, maybeFinalize) to update state when both return, but there’s no cleanup to prevent updates after unmount; modify the surrounding useEffect to create a mounted flag (or an AbortController) and in each successCallback/failureCallback check the flag (or abort signal) before assigning to processGroupResult/messageModelsResult, setting the loaded flags, and calling maybeFinalize, and return a cleanup function that sets mounted=false (or calls abort()) so callbacks won’t update state on an unmounted component.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@spiffworkflow-backend/src/spiffworkflow_backend/services/message_definition_service.py`:
- Around line 18-29: The code currently trusts a caller-supplied message_id and
assigns it to message_model.id which can overwrite an unrelated row; before
setting message_model.id (or before merge), query MessageModel by the numeric
message_id (e.g., MessageModel.query.get(message_id) or
filter_by(id=message_id)) and verify that if a record exists its identifier and
location match the current identifier and message_location; if they match, you
may reuse that id, if a record exists but identifier/location differ,
raise/abort (reject the payload) to avoid reusing someone else's PK, and if no
record exists allow using the supplied id; if caller did not supply an id fall
back to existing_model.id as before.
In `@spiffworkflow-frontend/src/components/messages/MessageHelper.tsx`:
- Around line 9-15: The filter for candidateLocations in MessageHelper.tsx fails
to treat the root (normalizedCandidate === '') as an ancestor; update the
predicate in the candidateLocations.filter (where normalizedCandidate is
derived) to explicitly accept an empty normalizedCandidate as matching any
descendant (e.g., add a check like normalizedCandidate === '' || ...), so that
normalizedCurrentLocation is considered a match when the candidate is root,
while keeping the existing equality and startsWith(`${normalizedCandidate}/`)
checks.
---
Nitpick comments:
In `@spiffworkflow-frontend/src/components/messages/MessageEditor.tsx`:
- Around line 310-344: The component makes two HttpService.makeCallToBackend
calls and uses closure vars (processGroupResult, messageModelsResult,
processGroupLoaded, messageModelsLoaded, maybeFinalize) to update state when
both return, but there’s no cleanup to prevent updates after unmount; modify the
surrounding useEffect to create a mounted flag (or an AbortController) and in
each successCallback/failureCallback check the flag (or abort signal) before
assigning to processGroupResult/messageModelsResult, setting the loaded flags,
and calling maybeFinalize, and return a cleanup function that sets mounted=false
(or calls abort()) so callbacks won’t update state on an unmounted component.
In `@spiffworkflow-frontend/src/interfaces.ts`:
- Around line 245-247: The MessageModel type is missing the new fields added to
MessageDefinition, causing the /message-models response to be under-typed;
update the MessageModel interface to include the same optional properties (e.g.,
add id?: number and location?: string to the MessageModel declaration) so its
shape matches MessageDefinition and the fetched response is correctly typed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: c4619d60-8b95-431e-b9e2-2a2f46e2819d
📒 Files selected for processing (10)
spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.pyspiffworkflow-backend/src/spiffworkflow_backend/routes/process_groups_controller.pyspiffworkflow-backend/src/spiffworkflow_backend/services/message_definition_service.pyspiffworkflow-backend/tests/spiffworkflow_backend/integration/test_messages.pyspiffworkflow-frontend/src/components/messages/MessageEditor.test.tsxspiffworkflow-frontend/src/components/messages/MessageEditor.tsxspiffworkflow-frontend/src/components/messages/MessageHelper.test.tsxspiffworkflow-frontend/src/components/messages/MessageHelper.tsxspiffworkflow-frontend/src/interfaces.tsspiffworkflow-frontend/src/locales/en_us/translation.json
spiffworkflow-backend/src/spiffworkflow_backend/services/message_definition_service.py
Show resolved
Hide resolved
| const matchingLocations = candidateLocations.filter((candidateLocation) => { | ||
| const normalizedCandidate = candidateLocation.replace(/(^\/+|\/+$)/g, ''); | ||
| return ( | ||
| normalizedCurrentLocation === normalizedCandidate || | ||
| normalizedCurrentLocation.startsWith(`${normalizedCandidate}/`) | ||
| ); | ||
| }); |
There was a problem hiding this comment.
Handle the root location as an ancestor.
When candidateLocation normalizes to '', Line 13 checks startsWith('/'), so a root-scoped shared message never matches descendant paths like order/residential. That diverges from the backend's “higher in the directory tree” lookup and will miss valid shared-message candidates.
Possible fix
const matchingLocations = candidateLocations.filter((candidateLocation) => {
const normalizedCandidate = candidateLocation.replace(/(^\/+|\/+$)/g, '');
return (
+ normalizedCandidate === '' ||
normalizedCurrentLocation === normalizedCandidate ||
normalizedCurrentLocation.startsWith(`${normalizedCandidate}/`)
);
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const matchingLocations = candidateLocations.filter((candidateLocation) => { | |
| const normalizedCandidate = candidateLocation.replace(/(^\/+|\/+$)/g, ''); | |
| return ( | |
| normalizedCurrentLocation === normalizedCandidate || | |
| normalizedCurrentLocation.startsWith(`${normalizedCandidate}/`) | |
| ); | |
| }); | |
| const matchingLocations = candidateLocations.filter((candidateLocation) => { | |
| const normalizedCandidate = candidateLocation.replace(/(^\/+|\/+$)/g, ''); | |
| return ( | |
| normalizedCandidate === '' || | |
| normalizedCurrentLocation === normalizedCandidate || | |
| normalizedCurrentLocation.startsWith(`${normalizedCandidate}/`) | |
| ); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@spiffworkflow-frontend/src/components/messages/MessageHelper.tsx` around
lines 9 - 15, The filter for candidateLocations in MessageHelper.tsx fails to
treat the root (normalizedCandidate === '') as an ancestor; update the predicate
in the candidateLocations.filter (where normalizedCandidate is derived) to
explicitly accept an empty normalizedCandidate as matching any descendant (e.g.,
add a check like normalizedCandidate === '' || ...), so that
normalizedCurrentLocation is considered a match when the candidate is root,
while keeping the existing equality and startsWith(`${normalizedCandidate}/`)
checks.
There was a problem hiding this comment.
@copilot fix if you can also run ./bin/run_pyl
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
There was a problem hiding this comment.
🧹 Nitpick comments (1)
spiffworkflow-frontend/Dockerfile (1)
45-45: Pin the NGINX base image by digest for reproducibility and supply-chain traceability.Line [45] uses a mutable tag (
nginx:1.29.7-alpine). Pin this image to its immutable digest for better supply-chain safety and build reproducibility:Suggested Dockerfile adjustment
-FROM nginx:1.29.7-alpine +FROM nginx:1.29.7-alpine@sha256:<resolved_digest>To find the exact digest, run:
docker manifest inspect nginx:1.29.7-alpine | jq '.[0].digest'🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spiffworkflow-frontend/Dockerfile` at line 45, Replace the mutable base image reference "FROM nginx:1.29.7-alpine" with its immutable digest form to ensure reproducible builds and better supply-chain traceability; obtain the exact digest by running `docker manifest inspect nginx:1.29.7-alpine | jq '.[0].digest'` (or the registry equivalent) and update the Dockerfile's FROM line to use "nginx@sha256:<digest>" instead of the tag.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@spiffworkflow-frontend/Dockerfile`:
- Line 45: Replace the mutable base image reference "FROM nginx:1.29.7-alpine"
with its immutable digest form to ensure reproducible builds and better
supply-chain traceability; obtain the exact digest by running `docker manifest
inspect nginx:1.29.7-alpine | jq '.[0].digest'` (or the registry equivalent) and
update the Dockerfile's FROM line to use "nginx@sha256:<digest>" instead of the
tag.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0598cbc7-bc6d-487e-a4be-b9bf0cfeae1b
⛔ Files ignored due to path filters (1)
spiffworkflow-backend/uv.lockis excluded by!**/*.lock
📒 Files selected for processing (2)
spiffworkflow-backend/pyproject.tomlspiffworkflow-frontend/Dockerfile
✅ Files skipped from review due to trivial changes (1)
- spiffworkflow-backend/pyproject.toml
|
@copilot Verify each finding against the current code and only fix it if needed. In |
Agent-Logs-Url: https://github.com/sartography/spiff-arena/sessions/8af82614-cd72-4fe4-b910-7dff33cda721 Co-authored-by: burnettk <18027+burnettk@users.noreply.github.com>
Fixed in 6f8eeb3. When |
Agent-Logs-Url: https://github.com/sartography/spiff-arena/sessions/c961d6bd-c5cb-48e5-96e0-a9508db4dac0 Co-authored-by: burnettk <18027+burnettk@users.noreply.github.com>
No description provided.