Skip to content

ACM-33136 Review step when clicking yaml highlight button, if yaml doesn't exist nothing happens#6046

Merged
openshift-merge-bot[bot] merged 4 commits intostolostron:mainfrom
jeswanke:ACM-33136-Review-step-when-clicking-yaml-highlight-button-if-yaml-doesn-t-exist-nothing-happens
Apr 24, 2026
Merged

ACM-33136 Review step when clicking yaml highlight button, if yaml doesn't exist nothing happens#6046
openshift-merge-bot[bot] merged 4 commits intostolostron:mainfrom
jeswanke:ACM-33136-Review-step-when-clicking-yaml-highlight-button-if-yaml-doesn-t-exist-nothing-happens

Conversation

@jeswanke
Copy link
Copy Markdown
Contributor

@jeswanke jeswanke commented Apr 23, 2026

📝 Summary

  1. when clicking on an arrow, if the key didn't exist in the yaml yet, nothing happened
    NOW: it opens the form input instead of doing nothing

  2. Also in Argo wizard, if repo hadn't been set this wouldn't have an error and its edit button would have no effect

CleanShot 2026-04-24 at 12 05 18@2x
  1. also the edit button on this would have no effect:
CleanShot 2026-04-24 at 12 05 52@2x

Ticket Summary (Title):
ACM-33136 Review step when clicking yaml highlight button, if yaml doesn't exist nothing happens

Ticket Link:
https://redhat.atlassian.net/browse/ACM-33136

Type of Change:

  • 🐞 Bug Fix
  • ✨ Feature
  • 🔧 Refactor
  • 💸 Tech Debt
  • 🧪 Test-related
  • 📄 Docs

✅ Checklist

General

  • PR title follows the convention (e.g. ACM-12340 Fix bug with...)
  • Code builds and runs locally without errors
  • No console logs, commented-out code, or unnecessary files
  • All commits are meaningful and well-labeled
  • All new display strings are externalized for localization (English only)
  • (Nice to have) JSDoc comments added for new functions and interfaces

If Feature

  • UI/UX reviewed (if applicable)
  • All acceptance criteria met
  • Unit test coverage added or updated
  • Relevant documentation or comments included

If Bugfix

  • Root cause and fix summary are documented in the ticket (for future reference / errata)
  • Fix tested thoroughly and resolves the issue
  • Test(s) added to prevent regression

🗒️ Notes for Reviewers

Summary by CodeRabbit

  • New Features

    • Simplified label display in review steps for improved readability
    • Visual error indicators for array input fields
  • Improvements

    • Enhanced validation for YAML highlight navigation paths
    • Optimized editor decoration selection logic for smoother scrolling behavior

Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

This PR refactors input path serialization from inputValueToPathValue callbacks to inputValueToPathString functions, updates review step rendering with label normalization and error propagation context, enforces required stepId on array instance nodes, implements item-aware YAML highlight validation in navigation, and prioritizes YAML highlights in editor decorations.

Changes

Cohort / File(s) Summary
Input Path String Serialization
frontend/packages/react-form-wizard/src/inputs/Input.ts, frontend/packages/react-form-wizard/src/inputs/WizCustomWrapper.tsx, frontend/wizards/Argo/ArgoWizard.tsx, frontend/src/wizards/Argo/ArgoWizard.tsx
Replaces inputValueToPathValue with inputValueToPathString callback for deriving stable string-based path suffixes. Adds inputValueToPathString optional property to InputCommonProps and wires it into sync-policy form controls with helpers for formatting values into #["key=value"] strings.
Review Step Rendering & Context
frontend/packages/react-form-wizard/src/review/ReviewStep.tsx, frontend/packages/react-form-wizard/src/review/ReviewStepContexts.tsx, frontend/packages/react-form-wizard/src/review/utils.ts
Post-processes review tree roots with simplifyLabels for label normalization. Broadens label/toggleLabel prop types to ReactNode, adds enclosingArrayInputError context field for propagating parent errors, and introduces label-stripping utility that removes leading path segments before / in whitespace-delimited words.
Array Instance Step Tracking
frontend/packages/react-form-wizard/src/review/ReviewStepContexts.tsx, frontend/packages/react-form-wizard/src/review/utils.ts
Adds optional stepId?: string to InputReviewStepMeta.ARRAY_INSTANCE, makes stepId required in rendered WizardDomTreeNode.ARRAY_INSTANCE, and threads parentStepId into array instance nodes during review subtree construction.
Navigation & Highlight Validation
frontend/packages/react-form-wizard/src/review/ReviewStepNavigation.tsx
Implements item-aware validation for YAML highlight navigation by checking path ownership via yamlPathBelongsToItem, normalizing paths, aligning with resource kinds, and parsing array hash annotations. Extends step-id resolution so ARRAY_INSTANCE nodes return their own stepId explicitly.
Editor Decoration Prioritization
frontend/src/components/SyncEditor/decorate.ts
Changes scrollToChangeDecoration to prioritize syncEditorYamlHighlight decorations over insertedLineDecoration when determining which decoration to reveal.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly maps to the core change: validation logic preventing YAML highlight navigation when the target YAML path doesn't belong to the current item.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed PR description follows template structure with ticket link, type of change, and relevant checklist items marked; bug fix details explain the issue and fix scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…-33136-Review-step-when-clicking-yaml-highlight-button-if-yaml-doesn-t-exist-nothing-happens

Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (5)
frontend/src/wizards/Argo/ArgoWizard.tsx (1)

698-716: Helpers duplicated verbatim with frontend/packages/react-form-wizard/wizards/Argo/ArgoWizard.tsx (lines 742-759).

These two functions are byte-identical across both files and must drift in lock-step forever, which is a silent-drift hazard. Consider extracting to a shared module (e.g. under frontend/packages/react-form-wizard/src) and importing from both call sites.

Also, a minor robustness note on the fallback branch: for non-boolean/non-string value (e.g. undefined/null), it produces #["PruneLast=undefined"], which still matches the hash-bracket regex consumer. Not reachable via the current wiring (pathValueToInputValue always yields boolean/string), but worth a guard if this helper is reused elsewhere.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/wizards/Argo/ArgoWizard.tsx` around lines 698 - 716, Two helpers
inputValueToPathString and prunePropagationPolicyCheckboxToPathString are
duplicated verbatim and have a weak fallback for non-boolean/non-string values;
extract both functions into a single shared utility module and import them from
both ArgoWizard locations so they stay in sync, and update
prunePropagationPolicyCheckboxToPathString (and the fallback branch of
inputValueToPathString) to defensively handle null/undefined/other types (e.g.,
coerce to empty string or skip adding the key) to avoid producing
"#[\"PruneLast=undefined\"]" while keeping the existing boolean/string behavior
intact.
frontend/packages/react-form-wizard/src/inputs/Input.ts (1)

161-174: Suffix concatenation is correct; one subtle consequence worth noting.

registrationPath is used both as the review-registration path (line 180) and — in non-test/non-Cypress mode — as the DOM id (line 174). Since inputValueToPathString(value) is value-dependent, the id/registration key will change every time the user toggles the control (e.g. …syncOptions#["PruneLast=true"]…#["PruneLast=false"]). That causes the useLayoutEffect at line 176 to unregister the old id and register a new one on every value change, plus a bumpReviewDomTree().

For the handful of Argo sync-policy checkboxes this is fine, but if this pattern is reused for high-frequency inputs (e.g. text inputs using inputValueToPathString) it will churn the registry on every keystroke. Worth a brief comment near line 166 warning future callers to only use this for low-cardinality/toggled inputs, or consider decoupling the registration key from the value (keep id stable, store the value-derived suffix only inside the registered meta).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/packages/react-form-wizard/src/inputs/Input.ts` around lines 161 -
174, The current code appends inputValueToPathString(value) to registrationPath
which makes the DOM id (id) change on every value change and churn the registry
in useLayoutEffect; fix by decoupling the DOM id from the value-derived suffix:
keep buildReviewInputRegistrationPath and the value-derived suffix only for the
review registration key, but compute a stable id for the DOM (use
convertId(props) or strip the inputValueToPathString part when assigning id),
and add a brief comment by the buildReviewInputRegistrationPath/id assignment
explaining that inputValueToPathString should only be used for low-cardinality
toggles or for registration metadata to avoid frequent unregister/register
cycles (referencing buildReviewInputRegistrationPath, inputValueToPathString,
registrationPath, convertId, id, and the useLayoutEffect unregister/register
flow).
frontend/packages/react-form-wizard/src/review/ReviewStepNavigation.tsx (2)

125-147: Asymmetric kind handling for single vs. array item.

When item is an array, you explicitly find a resource whose kind === kindHead and bail if none. When item is a single object, you skip that check and rely on get-value returning undefined for a wrong-kind prefix. That works, but consider guarding symmetrically for clarity and to avoid false positives if the single item happens to have a property named the same as the path's kind segment:

🔧 Symmetric kind validation
   let target: unknown = item
   if (Array.isArray(item)) {
     target = item.find((res) => {
       if (!res || typeof res !== 'object') return false
       const rk = (res as { kind?: unknown }).kind
       return rk != null && String(rk) !== '' && String(rk) === kindHead
     })
     if (!target) return false
+  } else if (item && typeof item === 'object') {
+    const rk = (item as { kind?: unknown }).kind
+    if (rk != null && String(rk) !== '' && String(rk) !== kindHead) return false
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/packages/react-form-wizard/src/review/ReviewStepNavigation.tsx`
around lines 125 - 147, The function yamlPathBelongsToItem has asymmetric kind
handling: when item is an array you check for a resource whose kind matches
kindHead but when item is a single object you don't; add the same guard for
single objects by extracting kindHead (already computed as kindHead) and, before
calling yamlPathValueBelongsToTarget, verify that (item as { kind?: unknown
}).kind is non-null and String(kind) === kindHead — if it does not match return
false; place this check in the branch where target is an object (inside
yamlPathBelongsToItem) so single-object items are validated the same way as
array elements.

95-113: Path-escape round-trip relies on get-value's key-with-dot fallback.

normalized (from line 128) already replaced \. with ., so when basePath includes a YAML key that contains dots (e.g. annotations like app.kubernetes.io/name), the lookup depends on get-value's built-in rejoin-on-miss behavior to find the real key. That does work with the default joinChar: '.', but if the key separator in your objects is ever something other than . (e.g. after Monaco-side transformation), this will silently miss.

Also: m[1] at line 107 is typed string | undefined under noUncheckedIndexedAccess; add a guard or non-null assertion consistent with the rest of the file (e.g. m[1]!).

🔧 Minor guard for capture group
   if (pathWasAppended && Array.isArray(got)) {
-    const key = bracketAnnotationKey(m[1])
+    const key = bracketAnnotationKey(m[1] ?? '')
     if (key === '') return false
     return got.some((el) => typeof el === 'string' && arrayStringStartsWithKeyAtNonAlphanumericBoundary(el, key))
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/packages/react-form-wizard/src/review/ReviewStepNavigation.tsx`
around lines 95 - 113, The lookup currently relies on get-value's join-on-miss
behavior and also uses m[1] without a non-null guard; update
yamlPathValueBelongsToTarget to first try get(target, resourcePath) (preserving
any original key tokens) before falling back to get(target, basePath) so we
don't silently depend on get-value's dot-rejoin behavior, and change m[1] to a
non-null assertion (m[1]!) or add a guard consistent with the file; keep the
existing array-handling logic but reference m[1]! when computing the bracket
key.
frontend/packages/react-form-wizard/src/review/utils.ts (1)

149-174: simplifyLabelWordSlashes is a blanket transform — verify edge cases.

Concerns with applying this to every label in the review tree:

  1. A word ending in / collapses to an empty string ("foo/".slice(4) === ""), turning "foo/ bar" into " bar".
  2. Any user-authored label containing / (e.g. "CPU/Memory", "Read/Write") loses its prefix. The transform appears targeted at Kubernetes-style keys like app.kubernetes.io/name → name, but it runs on all labels unconditionally.
  3. A leading-slash word like "/path" becomes "path".

If the intent is specifically k8s-prefixed label keys, consider scoping (e.g. only when prefix matches a known domain pattern) or at minimum guarding against the empty-word case.

🔧 Optional guard for empty-tail words
 function simplifyLabelWordSlashes(label: string): string {
   return label.replace(/\S+/g, (word) => {
     const i = word.indexOf('/')
     if (i === -1) return word
-    return word.slice(i + 1)
+    const tail = word.slice(i + 1)
+    return tail === '' ? word : tail
   })
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/packages/react-form-wizard/src/review/utils.ts` around lines 149 -
174, simplifyLabelWordSlashes currently strips everything before the first '/'
on any whitespace-delimited word, which drops trailing-slash words and non-k8s
labels; update simplifyLabelWordSlashes to only strip when (1) a '/' exists, (2)
the suffix after the slash is non-empty, and (3) the prefix looks like a k8s
domain-style prefix (e.g. contains a '.' or matches known domains like
"kubernetes.io"); otherwise return the original word. Modify the function
referenced by simplifyLabels and simplifyLabelsInNode so empty-tail cases
preserve the original word and only k8s-like prefixes are removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/packages/react-form-wizard/src/inputs/Input.ts`:
- Around line 161-174: The current code appends inputValueToPathString(value) to
registrationPath which makes the DOM id (id) change on every value change and
churn the registry in useLayoutEffect; fix by decoupling the DOM id from the
value-derived suffix: keep buildReviewInputRegistrationPath and the
value-derived suffix only for the review registration key, but compute a stable
id for the DOM (use convertId(props) or strip the inputValueToPathString part
when assigning id), and add a brief comment by the
buildReviewInputRegistrationPath/id assignment explaining that
inputValueToPathString should only be used for low-cardinality toggles or for
registration metadata to avoid frequent unregister/register cycles (referencing
buildReviewInputRegistrationPath, inputValueToPathString, registrationPath,
convertId, id, and the useLayoutEffect unregister/register flow).

In `@frontend/packages/react-form-wizard/src/review/ReviewStepNavigation.tsx`:
- Around line 125-147: The function yamlPathBelongsToItem has asymmetric kind
handling: when item is an array you check for a resource whose kind matches
kindHead but when item is a single object you don't; add the same guard for
single objects by extracting kindHead (already computed as kindHead) and, before
calling yamlPathValueBelongsToTarget, verify that (item as { kind?: unknown
}).kind is non-null and String(kind) === kindHead — if it does not match return
false; place this check in the branch where target is an object (inside
yamlPathBelongsToItem) so single-object items are validated the same way as
array elements.
- Around line 95-113: The lookup currently relies on get-value's join-on-miss
behavior and also uses m[1] without a non-null guard; update
yamlPathValueBelongsToTarget to first try get(target, resourcePath) (preserving
any original key tokens) before falling back to get(target, basePath) so we
don't silently depend on get-value's dot-rejoin behavior, and change m[1] to a
non-null assertion (m[1]!) or add a guard consistent with the file; keep the
existing array-handling logic but reference m[1]! when computing the bracket
key.

In `@frontend/packages/react-form-wizard/src/review/utils.ts`:
- Around line 149-174: simplifyLabelWordSlashes currently strips everything
before the first '/' on any whitespace-delimited word, which drops
trailing-slash words and non-k8s labels; update simplifyLabelWordSlashes to only
strip when (1) a '/' exists, (2) the suffix after the slash is non-empty, and
(3) the prefix looks like a k8s domain-style prefix (e.g. contains a '.' or
matches known domains like "kubernetes.io"); otherwise return the original word.
Modify the function referenced by simplifyLabels and simplifyLabelsInNode so
empty-tail cases preserve the original word and only k8s-like prefixes are
removed.

In `@frontend/src/wizards/Argo/ArgoWizard.tsx`:
- Around line 698-716: Two helpers inputValueToPathString and
prunePropagationPolicyCheckboxToPathString are duplicated verbatim and have a
weak fallback for non-boolean/non-string values; extract both functions into a
single shared utility module and import them from both ArgoWizard locations so
they stay in sync, and update prunePropagationPolicyCheckboxToPathString (and
the fallback branch of inputValueToPathString) to defensively handle
null/undefined/other types (e.g., coerce to empty string or skip adding the key)
to avoid producing "#[\"PruneLast=undefined\"]" while keeping the existing
boolean/string behavior intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8cb23769-e991-4258-9dd4-82a1c86e9a6c

📥 Commits

Reviewing files that changed from the base of the PR and between e8547fd and 18a0b17.

📒 Files selected for processing (9)
  • frontend/packages/react-form-wizard/src/inputs/Input.ts
  • frontend/packages/react-form-wizard/src/inputs/WizCustomWrapper.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStep.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStepContexts.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStepNavigation.tsx
  • frontend/packages/react-form-wizard/src/review/utils.ts
  • frontend/packages/react-form-wizard/wizards/Argo/ArgoWizard.tsx
  • frontend/src/components/SyncEditor/decorate.ts
  • frontend/src/wizards/Argo/ArgoWizard.tsx
💤 Files with no reviewable changes (1)
  • frontend/packages/react-form-wizard/src/inputs/WizCustomWrapper.tsx

@jeswanke jeswanke requested a review from fxiang1 April 24, 2026 16:27
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented Apr 24, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: fxiang1, jeswanke

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot openshift-merge-bot Bot merged commit f4eb543 into stolostron:main Apr 24, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants