Skip to content

ci: run dynamic-plugin e2e against RHDH on oinc - #348

Open
jasonmadigan wants to merge 6 commits into
Kuadrant:mainfrom
jasonmadigan:279-e2e-dynamic-plugin
Open

ci: run dynamic-plugin e2e against RHDH on oinc#348
jasonmadigan wants to merge 6 commits into
Kuadrant:mainfrom
jasonmadigan:279-e2e-dynamic-plugin

Conversation

@jasonmadigan

@jasonmadigan jasonmadigan commented Jul 17, 2026

Copy link
Copy Markdown
Member

Summary

Closes #279.

Adds an opt-in path for testing the Kuadrant plugins as RHDH dynamic plugins:

  • The existing static Backstage E2E job remains the default required PR path.
  • E2E (dynamic plugins) is workflow_dispatch only.
  • The path exports both plugins, bakes them into RHDH, starts an oinc cluster with Kuadrant, deploys Dex and RHDH, and runs the full Playwright suite.
  • Local and oinc environments use the same Dex personas and RBAC policy.
  • The shared RHDH ClusterRole has one source of truth.
  • Versions and image coordinates can be overridden through Make variables.

The PR also includes fixes exercised by the dynamic environment: API-key annotation conditions, Kubernetes error propagation, live-backend E2E coverage, repeatable test state, and the deprecated MUI multiline field usage.

Local use

# Build and leave RHDH running for manual testing
make dynamic-up

# Run or repeat the E2E suite
make e2e-deps e2e-specs

# Remove the cluster
make teardown

# One-shot build, test, and teardown
make e2e-dynamic

PLAYWRIGHT_ARGS is forwarded by make e2e-specs for focused or headed runs.

Verification

  • Fresh local make e2e-dynamic completed the build, deployment, full suite, and teardown successfully: 84 passed and one passed on retry.
  • A repeat full-suite run passed 85/85.
  • Backend provider/router suites: 50 tests passed.
  • TypeScript, lint, formatting, ShellCheck, actionlint, YAML, and Helm overlay checks passed.

The cold-run retry is an upstream developer-portal-controller v0.2.1 auto-approval ordering race; it is not a plugin or RHDH failure.

The manual workflow becomes dispatchable once its workflow file exists on the default branch.

Summary by CodeRabbit

  • New Features
    • Added a manual dynamic-plugin end-to-end testing workflow, with local commands to build, start, run specs, and tear down.
    • API key UI elements are shown only when API-key authentication is detected (not for OIDC-only products).
    • Expanded Dex-based quick-login usage to improve end-to-end test coverage.
  • Bug Fixes
    • Improved backend error handling for missing resources, validation issues, throttling, and forbidden cases, while preventing sensitive RBAC/service-account details from leaking.
  • Documentation
    • Updated CI and E2E guidance for dynamic plugins.
  • UI
    • Multiline description/use-case fields can now grow beyond their initial height.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds dynamic-plugin RHDH E2E infrastructure, oinc/Dex cluster setup, structured Kubernetes error handling, Playwright reliability improvements, API-key annotation gating, RBAC updates, documentation, and multiline input sizing changes.

Changes

Dynamic RHDH E2E

Layer / File(s) Summary
Cluster and CI workflow
Makefile, .github/workflows/*, oinc/..., e2e-tests/rhdh/*, kuadrant-dev-setup/rbac/*
Adds commands and manifests to build dynamic plugins, provision RHDH with Dex, run Playwright tests, collect diagnostics, and tear down the environment.
Testing guidance
CLAUDE.md, docs/ci.md, docs/e2e-testing.md, docs/oinc.md, docs/rbac-permissions.md
Documents dynamic testing commands, CI behaviour, authentication personas, oinc setup, and RBAC configuration.

Backend behaviour

Layer / File(s) Summary
Kubernetes error propagation
plugins/kuadrant-backend/src/k8s-client.ts, plugins/kuadrant-backend/src/router.ts, plugins/kuadrant-backend/src/router.test.ts
Adds structured Kubernetes errors and maps recognised failures to HTTP responses across backend routes.
API-key annotation gating
plugins/kuadrant-backend/src/providers/*, docs/kuadrant-resources.md
Emits kuadrant.io/auth-apikey only when an API-key authentication scheme is discovered, with Jest coverage and documentation.

E2E and UI validation

Layer / File(s) Summary
Playwright reliability
e2e-tests/playwright/fixtures/*, e2e-tests/playwright/utils/*, e2e-tests/playwright/e2e/*
Adds runtime failure guards, deterministic selection/table helpers, Dex authentication, live-backend coverage, and strengthened permission and lifecycle assertions.
Multiline inputs
plugins/kuadrant/src/components/*Dialog/*
Changes dialog text fields to use minimum row heights.

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

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant Makefile
  participant Oinc
  participant RHDH
  participant Playwright
  GitHubActions->>Makefile: make dynamic-up
  Makefile->>Oinc: provision cluster and Dex
  Makefile->>RHDH: build and install dynamic plugins
  GitHubActions->>Makefile: make e2e-specs
  Makefile->>Playwright: run test suite
  GitHubActions->>Makefile: make teardown
Loading

Possibly related PRs

Suggested reviewers: r-lawton, eguzki

Poem

A rabbit watched the plugins hop,
Into RHDH’s testing shop.
Dex lit the login lantern bright,
While guards caught errors overnight.
“Run the checks, then clean the floor!”
And fluffy paws approved the door.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% 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
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: running dynamic-plugin E2E tests on RHDH via oinc.
Linked Issues check ✅ Passed The workflow and supporting setup add dynamic-plugin Playwright E2E runs on RHDH with oinc, which satisfies issue #279.
Out of Scope Changes check ✅ Passed The extra docs, test, RBAC, and backend fixes all support the dynamic E2E path, with no obvious unrelated changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
e2e-tests/rhdh/Dockerfile

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

.github/workflows/ci.yml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

.github/workflows/e2e-dynamic.yml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

  • 3 others

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.

@jasonmadigan

jasonmadigan commented Jul 17, 2026

Copy link
Copy Markdown
Member Author

TODO: rhdh addon for oinc should slim this down considerably.
done

@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 (3)
.github/workflows/e2e-dynamic.yml (1)

30-31: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Disable credential persistence during checkout.

To improve the security posture, it is recommended to set persist-credentials: false when checking out the repository, unless the workflow explicitly needs to push changes back to the remote. This prevents the GITHUB_TOKEN from being persisted in the local Git configuration.

🛡️ Proposed fix
       - name: Checkout code
         uses: actions/checkout@v4
+        with:
+          persist-credentials: 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 @.github/workflows/e2e-dynamic.yml around lines 30 - 31, Update the
actions/checkout@v4 step to set persist-credentials to false, ensuring the
workflow does not retain the GITHUB_TOKEN in the local Git configuration.

Source: Linters/SAST tools

oinc/manifests/dex.yaml (1)

35-38: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Consider making the Dex root filesystem read-only.

The container already drops all capabilities and disables privilege escalation; adding readOnlyRootFilesystem: true would complete that hardening (flagged by Trivy KSV-0014). Given in-memory storage is documented, this is likely safe, but worth confirming Dex has no other write path (e.g. /tmp) before adding it — mount an emptyDir at that path if it does.

🔒️ Proposed hardening
           securityContext:
             allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
             capabilities:
               drop: ["ALL"]
🤖 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 `@oinc/manifests/dex.yaml` around lines 35 - 38, Update the Dex container
securityContext near allowPrivilegeEscalation and capabilities to set
readOnlyRootFilesystem: true. Verify Dex’s runtime write paths, especially /tmp,
and add an emptyDir mount for any required writable path while preserving the
existing hardening settings.

Source: Linters/SAST tools

oinc/setup-rhdh.sh (1)

99-105: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Validate npm integrity hashes before using them.

If npm view succeeds but returns an empty string (e.g. version not yet published, or dist.integrity missing), FRONTEND_HASH/BACKEND_HASH end up empty and silently produce an integrity: "" entry in the generated overlay — this only surfaces later as an opaque RHDH plugin-load failure rather than a clear script error.

🛡️ Proposed fix
   FRONTEND_HASH=$(npm view "${FRONTEND_PKG}" dist.integrity)
   BACKEND_HASH=$(npm view "${BACKEND_PKG}" dist.integrity)
+  if [ -z "${FRONTEND_HASH}" ] || [ -z "${BACKEND_HASH}" ]; then
+    log "error: failed to resolve npm package integrity hashes"
+    exit 1
+  fi
   log "frontend: ${FRONTEND_HASH}"
🤖 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 `@oinc/setup-rhdh.sh` around lines 99 - 105, Validate FRONTEND_HASH and
BACKEND_HASH immediately after the npm view calls in the PLUGIN_SOURCE=npm
branch, and fail with a clear error if either value is empty before logging or
generating the overlay. Preserve the existing successful hash flow when both
integrity values are present.
🤖 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 `@e2e-tests/playwright/e2e/kuadrant-happy-path.spec.ts`:
- Around line 85-92: Update the cleanup flow around context.close so the browser
context is always closed in a finally block, including when product cleanup
fails. Preserve the existing loud error logging, but rethrow the cleanup error
after logging so the test cannot pass while cleanup is incomplete.
- Around line 313-329: Track whether the Search textbox was found and filled in
the existing search flow. Only run the empty-state message assertion when
filtering occurred; when Search is absent, assert that the table rendered
instead, while preserving the scoped zero-row assertion for owner1’s API.

In `@e2e-tests/playwright/e2e/kuadrant-request-access.spec.ts`:
- Around line 471-480: Update the request route mock in the kuadrant access test
to return HTTP 422 and match the new Kubernetes mapper’s field-level error
response structure, replacing the legacy 500/raw-client payload while preserving
the invalid email scenario.

In `@e2e-tests/playwright/fixtures/test.ts`:
- Around line 19-23: Update the network failure watcher in the Playwright
fixture to register a requestfailed handler alongside the existing
response-status check. Record transport-level failures in failures, including
the failed request details, so DNS, connection, and reset errors are captured
even when no 5xx response exists; preserve the existing response handling.

In `@e2e-tests/playwright/utils/kuadrant-helpers.ts`:
- Around line 304-315: Update seedPendingApiKeyRequest to create its manual
browser context with the project use options, including baseURL and
ignoreHTTPSErrors, before calling dexQuickLogin. Preserve the existing page
setup, API key request, and context cleanup flow.

In `@kuadrant-dev-setup/rbac/rhdh-cluster-role.yaml`:
- Around line 27-32: Replace the cluster-wide secrets permissions in the
ClusterRole with namespace-scoped access, using a Role for each demo/target
namespace or resourceNames restrictions when API-key secret names are
predictable. Preserve only the get, create, and delete permissions required by
the API-key workflow, and leave the namespaces permissions unchanged.

In `@oinc/setup-cluster.sh`:
- Around line 47-54: Update the oinc create invocation in the cluster setup flow
to use only the supported --addons syntax for v0.3.1, removing
--kuadrant-devportal, --metallb-address-pool auto, and --gateway-api-gateway.
Preserve the requested addon installation through the supported addon install
flow after cluster creation, and keep the existing diagnostic and exit handling
on failure.

In `@plugins/kuadrant-backend/src/router.ts`:
- Around line 1816-1817: Update the inner catch around getSecret in the API key
secret retrieval flow so it handles only status 404 as “secret not found”;
rethrow 403, 429, 5xx, and all other failures to let sendKubernetesError map
them. Preserve the existing fallback response for genuinely missing secrets.
- Around line 153-165: Update the status handling in
plugins/kuadrant-backend/src/router.ts lines 153-165 to treat upstream status
503 like the existing 429 path: return HTTP 503 with the generic unavailable
message and set Retry-After from retryAfterSeconds when it is a positive number.
Update the corresponding test in plugins/kuadrant-backend/src/router.test.ts
lines 1634-1642 to expect 503 and cover the optional Retry-After header.
- Around line 470-475: Replace raw errorMessage responses in the fallback
branches with generic, operation-specific messages: API-product creation at
plugins/kuadrant-backend/src/router.ts lines 470-475, API-product update at
lines 754-756, Secret creation at lines 898-900, Secret deletion at lines
930-932, and API-key request creation at lines 1028-1033. Preserve
sendKubernetesError handling while ensuring these declined-status fallbacks
never expose K8sApiError.message.

---

Nitpick comments:
In @.github/workflows/e2e-dynamic.yml:
- Around line 30-31: Update the actions/checkout@v4 step to set
persist-credentials to false, ensuring the workflow does not retain the
GITHUB_TOKEN in the local Git configuration.

In `@oinc/manifests/dex.yaml`:
- Around line 35-38: Update the Dex container securityContext near
allowPrivilegeEscalation and capabilities to set readOnlyRootFilesystem: true.
Verify Dex’s runtime write paths, especially /tmp, and add an emptyDir mount for
any required writable path while preserving the existing hardening settings.

In `@oinc/setup-rhdh.sh`:
- Around line 99-105: Validate FRONTEND_HASH and BACKEND_HASH immediately after
the npm view calls in the PLUGIN_SOURCE=npm branch, and fail with a clear error
if either value is empty before logging or generating the overlay. Preserve the
existing successful hash flow when both integrity values are present.
🪄 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: Pro

Run ID: 8bbc71ba-f324-4c22-a04d-6f4893c34e44

📥 Commits

Reviewing files that changed from the base of the PR and between fb66dce and 5565d57.

📒 Files selected for processing (45)
  • .dockerignore
  • .github/workflows/ci.yml
  • .github/workflows/e2e-dynamic.yml
  • CLAUDE.md
  • Makefile
  • docs/ci.md
  • docs/e2e-testing.md
  • docs/kuadrant-resources.md
  • docs/oinc.md
  • docs/rbac-permissions.md
  • e2e-tests/playwright/e2e/kuadrant-auth-schemes.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-happy-path.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-live-backend.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-permissions-matrix.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-plugin.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-request-access.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-skeleton-loaders.spec.ts
  • e2e-tests/playwright/e2e/smoke-test.spec.ts
  • e2e-tests/playwright/fixtures/test.ts
  • e2e-tests/playwright/utils/kuadrant-helpers.ts
  • e2e-tests/rhdh/Dockerfile
  • e2e-tests/rhdh/wait-for-catalog.sh
  • kuadrant-dev-setup/Makefile
  • kuadrant-dev-setup/README.md
  • kuadrant-dev-setup/dex/config.yaml
  • kuadrant-dev-setup/rbac/rhdh-cluster-role.yaml
  • kuadrant-dev-setup/rbac/rhdh-rbac.yaml
  • oinc/lib.sh
  • oinc/manifests/dex.yaml
  • oinc/manifests/rhdh-sa.yaml
  • oinc/setup-cluster.sh
  • oinc/setup-dex.sh
  • oinc/setup-rhdh.sh
  • oinc/setup.sh
  • oinc/teardown.sh
  • plugins/kuadrant-backend/src/k8s-client.ts
  • plugins/kuadrant-backend/src/providers/APIProductEntityProvider.test.ts
  • plugins/kuadrant-backend/src/providers/APIProductEntityProvider.ts
  • plugins/kuadrant-backend/src/router.test.ts
  • plugins/kuadrant-backend/src/router.ts
  • plugins/kuadrant/src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx
  • plugins/kuadrant/src/components/EditAPIKeyDialog/EditAPIKeyDialog.tsx
  • plugins/kuadrant/src/components/EditAPIProductDialog/EditAPIProductDialog.tsx
  • plugins/kuadrant/src/components/RequestAccessDialog/RequestAccessDialog.tsx
  • plugins/kuadrant/src/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.tsx
💤 Files with no reviewable changes (3)
  • oinc/lib.sh
  • kuadrant-dev-setup/rbac/rhdh-rbac.yaml
  • oinc/manifests/rhdh-sa.yaml

Comment thread e2e-tests/playwright/e2e/kuadrant-happy-path.spec.ts Outdated
Comment thread e2e-tests/playwright/e2e/kuadrant-happy-path.spec.ts
Comment thread e2e-tests/playwright/e2e/kuadrant-request-access.spec.ts
Comment thread e2e-tests/playwright/fixtures/test.ts
Comment thread e2e-tests/playwright/utils/kuadrant-helpers.ts
Comment thread kuadrant-dev-setup/rbac/rhdh-cluster-role.yaml
Comment thread oinc/setup-cluster.sh
Comment thread plugins/kuadrant-backend/src/router.ts
Comment thread plugins/kuadrant-backend/src/router.ts Outdated
Comment thread plugins/kuadrant-backend/src/router.ts
@jasonmadigan
jasonmadigan force-pushed the 279-e2e-dynamic-plugin branch from 5565d57 to b4be492 Compare July 21, 2026 17:02

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

🧹 Nitpick comments (3)
.github/workflows/e2e-dynamic.yml (1)

30-31: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Disable credential persistence in checkout.

As a security best practice, consider setting persist-credentials: false when checking out the code, as this workflow does not need to push changes back to the repository.

🛠️ Proposed fix
       - name: Checkout code
         uses: actions/checkout@v4
+        with:
+          persist-credentials: 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 @.github/workflows/e2e-dynamic.yml around lines 30 - 31, Update the
actions/checkout@v4 step to set persist-credentials to false, leaving the rest
of the checkout configuration unchanged.
Makefile (1)

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

Accommodate macOS environments with GNU grep.

Based on learnings, GNU grep is required on macOS instead of the BSD implementation. You might consider adding a fallback to use ggrep if it is available, preventing potential compatibility issues for developers using macOS.

🛠️ Proposed fix
-	`@version`=$$(oinc version 2>/dev/null | grep -o 'v[0-9][^[:space:]]*' | head -1); \
+	`@GREP`=$$(command -v ggrep >/dev/null 2>&1 && echo ggrep || echo grep); \
+	version=$$(oinc version 2>/dev/null | $$GREP -o 'v[0-9][^[:space:]]*' | head -1); \
 	case "$$version" in \
🤖 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 `@Makefile` around lines 38 - 39, Update the version-detection command in the
Makefile to use GNU grep via ggrep when that executable is available, while
retaining grep as the fallback for environments where ggrep is unavailable.
Preserve the existing oinc version parsing and case handling.

Source: Learnings

oinc/setup-dex.sh (1)

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

Accommodate macOS environments with GNU sed.

Based on learnings, GNU sed is required on macOS instead of the BSD implementation. You may want to detect the environment and use gsed if available to prevent potential regular expression compatibility issues for developers using macOS.

🛠️ Proposed fix
-sed -E "s|^issuer:[[:space:]].*|issuer: ${DEX_URL}|" \
+SED=$(command -v gsed >/dev/null 2>&1 && echo gsed || echo sed)
+$SED -E "s|^issuer:[[:space:]].*|issuer: ${DEX_URL}|" \
   "${DEX_CONFIG}" >"${rendered_config}"
🤖 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 `@oinc/setup-dex.sh` around lines 25 - 26, Update the sed invocation in the
setup script to select GNU sed (`gsed`) when running on macOS, while retaining
the existing sed behavior elsewhere. Detect whether `gsed` is available and use
it for the issuer replacement performed by the rendered configuration
generation.

Source: Learnings

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

Nitpick comments:
In @.github/workflows/e2e-dynamic.yml:
- Around line 30-31: Update the actions/checkout@v4 step to set
persist-credentials to false, leaving the rest of the checkout configuration
unchanged.

In `@Makefile`:
- Around line 38-39: Update the version-detection command in the Makefile to use
GNU grep via ggrep when that executable is available, while retaining grep as
the fallback for environments where ggrep is unavailable. Preserve the existing
oinc version parsing and case handling.

In `@oinc/setup-dex.sh`:
- Around line 25-26: Update the sed invocation in the setup script to select GNU
sed (`gsed`) when running on macOS, while retaining the existing sed behavior
elsewhere. Detect whether `gsed` is available and use it for the issuer
replacement performed by the rendered configuration generation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 11e9335a-9140-462a-a60c-f522e92e84e8

📥 Commits

Reviewing files that changed from the base of the PR and between 5565d57 and b4be492.

📒 Files selected for processing (42)
  • .dockerignore
  • .github/workflows/ci.yml
  • .github/workflows/e2e-dynamic.yml
  • CLAUDE.md
  • Makefile
  • docs/ci.md
  • docs/e2e-testing.md
  • docs/oinc.md
  • docs/rbac-permissions.md
  • e2e-tests/playwright/e2e/kuadrant-auth-schemes.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-happy-path.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-live-backend.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-permissions-matrix.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-plugin.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-request-access.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-skeleton-loaders.spec.ts
  • e2e-tests/playwright/e2e/smoke-test.spec.ts
  • e2e-tests/playwright/fixtures/test.ts
  • e2e-tests/playwright/utils/kuadrant-helpers.ts
  • e2e-tests/rhdh/Dockerfile
  • e2e-tests/rhdh/wait-for-catalog.sh
  • kuadrant-dev-setup/Makefile
  • kuadrant-dev-setup/README.md
  • kuadrant-dev-setup/dex/config.yaml
  • kuadrant-dev-setup/rbac/rhdh-cluster-role.yaml
  • kuadrant-dev-setup/rbac/rhdh-rbac.yaml
  • oinc/lib.sh
  • oinc/manifests/dex.yaml
  • oinc/manifests/rhdh-sa.yaml
  • oinc/setup-cluster.sh
  • oinc/setup-dex.sh
  • oinc/setup-rhdh.sh
  • oinc/setup.sh
  • oinc/teardown.sh
  • plugins/kuadrant-backend/src/k8s-client.ts
  • plugins/kuadrant-backend/src/router.test.ts
  • plugins/kuadrant-backend/src/router.ts
  • plugins/kuadrant/src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx
  • plugins/kuadrant/src/components/EditAPIKeyDialog/EditAPIKeyDialog.tsx
  • plugins/kuadrant/src/components/EditAPIProductDialog/EditAPIProductDialog.tsx
  • plugins/kuadrant/src/components/RequestAccessDialog/RequestAccessDialog.tsx
  • plugins/kuadrant/src/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.tsx
💤 Files with no reviewable changes (3)
  • kuadrant-dev-setup/rbac/rhdh-rbac.yaml
  • oinc/manifests/rhdh-sa.yaml
  • oinc/lib.sh
🚧 Files skipped from review as they are similar to previous changes (23)
  • plugins/kuadrant/src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx
  • plugins/kuadrant/src/components/RequestAccessDialog/RequestAccessDialog.tsx
  • plugins/kuadrant/src/components/EditAPIKeyDialog/EditAPIKeyDialog.tsx
  • plugins/kuadrant/src/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.tsx
  • .github/workflows/ci.yml
  • kuadrant-dev-setup/Makefile
  • oinc/teardown.sh
  • plugins/kuadrant/src/components/EditAPIProductDialog/EditAPIProductDialog.tsx
  • e2e-tests/playwright/e2e/kuadrant-auth-schemes.spec.ts
  • kuadrant-dev-setup/README.md
  • e2e-tests/rhdh/wait-for-catalog.sh
  • e2e-tests/playwright/e2e/kuadrant-plugin.spec.ts
  • kuadrant-dev-setup/dex/config.yaml
  • e2e-tests/playwright/e2e/kuadrant-live-backend.spec.ts
  • docs/rbac-permissions.md
  • e2e-tests/playwright/utils/kuadrant-helpers.ts
  • CLAUDE.md
  • e2e-tests/playwright/fixtures/test.ts
  • plugins/kuadrant-backend/src/k8s-client.ts
  • e2e-tests/playwright/e2e/kuadrant-happy-path.spec.ts
  • oinc/setup-rhdh.sh
  • plugins/kuadrant-backend/src/router.ts
  • e2e-tests/playwright/e2e/kuadrant-permissions-matrix.spec.ts

RHDH's dynamic hasAnnotation condition checks key presence, so an annotation value of false still exposes the API Keys tab. Emit the annotation only for discovered API-key schemes and cover OIDC-only, mixed, and unresolved products.

Signed-off-by: Jason Madigan <jason@jasonmadigan.com>
Keep Kubernetes status details through the client boundary so request errors, conflicts, missing objects, validation failures, and throttling reach callers accurately. Treat service-account RBAC and missing-CRD failures as backend faults instead of blaming the signed-in user.

Signed-off-by: Jason Madigan <jason@jasonmadigan.com>
Run every Kuadrant spec through the same Dex personas, seed state instead of conditionally skipping assertions, and search paginated tables so repeated manual runs remain deterministic. Add live-backend coverage and fail tests on silent Kuadrant 5xx responses, page exceptions, and unexpected console errors.

Signed-off-by: Jason Madigan <jason@jasonmadigan.com>
Use minRows for multiline fields so MUI no longer emits the deprecated rows warning caught by the e2e runtime guard.

Signed-off-by: Jason Madigan <jason@jasonmadigan.com>
Keep the ClusterRole in one manifest and leave environment-specific service accounts and bindings in their own files. This gives the static and dynamic paths one permission set and includes the status, approval, request, and namespace access found while exercising the live backend.

Signed-off-by: Jason Madigan <jason@jasonmadigan.com>
Keep the existing static e2e job as the required PR path and add a workflow_dispatch-only RHDH path for the exported plugins. Share the build and cluster phases with local Make targets, run the full suite, pin Kuadrant 1.5.1 with an override, and keep manual environments up for inspection.

Use the existing Dex personas for every RHDH entry point, including yarn oinc:rhdh, while keeping the local Dex 2.45.1 pin direct. The baked and npm plugin modes now share the same RHDH configuration and canonical Kubernetes role.

Signed-off-by: Jason Madigan <jason@jasonmadigan.com>
@jasonmadigan
jasonmadigan force-pushed the 279-e2e-dynamic-plugin branch from b4be492 to 2ec783d Compare July 22, 2026 13:53

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

🧹 Nitpick comments (4)
.github/workflows/e2e-dynamic.yml (1)

30-31: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Disable persisted checkout credentials.

The job does not need Git credentials after checkout; avoid leaving the read token in the local Git config for repository-controlled build steps.

Proposed change
       - name: Checkout code
         uses: actions/checkout@v4
+        with:
+          persist-credentials: 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 @.github/workflows/e2e-dynamic.yml around lines 30 - 31, Update the
actions/checkout@v4 step to disable persisted Git credentials by setting its
persist-credentials option to false, while leaving the existing checkout
behavior unchanged.

Source: Linters/SAST tools

oinc/manifests/dex.yaml (1)

35-38: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Make Dex’s root filesystem read-only.

Dex only consumes the mounted configuration and template here; prevent writes outside explicitly mounted volumes.

Proposed change
           securityContext:
             allowPrivilegeEscalation: false
             capabilities:
               drop: ["ALL"]
+            readOnlyRootFilesystem: true
🤖 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 `@oinc/manifests/dex.yaml` around lines 35 - 38, Update Dex’s securityContext
in the dex manifest to set the root filesystem as read-only, while preserving
the existing privilege-escalation and capability restrictions.

Source: Linters/SAST tools

plugins/kuadrant-backend/src/router.ts (2)

1146-1204: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Inconsistent with the new structured status check.

The outer catch at Line 1200 now uses sendKubernetesError, but the inner catch (Lines 1170-1176, unchanged) still detects a missing consumer namespace via error.message?.includes('404') || error.statusCode === 404 — a fragile string-match that the new kubernetesStatus(error) helper was built to replace. A false-positive match (e.g. an unrelated error whose message happens to contain "404") would silently return an empty list instead of surfacing the real failure.

Consider swapping to kubernetesStatus(error) === 404 for consistency with the rest of this file's new error-mapping approach.

🤖 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 `@plugins/kuadrant-backend/src/router.ts` around lines 1146 - 1204, Replace the
fragile 404 detection in the inner catch of the /requests/my handler with
kubernetesStatus(error) === 404. Preserve the existing empty-items response for
a genuinely missing consumer namespace, and rethrow all other errors for the
outer error handling.

155-171: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate 429/503 handling.

The 429 and 503 branches are identical apart from the console.error text: both extract retryAfterSeconds, set the same Retry-After header, and return the same 503 JSON body. Worth extracting a small shared helper to avoid the two copies drifting apart later.

♻️ Proposed refactor
+  function sendTransientUnavailable(logPrefix: string, error: unknown): express.Response {
+    console.error(logPrefix, kubernetesMessage(error));
+    const retryAfter = kubernetesDetails(error)?.retryAfterSeconds;
+    if (typeof retryAfter === 'number' && retryAfter > 0) {
+      res.setHeader('Retry-After', String(retryAfter));
+    }
+    return res.status(503).json({ error: 'service temporarily unavailable' });
+  }
+
   if (status === 429) {
-    console.error('kubernetes is throttling this backend:', kubernetesMessage(error));
-    const retryAfter = kubernetesDetails(error)?.retryAfterSeconds;
-    if (typeof retryAfter === 'number' && retryAfter > 0) {
-      res.setHeader('Retry-After', String(retryAfter));
-    }
-    return res.status(503).json({ error: 'service temporarily unavailable' });
+    return sendTransientUnavailable('kubernetes is throttling this backend:', error);
   }

   if (status === 503) {
-    console.error('kubernetes is unavailable:', kubernetesMessage(error));
-    const retryAfter = kubernetesDetails(error)?.retryAfterSeconds;
-    if (typeof retryAfter === 'number' && retryAfter > 0) {
-      res.setHeader('Retry-After', String(retryAfter));
-    }
-    return res.status(503).json({ error: 'service temporarily unavailable' });
+    return sendTransientUnavailable('kubernetes is unavailable:', error);
   }
🤖 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 `@plugins/kuadrant-backend/src/router.ts` around lines 155 - 171, The 429 and
503 branches duplicate the same response handling. Extract the shared
retry-after header and 503 JSON response logic into a small helper, then have
both status branches retain only their distinct logging and delegate to that
helper.
🤖 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.

Nitpick comments:
In @.github/workflows/e2e-dynamic.yml:
- Around line 30-31: Update the actions/checkout@v4 step to disable persisted
Git credentials by setting its persist-credentials option to false, while
leaving the existing checkout behavior unchanged.

In `@oinc/manifests/dex.yaml`:
- Around line 35-38: Update Dex’s securityContext in the dex manifest to set the
root filesystem as read-only, while preserving the existing privilege-escalation
and capability restrictions.

In `@plugins/kuadrant-backend/src/router.ts`:
- Around line 1146-1204: Replace the fragile 404 detection in the inner catch of
the /requests/my handler with kubernetesStatus(error) === 404. Preserve the
existing empty-items response for a genuinely missing consumer namespace, and
rethrow all other errors for the outer error handling.
- Around line 155-171: The 429 and 503 branches duplicate the same response
handling. Extract the shared retry-after header and 503 JSON response logic into
a small helper, then have both status branches retain only their distinct
logging and delegate to that helper.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: abf81a0f-a6ea-45bb-9542-78a3580a6f3b

📥 Commits

Reviewing files that changed from the base of the PR and between b4be492 and 2ec783d.

📒 Files selected for processing (45)
  • .dockerignore
  • .github/workflows/ci.yml
  • .github/workflows/e2e-dynamic.yml
  • CLAUDE.md
  • Makefile
  • docs/ci.md
  • docs/e2e-testing.md
  • docs/kuadrant-resources.md
  • docs/oinc.md
  • docs/rbac-permissions.md
  • e2e-tests/playwright/e2e/kuadrant-auth-schemes.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-happy-path.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-live-backend.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-permissions-matrix.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-plugin.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-request-access.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-skeleton-loaders.spec.ts
  • e2e-tests/playwright/e2e/smoke-test.spec.ts
  • e2e-tests/playwright/fixtures/test.ts
  • e2e-tests/playwright/utils/kuadrant-helpers.ts
  • e2e-tests/rhdh/Dockerfile
  • e2e-tests/rhdh/wait-for-catalog.sh
  • kuadrant-dev-setup/Makefile
  • kuadrant-dev-setup/README.md
  • kuadrant-dev-setup/dex/config.yaml
  • kuadrant-dev-setup/rbac/rhdh-cluster-role.yaml
  • kuadrant-dev-setup/rbac/rhdh-rbac.yaml
  • oinc/lib.sh
  • oinc/manifests/dex.yaml
  • oinc/manifests/rhdh-sa.yaml
  • oinc/setup-cluster.sh
  • oinc/setup-dex.sh
  • oinc/setup-rhdh.sh
  • oinc/setup.sh
  • oinc/teardown.sh
  • plugins/kuadrant-backend/src/k8s-client.ts
  • plugins/kuadrant-backend/src/providers/APIProductEntityProvider.test.ts
  • plugins/kuadrant-backend/src/providers/APIProductEntityProvider.ts
  • plugins/kuadrant-backend/src/router.test.ts
  • plugins/kuadrant-backend/src/router.ts
  • plugins/kuadrant/src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx
  • plugins/kuadrant/src/components/EditAPIKeyDialog/EditAPIKeyDialog.tsx
  • plugins/kuadrant/src/components/EditAPIProductDialog/EditAPIProductDialog.tsx
  • plugins/kuadrant/src/components/RequestAccessDialog/RequestAccessDialog.tsx
  • plugins/kuadrant/src/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.tsx
💤 Files with no reviewable changes (3)
  • oinc/lib.sh
  • kuadrant-dev-setup/rbac/rhdh-rbac.yaml
  • oinc/manifests/rhdh-sa.yaml
🚧 Files skipped from review as they are similar to previous changes (32)
  • oinc/teardown.sh
  • plugins/kuadrant/src/components/EditAPIKeyDialog/EditAPIKeyDialog.tsx
  • e2e-tests/playwright/e2e/smoke-test.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-auth-schemes.spec.ts
  • kuadrant-dev-setup/dex/config.yaml
  • plugins/kuadrant/src/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.tsx
  • e2e-tests/playwright/e2e/kuadrant-live-backend.spec.ts
  • oinc/setup.sh
  • plugins/kuadrant/src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx
  • .dockerignore
  • e2e-tests/playwright/e2e/kuadrant-skeleton-loaders.spec.ts
  • plugins/kuadrant-backend/src/providers/APIProductEntityProvider.test.ts
  • docs/kuadrant-resources.md
  • plugins/kuadrant-backend/src/providers/APIProductEntityProvider.ts
  • kuadrant-dev-setup/README.md
  • plugins/kuadrant/src/components/RequestAccessDialog/RequestAccessDialog.tsx
  • e2e-tests/rhdh/wait-for-catalog.sh
  • kuadrant-dev-setup/Makefile
  • .github/workflows/ci.yml
  • plugins/kuadrant/src/components/EditAPIProductDialog/EditAPIProductDialog.tsx
  • docs/e2e-testing.md
  • e2e-tests/playwright/e2e/kuadrant-plugin.spec.ts
  • e2e-tests/playwright/fixtures/test.ts
  • e2e-tests/playwright/e2e/kuadrant-request-access.spec.ts
  • docs/rbac-permissions.md
  • oinc/setup-rhdh.sh
  • CLAUDE.md
  • plugins/kuadrant-backend/src/router.test.ts
  • plugins/kuadrant-backend/src/k8s-client.ts
  • e2e-tests/playwright/utils/kuadrant-helpers.ts
  • e2e-tests/playwright/e2e/kuadrant-happy-path.spec.ts
  • e2e-tests/playwright/e2e/kuadrant-permissions-matrix.spec.ts


// the queue pages at 20 rows, so narrow to the seeded api first -
// otherwise a fresh request can sit off the visible page.
await page.getByRole("textbox", { name: "Search" }).fill(owner2Api);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The approval-queue search fills at lines 364, 399, and 587 are missing the count() guard that narrowProductsTable uses. When the table is small enough not to render a search box, fill() will block until timeout.

// lines 364, 399, 587 — no guard:
await page.getByRole("textbox", { name: "Search" }).fill(owner2Api);

// narrowProductsTable does this:
const search = page.getByRole("textbox", { name: "Search" });
if (await search.count()) {
  await search.fill(text);
}

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.

Run e2e playwrite tests when on RHDH installing kuadrant as dynamic plugin

2 participants