[orchestrator-1.9-backport] fix(orchestrator): scope SchemaUpdater replacements#2732
Conversation
Limit SchemaUpdater replacements to the originating scope, with robust path resolution for nested and array schemas, plus tests covering scoping cases. Made-with: Cursor
Review Summary by QodoScope SchemaUpdater replacements to originating step
WalkthroughsDescription• Add optional scopeId parameter to SchemaUpdater for scoped updates • Implement scope resolution logic handling nested objects and arrays • Limit schema replacements to originating scope only • Add comprehensive test coverage for scoping scenarios Diagramflowchart LR
A["SchemaUpdater API"] -->|"add scopeId param"| B["OrchestratorFormSchemaUpdater"]
C["SchemaUpdater Widget"] -->|"pass props.id"| D["updateSchema call"]
E["Scope Resolution"] -->|"parse scopeId"| F["getScopePathFromId"]
F -->|"resolve path"| G["getScopedProperties"]
G -->|"limit updates"| H["deepSearchAndFirstReplace"]
H -->|"scoped chunks"| I["Updated Schema"]
File Changes1. workspaces/orchestrator/plugins/orchestrator-form-api/src/api.ts
|
Code Review by Qodo
|
|
| const scopePath = getScopePathFromId(schema, scopeId); | ||
| if (!scopePath || scopePath.length === 0) { | ||
| if (scopeId) { | ||
| // eslint-disable-next-line no-console | ||
| console.warn( | ||
| `SchemaUpdater: Failed to resolve scopeId "${scopeId}", falling back to root`, | ||
| ); | ||
| } | ||
| return schema.properties; | ||
| } | ||
|
|
||
| // Scope to the parent object of the SchemaUpdater field | ||
| const parentScope = scopePath.slice(0, -1); | ||
| if (parentScope.length === 0) { | ||
| return schema.properties; | ||
| } | ||
|
|
||
| let current: JSONSchema7 | undefined = schema; | ||
| for (const key of parentScope) { | ||
| if ( | ||
| current?.type === 'array' && | ||
| current.items && | ||
| typeof current.items === 'object' | ||
| ) { | ||
| current = current.items as JSONSchema7; | ||
| } | ||
|
|
||
| const properties = current?.properties; | ||
| if (!properties || typeof properties !== 'object') { | ||
| return undefined; | ||
| } | ||
|
|
||
| const next = properties[key]; | ||
| if (!next || typeof next !== 'object') { | ||
| return undefined; | ||
| } | ||
| current = next as JSONSchema7; | ||
| } | ||
|
|
||
| if ( | ||
| current?.type === 'array' && | ||
| current.items && | ||
| typeof current.items === 'object' | ||
| ) { | ||
| return (current.items as JSONSchema7).properties; | ||
| } | ||
|
|
||
| return current?.properties; | ||
| }; | ||
|
|
||
| // Stops searching and replacing after first hit | ||
| const deepSearchAndFirstReplace = ( | ||
| schemaProperties: JSONSchema7['properties'], |
There was a problem hiding this comment.
1. Scope failure updates root 🐞 Bug ≡ Correctness
When scopeId cannot be resolved, getScopedProperties() falls back to schema.properties (root), so getSchemaUpdater() still applies replacements globally even though a scopeId was provided, potentially modifying other steps/branches of the form schema.
Agent Prompt
### Issue description
When a `scopeId` is provided but can’t be resolved, the code falls back to the schema root and performs replacements globally. This can reintroduce cross-step/incorrect updates.
### Issue Context
This PR’s goal is to scope SchemaUpdater replacements; falling back to root when a scopeId is present undermines that goal.
### Fix Focus Areas
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/schemaUpdater.ts[91-147]
- workspaces/orchestrator/plugins/orchestrator/src/components/ExecuteWorkflowPage/schemaUpdater.ts[181-201]
### Suggested change
- If `scopeId` is provided and `getScopePathFromId()` (or `getScopedProperties()`) returns `undefined`/empty, **do not** apply updates (return early) instead of falling back to root.
- Keep the current root behavior only when `scopeId` is not provided (backward-compatible).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
lokanandaprabhu
left a comment
There was a problem hiding this comment.
Tested locally and it is working fine
/lgtm
Screen.Recording.2026-04-09.at.11.56.51.AM.mov
3281e3c
into
redhat-developer:orchestrator-1.9-backport
* [orchestrator] Backport orchestrator fixes and enhancements to 1.9 (#2666) * feat(orchestrator): pre-populate Execute Workflow form from URL query params (#2570) * prepopulate workflow execution page form from URL query params Signed-off-by: Karthik <karthik.jk11@gmail.com> * support enum coercison for case-insenstive match and skip invalid values * add support for fields that are defined via '$ref' * add full support for json schema fields --------- Signed-off-by: Karthik <karthik.jk11@gmail.com> * fix(orchestrator-form-react): scope async validation to active step (#2602) * fix(orchestrator-form-react): scope async validation to active step Limit validate:url requests to the active step during multi-step navigation. Made-with: Cursor * fix(orchestrator-form-react): keep full formData for async validation Pass full formData to template evaluation while scoping uiSchema traversal. Made-with: Cursor * fix(orchestrator-form-react): preserve ui:hidden on objects with properties (#2653) * fix(orchestrator): honor json schema defaults in initial formData (#2654) * fix(orchestrator): honor json schema defaults Ensure extractStaticDefaults falls back to JSON Schema defaults when ui:props fetch:response:default is absent so initial formData includes schema defaults. Made-with: Cursor * chore(changeset): document schema default fix Add changeset for orchestrator form defaults update. Made-with: Cursor * fix(orchestrator): handle root defaults Avoid setting an empty key for root schema defaults and add tests to cover root default handling. Made-with: Cursor * fix(orchestrator): document and test defaults Clarify extractStaticDefaults precedence in docs and add test coverage for default handling. Made-with: Cursor * chore(orchestrator): update yarn.lock after backport Made-with: Cursor --------- Signed-off-by: Karthik <karthik.jk11@gmail.com> Co-authored-by: Karthik Jeeyar <karthik@redhat.com> * fix(orchestrator): scope SchemaUpdater replacements (#2732) Limit SchemaUpdater replacements to the originating scope, with robust path resolution for nested and array schemas, plus tests covering scoping cases. Made-with: Cursor Co-authored-by: Lokananda Prabhu <lprabhu@redhat.com> --------- Signed-off-by: Karthik <karthik.jk11@gmail.com> Co-authored-by: Karthik Jeeyar <karthik@redhat.com> Co-authored-by: OpenShift Cherrypick Robot <openshift-cherrypick-robot@redhat.com>



This is an automated cherry-pick of #2725
/assign lokanandaprabhu