Skip to content

Improve UX with inline resources links#2174

Open
jpinsonneau wants to merge 4 commits into
openshift:mainfrom
jpinsonneau:linked-resources
Open

Improve UX with inline resources links#2174
jpinsonneau wants to merge 4 commits into
openshift:mainfrom
jpinsonneau:linked-resources

Conversation

@jpinsonneau

@jpinsonneau jpinsonneau commented Jul 6, 2026

Copy link
Copy Markdown

Summary

Adds inline linked Kubernetes resources to Lightspeed AI responses. When the assistant mentions resources returned by MCP tools (pod lists, resources_get, etc.), matching names in the response prose become clickable console links with kind icons and live status (SDK ResourceIcon + StatusComponent).

  • Detection — Parses tool results (MCP tables, YAML, structured JSON) and response text to build ResourceRefs; filters noise and non-linkable kinds (ConfigMaps, Secrets, namespaces).
  • Inline UI — Injects markdown links and renders InlineLinkedResource (icon + name + status badge) inside chat messages; navigation works from the Lightspeed modal via useConsoleNavigation.
  • Status — Watches resources with useK8sWatchResource; pod status uses container waiting reasons (e.g. CrashLoopBackOff) to match the console, not just phase.
  • Mock OLS servernpm run start-mock-ols serves a minimal lightspeed-service-compatible API for local testing without a real OLS backend. Supports common list/get scenarios, reads live pod data from oc when available, and aligns SSE/MCP output with kubernetes-mcp-server. Configurable via env vars (MOCK_NAMESPACE, MOCK_PODS, MOCK_DIVERSE_POD_STATUSES, etc.). => moved to Add mock OLS server #2182
  • Tests — 235 unit tests covering ref extraction, path building, markdown injection, status mapping, and CRD handling.

Also refactors GeneralPage message rendering (useLinkedResourceMarkdown, useMessageSources) and documents console image pinning in the README.

Test plan

  • npm run test:unit
  • npm run lint-fix && npm run build
  • Terminal 1: npm run start-mock-ols — Terminal 2: npm run start — Terminal 3: oc login && npm run start-console
  • In Lightspeed, ask e.g. “show pods in default” — verify inline pod names link to console, kind icons match, status icons match cluster (including a failing pod)
  • Click a link — confirm navigation to the resource details page from the chat modal
  • Optional: MOCK_DIVERSE_POD_STATUSES=1 npm run start-mock-ols to exercise varied statuses in tool output when no cluster is available

Assisted-by: cursor + claude opus 4.6

Summary by CodeRabbit

  • New Features
    • Added inline linked-resource support in chat, including clickable console navigation, resource icons, and live status badges, plus improved evidence/source context and pagination.
    • Added a local mock server for OpenShift Lightspeed streaming to enable linked-resource testing.
  • Bug Fixes
    • Improved Kubernetes/OpenShift resource status display and made console navigation more robust.
  • Documentation
    • Updated local development guidance, including default console image tag and token/Kubernetes auth troubleshooting notes.
  • Tests
    • Added unit test coverage for status, navigation, linked-resource rendering, markdown linking, and resource extraction.

@openshift-ci openshift-ci Bot requested review from joshuawilson and xrajesh July 6, 2026 09:54
@openshift-ci

openshift-ci Bot commented Jul 6, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign joshuawilson for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds shared resource-model and status helpers, linked-resource extraction and inline rendering, local mock/startup tooling, and updated localization/configuration. It also expands tests across model resolution, parsing, status mapping, and navigation.

Changes

Linked resources and local workflow

Layer / File(s) Summary
Shared model, path, and status helpers
src/pageContext.ts, src/crStatus.ts, src/resourceStatus.ts, src/linkedResourceWatch.ts, src/linkedResourceStatusDisplay.ts, src/consoleNavigation.ts, src/hooks/useConsoleNavigation.ts, src/hooks/useMessageSources.tsx
Adds shared resource model/ref types, console path resolution, status summaries, watch gating, status-display mapping, and console navigation/message-source hooks.
Resource parsing and link extraction
src/resourceListParsing.ts, src/resourceRefs.ts, src/linkedResources.ts, src/linkedResourceText.ts, src/hooks/useLinkedResourceMarkdown.tsx
Parses tool output and response text into resource refs, ranks and caps linkable refs, and injects resource links into markdown.
Inline linked-resource UI
src/components/ResourceIcon.tsx, src/components/InlineLinkedResource.tsx, src/components/LinkedResourceStatus.tsx, src/components/linked-resources.css, src/components/GeneralPage.tsx
Renders inline linked resources with icons and optional status badges, and wires the new hooks and model state into chat rendering.
Mock server, startup, and build updates
scripts/mock-ols-server.mjs, start-console.sh, package.json, webpack.config.ts, .eslintrc.yml, locales/en/plugin__lightspeed-console-plugin.json, README.md
Adds the mock OLS server, updates local startup behavior, preserves locale asset paths, and documents the new local workflow.
Unit tests
unit-tests/*
Expands coverage for model resolution, status mapping, resource parsing, markdown linking, linked-resource rendering, console navigation, and startup/mock behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and clearly reflects the main change: adding inline resource links to improve the console experience.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@jpinsonneau jpinsonneau mentioned this pull request Jul 6, 2026
4 tasks

@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: 10

🧹 Nitpick comments (13)
src/linkedResources.ts (2)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prettier formatting.

Static analysis flags the multi-import statement formatting on this line.

🤖 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/linkedResources.ts` at line 1, The import in linkedResources.ts needs
Prettier-compliant formatting because the current single-line multi-import is
flagged by static analysis. Reformat the existing import from pageContext to
match the project’s multiline import style, keeping the same symbols
getModelKindName, K8sModelRef, resolveRefModelKey, and resolveRefModelKeyOrKind
but spreading them across lines as needed.

Source: Linters/SAST tools


112-120: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Redundant recomputation in getLinkedResourceOverflow.

This calls extractLinkableResourceRefs directly for linkable, then calls extractLinkedResources, which internally recomputes extractLinkableResourceRefs (and re-runs prioritizeLinkedResources) a second time — duplicating the JSON/YAML parsing and regex-heavy extraction pipeline over the same tools/text for a single overflow calculation.

♻️ Proposed fix avoiding duplicate extraction
 export const getLinkedResourceOverflow = (
   tools: Record<string, Tool> | undefined,
   responseText: string | undefined,
   models: Record<string, K8sModelRef>,
 ): { shown: number; total: number } => {
   const linkable = extractLinkableResourceRefs(tools, responseText, models);
-  const shown = extractLinkedResources(tools, responseText, models).length;
-  return { shown, total: linkable.length };
+  const limit = resolveLinkedResourceLimit(tools, linkable.length);
+  return { shown: Math.min(linkable.length, limit), total: linkable.length };
 };
🤖 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/linkedResources.ts` around lines 112 - 120, getLinkedResourceOverflow is
doing the same linkable-resource extraction twice by calling
extractLinkableResourceRefs and then extractLinkedResources, which re-runs the
same parsing/prioritization work. Update getLinkedResourceOverflow to compute
the linked resources once and derive both shown and total from that shared
result, or otherwise reuse the single extractLinkableResourceRefs output instead
of invoking the pipeline again. Keep the fix localized to
getLinkedResourceOverflow and the linked resource helpers it calls.
src/resourceRefs.ts (1)

114-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate regex constant.

K8S_NODE_NAME_RE here is identical to the one already defined in src/resourceListParsing.ts (Line 4). Consider exporting one and importing it to avoid drift between the two copies.

🤖 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/resourceRefs.ts` at line 114, The K8S_NODE_NAME_RE regex is duplicated in
resourceRefs and resourceListParsing, so update the duplicated constant to use a
single shared definition instead of two copies. Export K8S_NODE_NAME_RE from
resourceListParsing and import it into resourceRefs, then remove the local
declaration so both ResourceRefs and ResourceListParsing rely on the same source
of truth.
unit-tests/linkedResourceWatch.test.ts (1)

33-53: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

No test coverage for kind-mismatch in matchesResourceRef.

Given the missing kind check flagged in src/linkedResourceWatch.ts (Lines 42-59), consider adding a test asserting matchesResourceRef rejects a resource with matching name/namespace but a different kind, once that check is added.

🤖 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 `@unit-tests/linkedResourceWatch.test.ts` around lines 33 - 53, Add a test in
matchesResourceRef coverage to verify kind mismatches are rejected: extend the
linkedResourceWatch.test.ts suite with a case where the resource name/namespace
matches but the resource kind differs from the ref, and assert
matchesResourceRef returns false. Use the matchesResourceRef helper and the
existing Namespace-style cases as the reference point so the new test clearly
exercises the kind check added in linkedResourceWatch.ts.
src/linkedResourceWatch.ts (1)

42-59: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

matchesResourceRef doesn't verify resource kind.

The check only compares metadata.name and metadata.namespace, not the kind. If a resourceRef transitions to a different kind but the same name/namespace (e.g. a component reused for a new resource before useK8sWatchResource re-fetches), a stale watched object of the previous kind would incorrectly be reported as matching, potentially showing status for the wrong resource kind.

Consider also comparing resource.kind (or the model's apiVersion/kind derived from resourceRef) to close this gap.

🤖 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/linkedResourceWatch.ts` around lines 42 - 59, `matchesResourceRef` only
checks name and namespace, so it can treat a stale object from the wrong kind as
a match. Update `matchesResourceRef` in `linkedResourceWatch` to also compare
the resource kind against `resourceRef` (or the derived model kind/apiVersion
from the ref) before returning true, while keeping the existing name/namespace
checks intact.
src/components/LinkedResourceStatus.tsx (1)

21-46: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant !hasMatchingResource check on Line 37.

After Line 33 already returns null for loaded && !hasMatchingResource, by the time Line 37 executes, !hasMatchingResource can only be true when !loaded is also true — so the check simplifies to just !loaded. Not a bug, but worth simplifying for clarity.

♻️ Proposed simplification
-  if (!loaded || !hasMatchingResource) {
+  if (!loaded) {
     return <Spinner aria-label={t('Loading resource status')} isInline size="sm" />;
   }
🤖 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/components/LinkedResourceStatus.tsx` around lines 21 - 46, The loading
condition in LinkedResourceStatus is redundant because the earlier null return
already covers the case where loaded is true and the resource does not match.
Simplify the conditional after the loadError check to only test loaded, keeping
the existing behavior intact while making the logic in LinkedResourceStatus
clearer.
src/components/InlineLinkedResource.tsx (1)

49-55: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

key prop is a no-op here.

key={resourceRefKey(resourceRef)} is set on LinkedResourceStatus, but it's rendered as a single conditional child, not inside a list/iteration, so React ignores it — it has no effect on remounting when resourceRef changes.

🤖 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/components/InlineLinkedResource.tsx` around lines 49 - 55, The key on
LinkedResourceStatus is ineffective because this conditional render is not part
of a list, so React will ignore it. Remove the key from InlineLinkedResource
and, if remounting on resourceRef changes is actually needed, move the identity
change to the parent conditional or derive it through a different prop-driven
render path using shouldShowLinkedResourceStatus, LinkedResourceStatus, and
resourceRefKey as the relevant symbols.
scripts/mock-ols-server.mjs (1)

973-973: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Formatting/lint cleanup: run the project formatter and drop the unused variable.

Static analysis reports numerous prettier/prettier formatting diffs across this file (e.g. lines 69-70, 183-185, 190-191, 210, 243-245, 246-248, 367-368, 382-383, 446-448, 482, 593-594, 611-612, 668-669, 975, 999, 1002) plus an unused conversationId destructure here and a lowercase comment at line 970.

🧹 Proposed fix
-    const { body, scenarioKey, conversationId } = buildStreamBody(query);
+    const { body, scenarioKey } = buildStreamBody(query);

Run npx eslint --fix scripts/mock-ols-server.mjs to clear the remaining formatting diffs.

🤖 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 `@scripts/mock-ols-server.mjs` at line 973, The file has broad formatter/lint
drift and an unused destructured value in the stream setup. Run the project
formatter/eslint fix on scripts/mock-ols-server.mjs to resolve the reported
prettier/prettier issues, remove the unused conversationId from the
buildStreamBody(query) destructure, and adjust the nearby lowercase comment so
it matches the file’s style. Use the buildStreamBody and query-related code
around the stream handler to locate the cleanup.

Source: Linters/SAST tools

start-console.sh (1)

64-78: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Preflight checks validate both tools independently, even though only one is actually used.

resolve_api_server/resolve_bearer_token prefer oc and only fall back to kubectl. But the preflight here requires both oc (if installed) to be logged in AND kubectl (if installed) to reach the API — even when only one of them will be used. A machine with both CLIs installed, where kubectl's default context is unrelated to the target cluster, would fail to start even though oc works fine.

♻️ Proposed fix: only validate the tool that will be used
-if command -v oc >/dev/null 2>&1 && ! oc whoami >/dev/null 2>&1; then
-  echo "error: not logged in to a cluster. Run 'oc login' (or point KUBECONFIG at a running cluster) and retry." >&2
-  exit 1
-fi
-
-if command -v kubectl >/dev/null 2>&1 && ! kubectl cluster-info >/dev/null 2>&1; then
-  echo "error: cannot reach the Kubernetes API. Is your cluster running?" >&2
-  echo "  Try: kubectl cluster-info" >&2
-  exit 1
-fi
+if command -v oc >/dev/null 2>&1; then
+  if ! oc whoami >/dev/null 2>&1; then
+    echo "error: not logged in to a cluster. Run 'oc login' (or point KUBECONFIG at a running cluster) and retry." >&2
+    exit 1
+  fi
+elif command -v kubectl >/dev/null 2>&1; then
+  if ! kubectl cluster-info >/dev/null 2>&1; then
+    echo "error: cannot reach the Kubernetes API. Is your cluster running?" >&2
+    echo "  Try: kubectl cluster-info" >&2
+    exit 1
+  fi
+fi
🤖 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 `@start-console.sh` around lines 64 - 78, The preflight checks in
start-console.sh are validating both oc and kubectl independently, even though
resolve_api_server and resolve_bearer_token only use one tool at runtime. Update
the startup checks to mirror that selection logic: determine the preferred CLI
once (oc first, otherwise kubectl), then run only the matching login/API
reachability validation for that chosen command. Keep the existing error
handling and messages aligned with the selected tool so machines with both CLIs
installed do not fail due to the unused one.
src/hooks/useMessageSources.tsx (1)

7-14: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Restrict isURL to explicit safe protocols.

Checking only protocol && host allows any scheme with a host component (e.g. intent://, file://, custom app schemes) to pass validation and render as an isExternal clickable link. Since doc_url originates from LLM/tool output, consider allowlisting http:/https: explicitly for defense-in-depth.

🔒 Proposed hardening
 const isURL = (value: string): boolean => {
   try {
     const url = new URL(value);
-    return !!(url.protocol && url.host);
+    return (url.protocol === 'http:' || url.protocol === 'https:') && !!url.host;
   } catch {
     return false;
   }
 };
🤖 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/hooks/useMessageSources.tsx` around lines 7 - 14, The isURL helper
currently treats any URL with a protocol and host as valid, which can let unsafe
schemes through and mark them as external links. Update isURL in
useMessageSources.tsx to explicitly allow only http: and https: when validating
the parsed URL, and keep the existing URL parsing/error handling so doc_url
values from message sources are only rendered as clickable links for safe web
protocols.
unit-tests/resourceStatus.test.ts (1)

1-211: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

LGTM! Good coverage across kinds. Consider adding cases for a 0/0-replica workload and a ready LoadBalancer Service to cover the edge cases flagged in src/resourceStatus.ts.

🤖 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 `@unit-tests/resourceStatus.test.ts` around lines 1 - 211, The resource status
tests are missing coverage for two edge cases mentioned in
src/resourceStatus.ts: a workload with zero desired replicas and a LoadBalancer
Service that is already ready. Add focused cases in getResourceStatusSummary
tests to assert the correct label and variant for a 0/0-replica state and for a
ready LoadBalancer Service, using the existing getResourceStatusSummary and
isInformativeStatusLabel helpers as anchors.
src/crStatus.ts (1)

1-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Circular module dependency between crStatus.ts and resourceStatus.ts.

crStatus.ts imports the StatusSummary type from ./resourceStatus, while resourceStatus.ts imports getGenericResourceStatus/variantForPhase (values) from ./crStatus (line 3 there). This is a real circular import between the two modules. If the build toolchain uses a single-file transpiler (e.g., Babel/isolatedModules) that can't elide type-only imports without import type, this becomes a genuine circular require, which is fragile even though today's top-level code doesn't invoke functions during module init.

♻️ Suggested fix
-import { StatusSummary } from './resourceStatus';
+import type { StatusSummary } from './resourceStatus';
🤖 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/crStatus.ts` around lines 1 - 3, The import in crStatus.ts creates a
circular dependency with resourceStatus.ts because StatusSummary is only used as
a type while resourceStatus.ts already depends on values from crStatus.ts.
Update the crStatus.ts import to be type-only and keep the
crStatus/getGenericResourceStatus/variantForPhase split intact so the modules no
longer form a runtime require cycle. Use the existing StatusSummary reference in
crStatus.ts and the value imports in resourceStatus.ts to verify the dependency
is broken without changing behavior.
unit-tests/crStatus.test.ts (1)

1-64: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

LGTM! Tests correctly exercise top-level phase precedence, standard Ready conditions, and OLM-style phase conditions. Consider adding a case with both Available: True and Degraded: True conditions to lock in the priority-order fix suggested in src/crStatus.ts.

🤖 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 `@unit-tests/crStatus.test.ts` around lines 1 - 64, Add a test in
getGenericResourceStatus coverage for the mixed-condition case where both
Available: True and Degraded: True are present, so the priority order change in
getGenericResourceStatus is locked in. Extend crStatus.test.ts by asserting the
expected label/variant for that scenario, using the existing
getGenericResourceStatus helper and matching the same style as the current Ready
and phase-condition tests.
🤖 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 `@scripts/mock-ols-server.mjs`:
- Around line 1-52: The mock server script uses Node globals like process and
Buffer, but the lint config for scripts/**/*.mjs does not declare a Node
environment, causing no-undef failures. Update the ESLint configuration to apply
a Node globals/env override for this script group so the mock server entrypoint
(mock-ols-server.mjs) is linted with process and Buffer recognized, without
changing the runtime code.

In `@src/components/GeneralPage.tsx`:
- Around line 174-183: The `messageSources` hook is unnecessarily tied to
`modelsLoaded` even though it only uses `entry.references` and does not depend
on `k8sModels`. In `GeneralPage`, split the shared `enabled` logic so
`useMessageSources` only waits on the AI entry/streaming/error checks, while
`useLinkedResourceMarkdown` keeps the `modelsLoaded` requirement. Use the
existing `messageSources` and `linkedResourceMarkdown` calls to decouple the
conditions cleanly.

In `@src/components/InlineLinkedResource.tsx`:
- Around line 33-48: The inline resource link in InlineLinkedResource should not
render as an active-looking link when buildResourceConsolePath produces an empty
value. Update the Button in InlineLinkedResource to reflect the non-navigable
state when path is falsy, for example by using an accessibility-disabled state
such as isAriaDisabled and/or preventing link styling, while keeping
navigate(path) only for valid paths. Ensure the behavior is handled in the same
component that computes path and renders ResourceIcon and the resource name.

In `@src/crStatus.ts`:
- Around line 133-167: The standard condition selection in
getStandardConditionStatus is masking Degraded=True by returning on
Ready/Available/Progressing first. Update the priority handling in
getStandardConditionStatus so Degraded and Failure are checked before the other
standard condition types, keeping the existing special-case variant logic
intact; this ensures a bad rollout isn’t reported as success when Available or
Progressing is also present.

In `@src/hooks/useConsoleNavigation.ts`:
- Around line 15-19: The fallback navigation in useConsoleNavigation’s navigate
handler is not fully guarded because navigateToConsolePath(path) can still throw
inside the outer catch. Update the try/catch around navigate(path) so the
fallback call has its own try/catch, or otherwise swallow errors from
navigateToConsolePath, and keep the behavior fail-closed without leaking
exceptions.

In `@src/linkedResources.ts`:
- Around line 17-49: The prioritization logic in prioritizeLinkedResources is
using only ref.name.toLowerCase() for both byName and used, which causes
distinct resources with the same name to collapse or be skipped. Update the
lookup and deduping to use each ResourceRef’s full identity (for example, name
plus kind/namespace or whatever unique fields exist on ResourceRef) when
building the Map and tracking used entries, so same-named but different
resources can all be preserved and only exact duplicates are reordered away.

In `@src/resourceRefs.ts`:
- Around line 249-261: The fallback in extractRefFromObject is too strict: it
only returns a ResourceRef when the item already has kind, so
extractRefsFromListDocument never gets to use the list document’s defaultKind.
Update extractRefFromObject (and its callers in extractRefsFromListDocument) so
items with metadata.name but no kind can still be converted using the parsed
list kind as the fallback, while preserving the existing namespace handling.

In `@src/resourceStatus.ts`:
- Around line 115-130: The `workloadReplicaStatus` helper is treating
intentionally scaled-to-0 workloads as an error state. Update the status logic
so that when `total === 0` it returns a neutral/non-error variant instead of
falling through to `danger`, while keeping the existing success and warning
behavior for nonzero replica counts. Use the `workloadReplicaStatus` symbol to
locate the conditional branches and adjust the `label`/`variant` mapping
accordingly.
- Around line 246-255: The Service status mapping is being shadowed by the
generic “ends with ready” rule, causing LoadBalancer services to display the
wrong state. Update the matching order in linkedResourceStatusDisplay so the
exact label check for “LoadBalancer ready” runs before the label.endsWith('
ready') branch, while keeping the label generated in resourceStatus.ts
unchanged.

In `@start-console.sh`:
- Around line 50-59: The token-minting path in start-console.sh is auto-creating
a ServiceAccount and cluster-admin ClusterRoleBinding without an explicit safety
check. Update the logic around the kubectl serviceaccount, clusterrolebinding,
and create token commands to require an opt-in guard (for example an env var
like MOCK_ALLOW_DEV_TOKEN_MINT=1) before provisioning anything, and otherwise
skip or fail with a clear message. Keep the existing flow for the dev-token
case, but make it only run when the explicit opt-in is present.

---

Nitpick comments:
In `@scripts/mock-ols-server.mjs`:
- Line 973: The file has broad formatter/lint drift and an unused destructured
value in the stream setup. Run the project formatter/eslint fix on
scripts/mock-ols-server.mjs to resolve the reported prettier/prettier issues,
remove the unused conversationId from the buildStreamBody(query) destructure,
and adjust the nearby lowercase comment so it matches the file’s style. Use the
buildStreamBody and query-related code around the stream handler to locate the
cleanup.

In `@src/components/InlineLinkedResource.tsx`:
- Around line 49-55: The key on LinkedResourceStatus is ineffective because this
conditional render is not part of a list, so React will ignore it. Remove the
key from InlineLinkedResource and, if remounting on resourceRef changes is
actually needed, move the identity change to the parent conditional or derive it
through a different prop-driven render path using
shouldShowLinkedResourceStatus, LinkedResourceStatus, and resourceRefKey as the
relevant symbols.

In `@src/components/LinkedResourceStatus.tsx`:
- Around line 21-46: The loading condition in LinkedResourceStatus is redundant
because the earlier null return already covers the case where loaded is true and
the resource does not match. Simplify the conditional after the loadError check
to only test loaded, keeping the existing behavior intact while making the logic
in LinkedResourceStatus clearer.

In `@src/crStatus.ts`:
- Around line 1-3: The import in crStatus.ts creates a circular dependency with
resourceStatus.ts because StatusSummary is only used as a type while
resourceStatus.ts already depends on values from crStatus.ts. Update the
crStatus.ts import to be type-only and keep the
crStatus/getGenericResourceStatus/variantForPhase split intact so the modules no
longer form a runtime require cycle. Use the existing StatusSummary reference in
crStatus.ts and the value imports in resourceStatus.ts to verify the dependency
is broken without changing behavior.

In `@src/hooks/useMessageSources.tsx`:
- Around line 7-14: The isURL helper currently treats any URL with a protocol
and host as valid, which can let unsafe schemes through and mark them as
external links. Update isURL in useMessageSources.tsx to explicitly allow only
http: and https: when validating the parsed URL, and keep the existing URL
parsing/error handling so doc_url values from message sources are only rendered
as clickable links for safe web protocols.

In `@src/linkedResources.ts`:
- Line 1: The import in linkedResources.ts needs Prettier-compliant formatting
because the current single-line multi-import is flagged by static analysis.
Reformat the existing import from pageContext to match the project’s multiline
import style, keeping the same symbols getModelKindName, K8sModelRef,
resolveRefModelKey, and resolveRefModelKeyOrKind but spreading them across lines
as needed.
- Around line 112-120: getLinkedResourceOverflow is doing the same
linkable-resource extraction twice by calling extractLinkableResourceRefs and
then extractLinkedResources, which re-runs the same parsing/prioritization work.
Update getLinkedResourceOverflow to compute the linked resources once and derive
both shown and total from that shared result, or otherwise reuse the single
extractLinkableResourceRefs output instead of invoking the pipeline again. Keep
the fix localized to getLinkedResourceOverflow and the linked resource helpers
it calls.

In `@src/linkedResourceWatch.ts`:
- Around line 42-59: `matchesResourceRef` only checks name and namespace, so it
can treat a stale object from the wrong kind as a match. Update
`matchesResourceRef` in `linkedResourceWatch` to also compare the resource kind
against `resourceRef` (or the derived model kind/apiVersion from the ref) before
returning true, while keeping the existing name/namespace checks intact.

In `@src/resourceRefs.ts`:
- Line 114: The K8S_NODE_NAME_RE regex is duplicated in resourceRefs and
resourceListParsing, so update the duplicated constant to use a single shared
definition instead of two copies. Export K8S_NODE_NAME_RE from
resourceListParsing and import it into resourceRefs, then remove the local
declaration so both ResourceRefs and ResourceListParsing rely on the same source
of truth.

In `@start-console.sh`:
- Around line 64-78: The preflight checks in start-console.sh are validating
both oc and kubectl independently, even though resolve_api_server and
resolve_bearer_token only use one tool at runtime. Update the startup checks to
mirror that selection logic: determine the preferred CLI once (oc first,
otherwise kubectl), then run only the matching login/API reachability validation
for that chosen command. Keep the existing error handling and messages aligned
with the selected tool so machines with both CLIs installed do not fail due to
the unused one.

In `@unit-tests/crStatus.test.ts`:
- Around line 1-64: Add a test in getGenericResourceStatus coverage for the
mixed-condition case where both Available: True and Degraded: True are present,
so the priority order change in getGenericResourceStatus is locked in. Extend
crStatus.test.ts by asserting the expected label/variant for that scenario,
using the existing getGenericResourceStatus helper and matching the same style
as the current Ready and phase-condition tests.

In `@unit-tests/linkedResourceWatch.test.ts`:
- Around line 33-53: Add a test in matchesResourceRef coverage to verify kind
mismatches are rejected: extend the linkedResourceWatch.test.ts suite with a
case where the resource name/namespace matches but the resource kind differs
from the ref, and assert matchesResourceRef returns false. Use the
matchesResourceRef helper and the existing Namespace-style cases as the
reference point so the new test clearly exercises the kind check added in
linkedResourceWatch.ts.

In `@unit-tests/resourceStatus.test.ts`:
- Around line 1-211: The resource status tests are missing coverage for two edge
cases mentioned in src/resourceStatus.ts: a workload with zero desired replicas
and a LoadBalancer Service that is already ready. Add focused cases in
getResourceStatusSummary tests to assert the correct label and variant for a
0/0-replica state and for a ready LoadBalancer Service, using the existing
getResourceStatusSummary and isInformativeStatusLabel helpers as anchors.
🪄 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: Enterprise

Run ID: 798c07ca-e8ac-45a9-8285-de5d4e633ecf

📥 Commits

Reviewing files that changed from the base of the PR and between 2d7e7a6 and cebd9ed.

📒 Files selected for processing (35)
  • README.md
  • locales/en/plugin__lightspeed-console-plugin.json
  • package.json
  • scripts/mock-ols-server.mjs
  • src/components/GeneralPage.tsx
  • src/components/InlineLinkedResource.tsx
  • src/components/LinkedResourceStatus.tsx
  • src/components/ResourceIcon.tsx
  • src/components/linked-resources.css
  • src/consoleNavigation.ts
  • src/crStatus.ts
  • src/hooks/useConsoleNavigation.ts
  • src/hooks/useLinkedResourceMarkdown.tsx
  • src/hooks/useMessageSources.tsx
  • src/linkedResourceStatusDisplay.ts
  • src/linkedResourceText.ts
  • src/linkedResourceWatch.ts
  • src/linkedResources.ts
  • src/pageContext.ts
  • src/resourceListParsing.ts
  • src/resourceRefs.ts
  • src/resourceStatus.ts
  • start-console.sh
  • unit-tests/consoleNavigation.test.ts
  • unit-tests/crStatus.test.ts
  • unit-tests/fixtures/k8sModels.ts
  • unit-tests/linkedResourceStatusDisplay.test.ts
  • unit-tests/linkedResourceText.test.ts
  • unit-tests/linkedResourceWatch.test.ts
  • unit-tests/linkedResources.test.ts
  • unit-tests/pageContext.test.ts
  • unit-tests/resourceListParsing.test.ts
  • unit-tests/resourceRefs.test.ts
  • unit-tests/resourceStatus.test.ts
  • webpack.config.ts

Comment thread scripts/mock-ols-server.mjs Outdated
Comment thread src/components/GeneralPage.tsx
Comment thread src/components/InlineLinkedResource.tsx
Comment thread src/crStatus.ts
Comment thread src/hooks/useConsoleNavigation.ts
Comment thread src/linkedResources.ts
Comment thread src/resourceRefs.ts Outdated
Comment thread src/resourceStatus.ts
Comment thread src/resourceStatus.ts
Comment thread start-console.sh Outdated
@jpinsonneau

Copy link
Copy Markdown
Author

/retest-failed

@jpinsonneau

Copy link
Copy Markdown
Author

/retest-failed

Seems like konflux is failing to lint with StepOOM. It's passing locally. Let me know if you need extra changes or feel free to update here directly 👌

Dev-only mock server, start-console-kind, and related README/start-console
changes live on the mock-ols-server branch for a separate PR.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant