Skip to content

View in Argo CD action disabled (#10082)#254

Open
keithchong wants to merge 1 commit into
redhat-developer:mainfrom
keithchong:10082-ViewInArgoCD
Open

View in Argo CD action disabled (#10082)#254
keithchong wants to merge 1 commit into
redhat-developer:mainfrom
keithchong:10082-ViewInArgoCD

Conversation

@keithchong

Copy link
Copy Markdown
Collaborator

Signed-off-by: Keith Chong <kykchong@redhat.com>
@openshift-ci openshift-ci Bot requested a review from wtam2018 July 4, 2026 04:20
@keithchong keithchong requested review from aali309 and removed request for wtam2018 July 4, 2026 04:20
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Improved “View in Argo CD” and related application links across GitOps screens.
    • Application pages now build links consistently from the selected application’s details.
  • Bug Fixes

    • Fixed link generation for application, resource, sync status, history, and graph views.
    • Action buttons now only appear when a valid destination is available, avoiding disabled empty links.

Walkthrough

This PR introduces a shared getApplicationArgoUrl utility and useArgoServer hook that centralize Argo server resolution and application URL construction. Multiple Application tab/view components (ApplicationDetailsTab, ApplicationResourcesTab, ApplicationSourcesTab, ApplicationSyncStatusTab, History, ApplicationGraphView, ApplicationNavPage) are refactored to use these instead of duplicated useK8sModel/local state/effect logic. useApplicationActionsProvider now conditionally includes the "View in Argo CD" action only when a URL is available.

Changes

Argo URL centralization

Layer / File(s) Summary
Shared Argo URL utility and hook
src/gitops/utils/gitops.ts, src/gitops/utils/gitops.test.ts, src/gitops/hooks/useArgoServer.ts
Adds getApplicationArgoUrl(argoServer, app?) returning a formatted applications URL or empty string when inputs are missing, with tests; adds useArgoServer(app?) hook resolving ArgoServer via the Route model and getArgoServer.
Tab components migration
src/gitops/components/application/ApplicationDetailsTab.tsx, ApplicationResourcesTab.tsx, ApplicationSourcesTab.tsx, ApplicationSyncStatusTab.tsx
Replaces per-component useK8sModel/useState/useEffect Argo server fetching with useArgoServer and getApplicationArgoUrl, updating ArgoCDLink hrefs and useResourceRowsDV calls to use the derived argoUrl.
History and graph view migration
src/gitops/components/application/History/History.tsx, src/gitops/components/application/graph/ApplicationGraphView.tsx
Replaces Route-model based async Argo server resolution with useArgoServer/getApplicationArgoUrl; ApplicationGraphView also switches from useK8sModel for Route to useK8sModels().
Nav page wiring and conditional action
src/gitops/components/application/ApplicationNavPage.tsx, src/gitops/hooks/useApplicationActionsProvider.tsx
ApplicationNavPage derives argoUrl and passes it to useApplicationActionsProvider alongside application; the "View in Argo CD" action is now included in the actions array only when href is truthy, instead of always present with a disabled flag.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Component as Application Tab/View
  participant useArgoServer
  participant RouteModel as Route Model
  participant getApplicationArgoUrl

  Component->>useArgoServer: useArgoServer(app)
  useArgoServer->>RouteModel: getArgoServer(model, app)
  RouteModel-->>useArgoServer: ArgoServer (protocol, host)
  useArgoServer-->>Component: argoServer state
  Component->>getApplicationArgoUrl: getApplicationArgoUrl(argoServer, app)
  getApplicationArgoUrl-->>Component: argoUrl string
  Component->>Component: render ArgoCDLink / useResourceRowsDV with argoUrl
Loading

Related PRs: None found.

Suggested labels: refactor, frontend

Suggested reviewers: None specified.

🐰 A hop through hooks, a leap through state,
No more effects that fetch and wait,
One tidy URL, derived just right,
Argo links now shine bright and light!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main intent around the View in Argo CD action behavior and is specific enough for the changeset.
Description check ✅ Passed The description references the linked issue that this changeset implements, so it is related to the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

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.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 7.40741% with 50 lines in your changes missing coverage. Please review.
✅ Project coverage is 11.94%. Comparing base (01e9db1) to head (0d49285).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
src/gitops/hooks/useArgoServer.ts 0.00% 13 Missing ⚠️
...s/components/application/ApplicationDetailsTab.tsx 0.00% 5 Missing ⚠️
...tops/components/application/ApplicationNavPage.tsx 0.00% 5 Missing ⚠️
...components/application/ApplicationResourcesTab.tsx 0.00% 5 Missing ⚠️
...omponents/application/ApplicationSyncStatusTab.tsx 0.00% 5 Missing ⚠️
.../gitops/components/application/History/History.tsx 0.00% 5 Missing ⚠️
...ponents/application/graph/ApplicationGraphView.tsx 0.00% 5 Missing ⚠️
src/gitops/hooks/useApplicationActionsProvider.tsx 0.00% 4 Missing ⚠️
...s/components/application/ApplicationSourcesTab.tsx 0.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #254      +/-   ##
==========================================
+ Coverage   11.92%   11.94%   +0.01%     
==========================================
  Files         154      155       +1     
  Lines        6272     6305      +33     
  Branches     2028     2109      +81     
==========================================
+ Hits          748      753       +5     
- Misses       5524     5552      +28     
Flag Coverage Δ
unit-tests 11.94% <7.40%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/gitops/components/application/History/History.tsx (1)

63-69: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve the empty-url fallback before appending query params.

getApplicationArgoUrl returns '' until the Argo server is available, but this concatenation turns it into a relative ?resource=... link. Keep href empty when argoUrl is empty.

Proposed fix
-          argoUrl +
-          '?resource=&node=argoproj.io%2FApplication%2F' +
-          obj?.metadata?.namespace +
-          '%2F' +
-          obj?.metadata?.name +
-          '%2F' +
-          '&view=tree&resource=&operation=false&rollback=0'
+          argoUrl
+            ? `${argoUrl}?resource=&node=argoproj.io%2FApplication%2F${obj?.metadata?.namespace}%2F${obj?.metadata?.name}%2F&view=tree&resource=&operation=false&rollback=0`
+            : ''
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/components/application/History/History.tsx` around lines 63 - 69,
The `History` link builder is turning an empty `getApplicationArgoUrl` result
into a relative query-only URL instead of preserving the empty fallback. Update
the `href` construction in `History.tsx` so the query params are appended only
when `argoUrl` is non-empty, and otherwise keep the link empty. Use the existing
`getApplicationArgoUrl`/`argoUrl` logic in `History` to guard the concatenation.
src/gitops/components/application/ApplicationSourcesTab.tsx (1)

199-210: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Empty argoUrl produces a malformed relative link, not an empty one.

When getApplicationArgoUrl(argoServer, obj) returns '' (e.g., before useArgoServer's async resolution completes), the resulting href becomes '?resource=&node=...&tab=parameters' — a truthy, relative URL rather than an empty/no-op href. Clicking it during that window navigates to a nonsensical path instead of doing nothing.

🔧 Proposed fix
+  const argoUrl = getApplicationArgoUrl(argoServer, obj);
   return (
     <>
       <ArgoCDLink
         href={
-          getApplicationArgoUrl(argoServer, obj) +
-          '?resource=&node=argoproj.io%2FApplication%2F' +
-          obj?.metadata?.namespace +
-          '%2F' +
-          obj?.metadata?.name +
-          '%2F' +
-          '&tab=parameters'
+          argoUrl
+            ? `${argoUrl}?resource=&node=argoproj.io%2FApplication%2F${obj?.metadata?.namespace}%2F${obj?.metadata?.name}%2F&tab=parameters`
+            : ''
         }
       />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/components/application/ApplicationSourcesTab.tsx` around lines 199
- 210, The ArgoCD link in ApplicationSourcesTab is being built even when
getApplicationArgoUrl(argoServer, obj) returns an empty string, which turns the
href into a malformed relative URL. Update the ArgoCDLink href construction so
it only appends the resource/tab query when the base URL is present, and
otherwise pass an empty/no-op href. Use the ApplicationSourcesTab component and
getApplicationArgoUrl call as the key places to fix this conditional link
generation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/gitops/components/application/ApplicationDetailsTab.tsx`:
- Around line 49-50: Gate the Argo CD link rendering in ApplicationDetailsTab so
it only appears once the final argoUrl is available instead of passing an empty
or partial URL to ArgoCDLink. Update the logic around useArgoServer and
getApplicationArgoUrl to conditionally render the link only when argoUrl is
ready, and apply the same pattern in the related ApplicationResourcesTab and
ApplicationSourcesTab link paths so no query-only relative links are shown while
the server is still resolving.

In `@src/gitops/components/application/ApplicationResourcesTab.tsx`:
- Around line 50-51: Guard the resource-level Argo CD action in
ApplicationResourcesTab so it only renders or becomes enabled when
argoBaseURL/argoUrl is available, matching the application-level action
behavior. Update the kebab action path that calls
window.open(getResourceURL(argoBaseURL, resource), '_blank') to check for a
valid server URL first, and hide or disable the action until useArgoServer(obj)
and getApplicationArgoUrl(...) have produced a usable URL.

In `@src/gitops/components/application/graph/ApplicationGraphView.tsx`:
- Around line 343-348: The ref initializer block in ApplicationGraphView is
failing Prettier/ESLint formatting, so normalize the indentation and alignment
of the object/function arguments in that section. Update the ref initializer
near the ApplicationGraphView component so the listed symbols (application,
navigate, launchLabelsModal, launchAnnotationsModal, launchDeleteModal,
setGroupNodeStates) follow the same multiline formatting style as the rest of
the file and pass the lint gate.

In `@src/gitops/hooks/useApplicationActionsProvider.tsx`:
- Around line 154-168: Fix the formatting in useApplicationActionsProvider’s
conditional action array so it matches ESLint/Prettier expectations, and remove
the dead disabled check from the “View in Argo CD” action. Since the array item
is only included when href is truthy, the disabled: href === undefined property
in the object is unreachable; clean up the object in the cta block and keep the
existing accessReview and window.open(href, '_blank') behavior intact.
- Around line 164-166: The CTA in useApplicationActionsProvider currently opens
a new tab with window.open(href, '_blank') and should be hardened against
tabnabbing. Update the cta callback to open the link with noopener and
noreferrer behavior, preserving the existing href/new-tab flow while preventing
the opened page from accessing window.opener.

In `@src/gitops/hooks/useArgoServer.ts`:
- Around line 8-25: The useArgoServer effect can still call setArgoServer after
app or model changes, allowing an older getArgoServer request to overwrite newer
state. Add a cancellation/cleanup guard inside useEffect in useArgoServer so
only the latest request can update state, and ignore resolved results or errors
after the effect has been invalidated; keep the logic tied to getArgoServer,
setArgoServer, and the React.useEffect cleanup.
- Around line 9-22: Guard the useEffect in useArgoServer until the Route model
from useK8sModel is available, since model can be undefined on the first render
and getArgoServer(model, app) may run too early. Add a check alongside the
existing app guard so the effect returns before calling getArgoServer when model
is not ready, and keep the current React.useEffect dependency list and
argoServer state flow unchanged.

In `@src/gitops/utils/gitops.test.ts`:
- Around line 14-24: The gitops tests in getApplicationArgoUrl need prettier
cleanup because the multi-line calls are not formatted consistently. Update the
assertions in gitops.test.ts so the getApplicationArgoUrl invocations follow
standard line breaks and indentation, matching prettier output; using the
getApplicationArgoUrl test cases as the anchor should make the formatting fix
straightforward.

---

Outside diff comments:
In `@src/gitops/components/application/ApplicationSourcesTab.tsx`:
- Around line 199-210: The ArgoCD link in ApplicationSourcesTab is being built
even when getApplicationArgoUrl(argoServer, obj) returns an empty string, which
turns the href into a malformed relative URL. Update the ArgoCDLink href
construction so it only appends the resource/tab query when the base URL is
present, and otherwise pass an empty/no-op href. Use the ApplicationSourcesTab
component and getApplicationArgoUrl call as the key places to fix this
conditional link generation.

In `@src/gitops/components/application/History/History.tsx`:
- Around line 63-69: The `History` link builder is turning an empty
`getApplicationArgoUrl` result into a relative query-only URL instead of
preserving the empty fallback. Update the `href` construction in `History.tsx`
so the query params are appended only when `argoUrl` is non-empty, and otherwise
keep the link empty. Use the existing `getApplicationArgoUrl`/`argoUrl` logic in
`History` to guard the concatenation.
🪄 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: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: 31c220ff-a5c0-455d-809f-03c14b976d7e

📥 Commits

Reviewing files that changed from the base of the PR and between 9086cb7 and 0d49285.

📒 Files selected for processing (11)
  • src/gitops/components/application/ApplicationDetailsTab.tsx
  • src/gitops/components/application/ApplicationNavPage.tsx
  • src/gitops/components/application/ApplicationResourcesTab.tsx
  • src/gitops/components/application/ApplicationSourcesTab.tsx
  • src/gitops/components/application/ApplicationSyncStatusTab.tsx
  • src/gitops/components/application/History/History.tsx
  • src/gitops/components/application/graph/ApplicationGraphView.tsx
  • src/gitops/hooks/useApplicationActionsProvider.tsx
  • src/gitops/hooks/useArgoServer.ts
  • src/gitops/utils/gitops.test.ts
  • src/gitops/utils/gitops.ts

Comment on lines +49 to +50
const argoServer = useArgoServer(obj);
const argoUrl = getApplicationArgoUrl(argoServer, obj);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- files ---\n'
git ls-files 'src/gitops/components/application/*' 'src/gitops/hooks/*' | sed -n '1,200p'

printf '\n--- relevant symbols ---\n'
rg -n "useArgoServer|getApplicationArgoUrl|ArgoCDLink|View in Argo CD|useApplicationActionsProvider" src/gitops/components src/gitops/hooks -S

printf '\n--- ApplicationDetailsTab excerpt ---\n'
sed -n '1,220p' src/gitops/components/application/ApplicationDetailsTab.tsx

printf '\n--- ApplicationResourcesTab excerpt ---\n'
sed -n '1,220p' src/gitops/components/application/ApplicationResourcesTab.tsx

printf '\n--- ApplicationSourcesTab excerpt ---\n'
sed -n '1,220p' src/gitops/components/application/ApplicationSourcesTab.tsx

printf '\n--- useArgoServer / url helper excerpts ---\n'
rg -n "function useArgoServer|const useArgoServer|export .*useArgoServer|function getApplicationArgoUrl|const getApplicationArgoUrl|export .*getApplicationArgoUrl" src -S

Repository: redhat-developer/gitops-console-plugin

Length of output: 267


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- files ---'
git ls-files 'src/gitops/components/application/*' 'src/gitops/hooks/*' | sed -n '1,200p'

echo
echo '--- relevant symbols ---'
rg -n "useArgoServer|getApplicationArgoUrl|ArgoCDLink|View in Argo CD|useApplicationActionsProvider" src/gitops/components src/gitops/hooks -S

echo
echo '--- ApplicationDetailsTab excerpt ---'
sed -n '1,220p' src/gitops/components/application/ApplicationDetailsTab.tsx

echo
echo '--- ApplicationResourcesTab excerpt ---'
sed -n '1,220p' src/gitops/components/application/ApplicationResourcesTab.tsx

echo
echo '--- ApplicationSourcesTab excerpt ---'
sed -n '1,220p' src/gitops/components/application/ApplicationSourcesTab.tsx

echo
echo '--- useArgoServer / url helper excerpts ---'
rg -n "function useArgoServer|const useArgoServer|export .*useArgoServer|function getApplicationArgoUrl|const getApplicationArgoUrl|export .*getApplicationArgoUrl" src -S

Repository: redhat-developer/gitops-console-plugin

Length of output: 30790


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- useArgoServer.ts ---'
cat -n src/gitops/hooks/useArgoServer.ts

echo
echo '--- utils/gitops.ts around getApplicationArgoUrl ---'
sed -n '80,150p' src/gitops/utils/gitops.ts | cat -n

echo
echo '--- ArgoCDLink.tsx ---'
cat -n src/gitops/components/shared/ArgoCDLink/ArgoCDLink.tsx

echo
echo '--- ApplicationDetailsTab around the link ---'
sed -n '120,150p' src/gitops/components/application/ApplicationDetailsTab.tsx | cat -n

echo
echo '--- ApplicationResourcesTab around the link ---'
sed -n '105,125p' src/gitops/components/application/ApplicationResourcesTab.tsx | cat -n

echo
echo '--- ApplicationSourcesTab around the link ---'
sed -n '190,215p' src/gitops/components/application/ApplicationSourcesTab.tsx | cat -n

Repository: redhat-developer/gitops-console-plugin

Length of output: 8354


Hide Argo CD links until the URL is ready

  • ApplicationDetailsTab.tsx and ApplicationResourcesTab.tsx pass '' to ArgoCDLink while useArgoServer is still resolving.
  • ApplicationSourcesTab.tsx turns that same state into a query-only relative link (?resource=...).

Gate these links on the final argoUrl before rendering.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/components/application/ApplicationDetailsTab.tsx` around lines 49
- 50, Gate the Argo CD link rendering in ApplicationDetailsTab so it only
appears once the final argoUrl is available instead of passing an empty or
partial URL to ArgoCDLink. Update the logic around useArgoServer and
getApplicationArgoUrl to conditionally render the link only when argoUrl is
ready, and apply the same pattern in the related ApplicationResourcesTab and
ApplicationSourcesTab link paths so no query-only relative links are shown while
the server is still resolving.

Comment on lines +50 to +51
const argoServer = useArgoServer(obj);
const argoUrl = getApplicationArgoUrl(argoServer, obj);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether useResourceActionsProvider conditionally handles an empty argoBaseURL
# similar to useApplicationActionsProvider's href-truthy check.
fd -e ts -e tsx useResourceActionsProvider
rg -n -A 20 'useResourceActionsProvider' --type=tsx --type=ts

Repository: redhat-developer/gitops-console-plugin

Length of output: 252


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== outline: ApplicationResourcesTab =="
ast-grep outline src/gitops/components/application/ApplicationResourcesTab.tsx --view expanded || true

echo
echo "== outline: useResourceActionsProvider =="
ast-grep outline src/gitops/hooks/useResourceActionsProvider.tsx --view expanded || true

echo
echo "== outline: useApplicationActionsProvider =="
fd -a useApplicationActionsProvider src/gitops/hooks src/gitops/components || true
if [ -f src/gitops/hooks/useApplicationActionsProvider.tsx ]; then
  ast-grep outline src/gitops/hooks/useApplicationActionsProvider.tsx --view expanded || true
fi

echo
echo "== relevant matches =="
rg -n -A 30 -B 10 'useResourceActionsProvider|useApplicationActionsProvider|argoBaseURL|argoUrl|View in Argo CD' src/gitops/components/application/ApplicationResourcesTab.tsx src/gitops/hooks/useResourceActionsProvider.tsx src/gitops/hooks/useApplicationActionsProvider.tsx || true

Repository: redhat-developer/gitops-console-plugin

Length of output: 38061


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== useResourceActionsProvider =="
cat -n src/gitops/hooks/useResourceActionsProvider.tsx | sed -n '1,260p'

echo
echo "== useApplicationActionsProvider =="
fd -a useApplicationActionsProvider src/gitops/hooks src/gitops/components || true
if [ -f src/gitops/hooks/useApplicationActionsProvider.tsx ]; then
  cat -n src/gitops/hooks/useApplicationActionsProvider.tsx | sed -n '1,260p'
fi

echo
echo "== ApplicationResourcesTab around the caller =="
cat -n src/gitops/components/application/ApplicationResourcesTab.tsx | sed -n '280,340p'

Repository: redhat-developer/gitops-console-plugin

Length of output: 13126


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,260p' src/gitops/hooks/useResourceActionsProvider.tsx | cat -n
printf '\n---\n'
sed -n '1,260p' src/gitops/hooks/useApplicationActionsProvider.tsx | cat -n
printf '\n---\n'
sed -n '280,340p' src/gitops/components/application/ApplicationResourcesTab.tsx | cat -n

Repository: redhat-developer/gitops-console-plugin

Length of output: 12947


Guard the resource-level Argo CD action on argoBaseURL The kebab action still always renders and calls window.open(getResourceURL(argoBaseURL, resource), '_blank'), so it can still open a broken/empty Argo CD URL when the server URL isn’t ready. Hide or disable this action until the URL exists, like the application action does.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/components/application/ApplicationResourcesTab.tsx` around lines
50 - 51, Guard the resource-level Argo CD action in ApplicationResourcesTab so
it only renders or becomes enabled when argoBaseURL/argoUrl is available,
matching the application-level action behavior. Update the kebab action path
that calls window.open(getResourceURL(argoBaseURL, resource), '_blank') to check
for a valid server URL first, and hide or disable the action until
useArgoServer(obj) and getApplicationArgoUrl(...) have produced a usable URL.

Comment on lines +343 to +348
application,
navigate,
launchLabelsModal,
launchAnnotationsModal,
launchDeleteModal,
setGroupNodeStates,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the Prettier error in the ref initializer.

ESLint reports this block as non-compliant; normalize the indentation so the lint gate passes.

Proposed fix
-        application,
-        navigate,
-        launchLabelsModal,
-        launchAnnotationsModal,
-        launchDeleteModal,
-        setGroupNodeStates,
+    application,
+    navigate,
+    launchLabelsModal,
+    launchAnnotationsModal,
+    launchDeleteModal,
+    setGroupNodeStates,
📝 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.

Suggested change
application,
navigate,
launchLabelsModal,
launchAnnotationsModal,
launchDeleteModal,
setGroupNodeStates,
application,
navigate,
launchLabelsModal,
launchAnnotationsModal,
launchDeleteModal,
setGroupNodeStates,
🧰 Tools
🪛 ESLint

[error] 343-343: Delete ····

(prettier/prettier)


[error] 344-344: Replace ········ with ····

(prettier/prettier)


[error] 345-345: Delete ····

(prettier/prettier)


[error] 346-346: Delete ····

(prettier/prettier)


[error] 347-347: Replace ········ with ····

(prettier/prettier)


[error] 348-348: Delete ····

(prettier/prettier)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/components/application/graph/ApplicationGraphView.tsx` around
lines 343 - 348, The ref initializer block in ApplicationGraphView is failing
Prettier/ESLint formatting, so normalize the indentation and alignment of the
object/function arguments in that section. Update the ref initializer near the
ApplicationGraphView component so the listed symbols (application, navigate,
launchLabelsModal, launchAnnotationsModal, launchDeleteModal,
setGroupNodeStates) follow the same multiline formatting style as the rest of
the file and pass the lint gate.

Source: Linters/SAST tools

Comment on lines +154 to +168
...(href ? [{
id: 'gitops-action-view-in-argocd',
disabled: href === undefined,
label: t('View in Argo CD'),
accessReview: {
group: ApplicationModel.apiGroup,
verb: 'get' as K8sVerb,
resource: ApplicationModel.plural,
namespace: application?.metadata?.namespace,
},
cta: () => {
window.open(href, '_blank');
}
}] : []
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix lint formatting and drop the now-dead disabled check.

ESLint/Prettier report formatting violations across this block. Also, since the object is only spread into the array when href is truthy, disabled: href === undefined can never be true — it's dead logic left over from the previous always-present-but-disabled approach.

🧹 Proposed cleanup
-      ...(href ? [{
-          id: 'gitops-action-view-in-argocd',
-          disabled: href === undefined,
-          label: t('View in Argo CD'),
-          accessReview: {
-            group: ApplicationModel.apiGroup,
-            verb: 'get' as K8sVerb,
-            resource: ApplicationModel.plural,
-            namespace: application?.metadata?.namespace,
-          },
-          cta: () => {
-            window.open(href, '_blank');
-          }
-        }] : []
-      ),
+      ...(href
+        ? [
+            {
+              id: 'gitops-action-view-in-argocd',
+              disabled: false,
+              label: t('View in Argo CD'),
+              accessReview: {
+                group: ApplicationModel.apiGroup,
+                verb: 'get' as K8sVerb,
+                resource: ApplicationModel.plural,
+                namespace: application?.metadata?.namespace,
+              },
+              cta: () => {
+                window.open(href, '_blank');
+              },
+            },
+          ]
+        : []),

As per static analysis hints (prettier/prettier), these lines require formatting corrections.

📝 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.

Suggested change
...(href ? [{
id: 'gitops-action-view-in-argocd',
disabled: href === undefined,
label: t('View in Argo CD'),
accessReview: {
group: ApplicationModel.apiGroup,
verb: 'get' as K8sVerb,
resource: ApplicationModel.plural,
namespace: application?.metadata?.namespace,
},
cta: () => {
window.open(href, '_blank');
}
}] : []
),
...(href
? [
{
id: 'gitops-action-view-in-argocd',
disabled: false,
label: t('View in Argo CD'),
accessReview: {
group: ApplicationModel.apiGroup,
verb: 'get' as K8sVerb,
resource: ApplicationModel.plural,
namespace: application?.metadata?.namespace,
},
cta: () => {
window.open(href, '_blank');
},
},
]
: []),
🧰 Tools
🪛 ESLint

[error] 154-154: Replace ·?·[ with ⏎········?·[⏎············

(prettier/prettier)


[error] 155-155: Replace ·········· with ··············

(prettier/prettier)


[error] 156-156: Insert ····

(prettier/prettier)


[error] 157-157: Replace ·········· with ··············

(prettier/prettier)


[error] 158-158: Replace ·········· with ··············

(prettier/prettier)


[error] 159-159: Insert ····

(prettier/prettier)


[error] 160-160: Insert ····

(prettier/prettier)


[error] 161-161: Replace ············ with ················

(prettier/prettier)


[error] 162-162: Insert ····

(prettier/prettier)


[error] 163-163: Insert ····

(prettier/prettier)


[error] 164-164: Replace ·········· with ··············

(prettier/prettier)


[error] 165-165: Insert ····

(prettier/prettier)


[error] 166-166: Replace } with ····},

(prettier/prettier)


[error] 167-167: Replace }]·:·[ with ····},⏎··········

(prettier/prettier)


[error] 168-168: Replace ······ with ········:·[]

(prettier/prettier)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/hooks/useApplicationActionsProvider.tsx` around lines 154 - 168,
Fix the formatting in useApplicationActionsProvider’s conditional action array
so it matches ESLint/Prettier expectations, and remove the dead disabled check
from the “View in Argo CD” action. Since the array item is only included when
href is truthy, the disabled: href === undefined property in the object is
unreachable; clean up the object in the cta block and keep the existing
accessReview and window.open(href, '_blank') behavior intact.

Source: Linters/SAST tools

Comment on lines +164 to +166
cta: () => {
window.open(href, '_blank');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Harden window.open against tabnabbing.

Opening a new tab via window.open(href, '_blank') without noopener/noreferrer lets the new page access window.opener and redirect the original tab.

🔒 Proposed fix
-          cta: () => {
-            window.open(href, '_blank');
-          }
+          cta: () => {
+            window.open(href, '_blank', 'noopener,noreferrer');
+          },
📝 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.

Suggested change
cta: () => {
window.open(href, '_blank');
}
cta: () => {
window.open(href, '_blank', 'noopener,noreferrer');
},
🧰 Tools
🪛 ESLint

[error] 164-164: Replace ·········· with ··············

(prettier/prettier)


[error] 165-165: Insert ····

(prettier/prettier)


[error] 166-166: Replace } with ····},

(prettier/prettier)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/hooks/useApplicationActionsProvider.tsx` around lines 164 - 166,
The CTA in useApplicationActionsProvider currently opens a new tab with
window.open(href, '_blank') and should be hardened against tabnabbing. Update
the cta callback to open the link with noopener and noreferrer behavior,
preserving the existing href/new-tab flow while preventing the opened page from
accessing window.opener.

Comment on lines +8 to +25
export const useArgoServer = (app?: ApplicationKind): ArgoServer => {
const [model] = useK8sModel({ group: 'route.openshift.io', version: 'v1', kind: 'Route' });
const [argoServer, setArgoServer] = React.useState<ArgoServer>({ host: '', protocol: '' });

React.useEffect(() => {
if (!app) {
return undefined;
}

getArgoServer(model, app)
.then(setArgoServer)
.catch((err) => {
console.error('Error:', err);
});
}, [model, app]);

return argoServer;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add cancellation guard to avoid stale state updates.

The effect has no cleanup, so if app (or model) changes before the in-flight getArgoServer promise resolves, a stale response can overwrite state with outdated data after the newer request has already started/resolved.

🔧 Proposed fix
   React.useEffect(() => {
     if (!app) {
       return undefined;
     }
-
-    getArgoServer(model, app)
-      .then(setArgoServer)
-      .catch((err) => {
-        console.error('Error:', err);
-      });
+    let cancelled = false;
+
+    getArgoServer(model, app)
+      .then((server) => {
+        if (!cancelled) setArgoServer(server);
+      })
+      .catch((err) => {
+        if (!cancelled) console.error('Error:', err);
+      });
+
+    return () => {
+      cancelled = true;
+    };
   }, [model, app]);
📝 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.

Suggested change
export const useArgoServer = (app?: ApplicationKind): ArgoServer => {
const [model] = useK8sModel({ group: 'route.openshift.io', version: 'v1', kind: 'Route' });
const [argoServer, setArgoServer] = React.useState<ArgoServer>({ host: '', protocol: '' });
React.useEffect(() => {
if (!app) {
return undefined;
}
getArgoServer(model, app)
.then(setArgoServer)
.catch((err) => {
console.error('Error:', err);
});
}, [model, app]);
return argoServer;
};
export const useArgoServer = (app?: ApplicationKind): ArgoServer => {
const [model] = useK8sModel({ group: 'route.openshift.io', version: 'v1', kind: 'Route' });
const [argoServer, setArgoServer] = React.useState<ArgoServer>({ host: '', protocol: '' });
React.useEffect(() => {
if (!app) {
return undefined;
}
let cancelled = false;
getArgoServer(model, app)
.then((server) => {
if (!cancelled) setArgoServer(server);
})
.catch((err) => {
if (!cancelled) console.error('Error:', err);
});
return () => {
cancelled = true;
};
}, [model, app]);
return argoServer;
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/hooks/useArgoServer.ts` around lines 8 - 25, The useArgoServer
effect can still call setArgoServer after app or model changes, allowing an
older getArgoServer request to overwrite newer state. Add a cancellation/cleanup
guard inside useEffect in useArgoServer so only the latest request can update
state, and ignore resolved results or errors after the effect has been
invalidated; keep the logic tied to getArgoServer, setArgoServer, and the
React.useEffect cleanup.

Comment on lines +9 to +22
const [model] = useK8sModel({ group: 'route.openshift.io', version: 'v1', kind: 'Route' });
const [argoServer, setArgoServer] = React.useState<ArgoServer>({ host: '', protocol: '' });

React.useEffect(() => {
if (!app) {
return undefined;
}

getArgoServer(model, app)
.then(setArgoServer)
.catch((err) => {
console.error('Error:', err);
});
}, [model, app]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect getArgoServer to see how it uses the model param and whether an unresolved model causes incorrect host resolution.
rg -n -A 20 'export (const|function) getArgoServer' src/gitops/utils/gitops.ts

Repository: redhat-developer/gitops-console-plugin

Length of output: 1663


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== useArgoServer.ts ==\n'
sed -n '1,220p' src/gitops/hooks/useArgoServer.ts

printf '\n== gitops.ts getArgoServer area ==\n'
sed -n '1,180p' src/gitops/utils/gitops.ts

printf '\n== useK8sModel usages ==\n'
rg -n "useK8sModel\\(" src | sed -n '1,120p'

Repository: redhat-developer/gitops-console-plugin

Length of output: 7942


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== inFlight usage with useK8sModel ==\n'
rg -n -A 3 -B 3 'useK8sModel\\(' src | sed -n '1,240p'

printf '\n== explicit inFlight references ==\n'
rg -n 'inFlight' src | sed -n '1,240p'

printf '\n== similar Route model hooks/components ==\n'
sed -n '300,380p' src/gitops/components/appset/graph/ApplicationSetGraphView.tsx
sed -n '60,120p' src/gitops/components/project/ProjectRolesTab.tsx
sed -n '60,120p' src/gitops/components/project/ProjectAllowDenyTab.tsx
sed -n '1,80p' src/gitops/components/project/ProjectSyncWindowsTab.tsx

Repository: redhat-developer/gitops-console-plugin

Length of output: 294


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== explicit inFlight references ==\n'
rg -n 'inFlight' src | sed -n '1,240p'

printf '\n== useK8sModel call sites around Route model ==\n'
sed -n '320,360p' src/gitops/components/appset/graph/ApplicationSetGraphView.tsx
sed -n '70,110p' src/gitops/components/project/ProjectRolesTab.tsx
sed -n '60,100p' src/gitops/components/project/ProjectAllowDenyTab.tsx
sed -n '1,60p' src/gitops/components/project/ProjectSyncWindowsTab.tsx

printf '\n== useArgoServer consumers ==\n'
rg -n 'useArgoServer\\(' src | sed -n '1,120p'

Repository: redhat-developer/gitops-console-plugin

Length of output: 212


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== useArgoServer consumers ==\n'
rg -n 'useArgoServer\(' src | sed -n '1,120p'

printf '\n== relevant consumer files ==\n'
sed -n '1,220p' src/gitops/components/project/ProjectRolesTab.tsx
sed -n '1,220p' src/gitops/components/project/ProjectAllowDenyTab.tsx
sed -n '1,120p' src/gitops/components/project/ProjectSyncWindowsTab.tsx
sed -n '300,380p' src/gitops/components/appset/graph/ApplicationSetGraphView.tsx

Repository: redhat-developer/gitops-console-plugin

Length of output: 21995


🌐 Web query:

useK8sModel returns [model, inFlight] dynamic-plugin-sdk semantics and whether model is undefined before the resource is loaded

💡 Result:

The useK8sModel hook in the dynamic-plugin-sdk returns an array containing two elements: [model, inFlight] [1][2]. The model element represents the retrieved Kubernetes model (or undefined) [2][3], and the inFlight element is a boolean indicating the current loading status [1][2]. Regarding the behavior before the resource (model) is loaded: 1. Model State: Before the Kubernetes models are fully loaded or if the requested model cannot be found in the Redux store, the model value is undefined [2][3]. The hook retrieves the model from Redux, and if it is not present, it returns undefined [3]. 2. In-Flight Status: The inFlight boolean indicates whether the application is currently fetching or waiting for Kubernetes model data [1][2]. Because the hook relies on Redux state for model retrieval, it is designed to reactively update. When a component first mounts and the model data has not yet been populated in the global store, the model will typically be undefined until the underlying Redux state is updated with the available models [2][3]. Summary of return values: - model: The K8sModel object (if found) or undefined (if not found or still loading) [2][3]. - inFlight: A boolean true while the models are loading/fetching, and false once the loading process has completed [1][2].

Citations:


Guard the effect until the Route model is available. useK8sModel can return undefined on the first render, so getArgoServer(model, app) may run once with an unresolved model and emit an avoidable error before the effect reruns.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/hooks/useArgoServer.ts` around lines 9 - 22, Guard the useEffect
in useArgoServer until the Route model from useK8sModel is available, since
model can be undefined on the first render and getArgoServer(model, app) may run
too early. Add a check alongside the existing app guard so the effect returns
before calling getArgoServer when model is not ready, and keep the current
React.useEffect dependency list and argoServer state flow unchanged.

Comment on lines +14 to +24
getApplicationArgoUrl({ protocol: 'https', host: 'openshift-gitops-server-openshift-gitops' }, {
metadata: { name: 'guestbook', namespace: 'openshift-gitops' },
} as any),
).toBe('https://openshift-gitops-server-openshift-gitops/applications/openshift-gitops/guestbook');
});

it('returns empty string when server or app metadata is missing', () => {
expect(getApplicationArgoUrl({ protocol: 'https', host: '' }, {} as any)).toBe('');
expect(
getApplicationArgoUrl({ protocol: 'https', host: 'openshift-gitops-server-openshift-gitops' }, undefined),
).toBe('');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix prettier formatting.

ESLint/prettier flags formatting issues on lines 14-17 and 23 (missing line breaks/indentation in the multi-line getApplicationArgoUrl calls). Run prettier --write on this file.

🧰 Tools
🪛 ESLint

[error] 14-14: Replace {·protocol:·'https',·host:·'openshift-gitops-server-openshift-gitops'·}, with ⏎········{·protocol:·'https',·host:·'openshift-gitops-server-openshift-gitops'·},⏎·······

(prettier/prettier)


[error] 15-15: Insert ··

(prettier/prettier)


[error] 16-16: Replace }·as·any with ··}·as·any,⏎······

(prettier/prettier)


[error] 17-17: Replace 'https://openshift-gitops-server-openshift-gitops/applications/openshift-gitops/guestbook' with ⏎······'https://openshift-gitops-server-openshift-gitops/applications/openshift-gitops/guestbook',⏎····

(prettier/prettier)


[error] 23-23: Replace {·protocol:·'https',·host:·'openshift-gitops-server-openshift-gitops'·},·undefined with ⏎········{·protocol:·'https',·host:·'openshift-gitops-server-openshift-gitops'·},⏎········undefined,⏎······

(prettier/prettier)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gitops/utils/gitops.test.ts` around lines 14 - 24, The gitops tests in
getApplicationArgoUrl need prettier cleanup because the multi-line calls are not
formatted consistently. Update the assertions in gitops.test.ts so the
getApplicationArgoUrl invocations follow standard line breaks and indentation,
matching prettier output; using the getApplicationArgoUrl test cases as the
anchor should make the formatting fix straightforward.

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants