feat(ci): add UI E2E tests on GKE#21421
Conversation
Add a Cypress UI E2E workflow that runs on GKE with 9 parallel shards. Triggered by the `e2e-ui-gke` label on PRs, or via workflow_dispatch. New files: - .github/workflows/ui-e2e.yaml: orchestrates setup-shards, provision-gke, gke-e2e (sharded Cypress), and cleanup-gke - .github/actions/deploy-stackrox: deploys StackRox via roxie with API token generation Modified: - .github/actions/create-gke-cluster: add auto-cleanup input (default true) so multi-job workflows can disable the post-step cleanup - .github/workflows/build.yaml: add ui-e2e job gated on e2e-ui-gke label - networkDeploymentSidebar test: use deploymentNode selector instead of fragile selectDeployment dropdown filter Partially generated by AI. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe PR adds a reusable UI E2E workflow that shards Cypress specs, provisions a GKE cluster, deploys StackRox, runs shard-parallel tests, and cleans up the cluster. It also wires the workflow into the build pipeline, adds a deploy-stackrox composite action, and updates one Cypress sidebar test. ChangesUI E2E provisioning and deployment
Sequence Diagram(s)sequenceDiagram
participant build_ui_e2e_job
participant ui_e2e_workflow
participant setup_shards_job
participant provision_gke_job
participant deploy_stackrox_action
participant gke_e2e_job
participant cleanup_gke_job
build_ui_e2e_job->>ui_e2e_workflow: calls reusable workflow with build-tag
ui_e2e_workflow->>setup_shards_job: discovers Cypress specs
setup_shards_job-->>ui_e2e_workflow: emits shard matrix JSON
ui_e2e_workflow->>provision_gke_job: provisions a GKE cluster
provision_gke_job->>deploy_stackrox_action: deploys StackRox with scanner v2
ui_e2e_workflow->>gke_e2e_job: runs shard-parallel Cypress tests
ui_e2e_workflow->>cleanup_gke_job: deletes the GKE cluster asynchronously
🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
.github/actions/deploy-stackrox/action.yaml (1)
97-114: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winPass action inputs through
env:instead of${{ }}interpolation in run scripts.
${{ inputs.cluster-name }},${{ inputs.tag }},${{ inputs.scanner }},${{ inputs.resources }}, and${{ inputs.exposure }}are expanded into the shell before execution (e.g. embedded inside theyqstring on Line 97). If any value ever contains shell metacharacters, this is a template-injection vector. The registry credentials already follow the safeenv:pattern (Lines 66-67); apply the same to the rest.🔒 Sketch
- name: Deploy StackRox shell: bash env: INPUT_REGISTRY_USERNAME: ${{ inputs.registry-username }} INPUT_REGISTRY_PASSWORD: ${{ inputs.registry-password }} + INPUT_CLUSTER_NAME: ${{ inputs.cluster-name }} + INPUT_TAG: ${{ inputs.tag }} + INPUT_SCANNER: ${{ inputs.scanner }} + INPUT_RESOURCES: ${{ inputs.resources }} + INPUT_EXPOSURE: ${{ inputs.exposure }}Then reference
"$INPUT_CLUSTER_NAME","$INPUT_TAG", etc. in the script.🤖 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/actions/deploy-stackrox/action.yaml around lines 97 - 114, Move the action inputs used in the deploy script to env variables instead of interpolating `${{ inputs.* }}` directly inside the run block. Update the `action.yaml` step that builds `/tmp/roxie-override.yaml` and calls `roxie deploy` to reference safe shell variables like `"$INPUT_CLUSTER_NAME"`, `"$INPUT_SCANNER"`, `"$INPUT_RESOURCES"`, `"$INPUT_EXPOSURE"`, and `"$INPUT_TAG"` rather than expanding inputs inline. Keep the existing logic in the same step, but read all input-derived values from `env:` so the `yq` and `roxie deploy` commands use quoted shell variables throughout.
🤖 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 @.github/actions/deploy-stackrox/action.yaml:
- Line 116: The current env export in the action is too brittle because the sed
cleanup in the step that writes to GITHUB_ENV strips quotes from all values and
cannot safely handle multiline entries. Update the export logic around the
roxie-env.sh processing so it preserves quoted content correctly and writes
multiline values using GITHUB_ENV heredoc syntax, or otherwise parse and emit
each variable explicitly in the deploy-stackrox action instead of relying on
global sed replacements.
In @.github/workflows/build.yaml:
- Around line 913-923: The `ui-e2e` caller job is using the default GitHub token
scope and `secrets: inherit`, which is too broad for this reusable workflow. Add
an explicit least-privilege `permissions:` block on the `ui-e2e` job in
`build.yaml`, and update the `uses: ./.github/workflows/ui-e2e.yaml` call to
pass only the named secrets that `ui-e2e.yaml` actually needs instead of
inheriting everything. Use the `ui-e2e` job and the reusable `ui-e2e.yaml`
workflow as the points to align the permissions and secret inputs.
In @.github/workflows/ui-e2e.yaml:
- Line 238: Avoid interpolating matrix-derived values directly in the shell
script for the Wait for shard-specific data step and the other referenced run
steps. In ui-e2e workflow, bind matrix.name and matrix.specs through env: on the
affected steps, then reference those environment variables in the script instead
of using ${{ matrix.name }} or ${{ matrix.specs }} inline. This applies to the
step using SHARD and the matching Run Cypress-related steps so the shell never
expands untrusted directory-name content directly.
- Around line 118-120: The `gke-zone` workflow output is reading `env.ZONE`, but
`ZONE` is only populated indirectly by `ci_export` in `scripts/ci/gke.sh` and
must be available before the job output is evaluated. Make sure the
`provision-gke` job step that runs `create-gke-cluster` executes before the
outputs are consumed, and verify the workflow passes the exported `ZONE` through
correctly so `gke-e2e` and `cleanup-gke` receive a non-empty zone. Use
`provision-gke`, `create-gke-cluster`, and `ci_export` to locate the relevant
places.
- Around line 27-31: Add a top-level permissions block to the ui-e2e workflow so
the default GITHUB_TOKEN scope is least-privilege; since the jobs only need
checkout, GCP auth, and artifact upload/download, set workflow-level permissions
to contents: read and override per-job only if a later step needs more access.
Place it alongside the existing defaults/jobs section so the workflow uses the
narrower token by default.
In
`@ui/apps/platform/cypress/integration/networkGraph/networkDeploymentSidebar.test.js`:
- Around line 23-29: The Cypress sidebar test is using substring-based selectors
that can pass on the wrong deployment, so tighten it to exact matching in the
networkDeploymentSidebar test. Update the assertions around
networkGraphSelectors.deploymentNode('sensor'),
networkGraphSelectors.drawerTitle, and networkGraphSelectors.drawerSubtitle so
they verify the intended deployment and subtitle exactly rather than relying on
:contains() behavior. This should make the sidebar flow fail unless the correct
sensor node and matching drawer content are selected.
---
Nitpick comments:
In @.github/actions/deploy-stackrox/action.yaml:
- Around line 97-114: Move the action inputs used in the deploy script to env
variables instead of interpolating `${{ inputs.* }}` directly inside the run
block. Update the `action.yaml` step that builds `/tmp/roxie-override.yaml` and
calls `roxie deploy` to reference safe shell variables like
`"$INPUT_CLUSTER_NAME"`, `"$INPUT_SCANNER"`, `"$INPUT_RESOURCES"`,
`"$INPUT_EXPOSURE"`, and `"$INPUT_TAG"` rather than expanding inputs inline.
Keep the existing logic in the same step, but read all input-derived values from
`env:` so the `yq` and `roxie deploy` commands use quoted shell variables
throughout.
🪄 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: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: fc2ddb24-3a6b-43b9-828e-532cf29cfd14
📒 Files selected for processing (5)
.github/actions/create-gke-cluster/action.yaml.github/actions/deploy-stackrox/action.yaml.github/workflows/build.yaml.github/workflows/ui-e2e.yamlui/apps/platform/cypress/integration/networkGraph/networkDeploymentSidebar.test.js
| --tag ${{ inputs.tag }} \ | ||
| $exposure_flag | ||
|
|
||
| sed "s/^export //; s/['\"]//g" /tmp/roxie-env.sh >> "$GITHUB_ENV" |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
sed-based env export is fragile.
s/['\"]//g strips every quote from values (not just wrapping quotes), and any multiline value would corrupt $GITHUB_ENV, which requires heredoc delimiters for multiline content. If roxie-env.sh only ever emits single-line, quote-free values this is safe; otherwise downstream steps will read truncated values.
🤖 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/actions/deploy-stackrox/action.yaml at line 116, The current env
export in the action is too brittle because the sed cleanup in the step that
writes to GITHUB_ENV strips quotes from all values and cannot safely handle
multiline entries. Update the export logic around the roxie-env.sh processing so
it preserves quoted content correctly and writes multiline values using
GITHUB_ENV heredoc syntax, or otherwise parse and emit each variable explicitly
in the deploy-stackrox action instead of relying on global sed replacements.
Source: Linters/SAST tools
| ui-e2e: | ||
| needs: | ||
| - define-job-matrix | ||
| - push-main-manifests | ||
| if: >- | ||
| !cancelled() && needs.push-main-manifests.result == 'success' && | ||
| contains(github.event.pull_request.labels.*.name, 'e2e-ui-gke') | ||
| uses: ./.github/workflows/ui-e2e.yaml | ||
| with: | ||
| tag: ${{ needs.define-job-matrix.outputs.build-tag }} | ||
| secrets: inherit |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Add an explicit least-privilege permissions: block and scope inherited secrets.
This caller job runs with the default token permissions and forwards every secret via secrets: inherit. The reusable ui-e2e.yaml only needs read access plus the specific GCP/Quay/bot secrets, so granting all of them broadens the blast radius unnecessarily. Add a minimal permissions: block here and prefer passing named secrets to the reusable workflow over inherit.
🔒 Suggestion
ui-e2e:
+ permissions:
+ contents: read
needs:
- define-job-matrix
- push-main-manifests🧰 Tools
🪛 zizmor (1.26.1)
[warning] 913-923: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block
(excessive-permissions)
[warning] 920-920: secrets unconditionally inherited by called workflow (secrets-inherit): this reusable workflow
(secrets-inherit)
🤖 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/build.yaml around lines 913 - 923, The `ui-e2e` caller job
is using the default GitHub token scope and `secrets: inherit`, which is too
broad for this reusable workflow. Add an explicit least-privilege `permissions:`
block on the `ui-e2e` job in `build.yaml`, and update the `uses:
./.github/workflows/ui-e2e.yaml` call to pass only the named secrets that
`ui-e2e.yaml` actually needs instead of inheriting everything. Use the `ui-e2e`
job and the reusable `ui-e2e.yaml` workflow as the points to align the
permissions and secret inputs.
Source: Linters/SAST tools
| defaults: | ||
| run: | ||
| shell: bash | ||
|
|
||
| jobs: |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Add a top-level least-privilege permissions: block.
None of the jobs declare permissions, so they all run with the default (broad) GITHUB_TOKEN scope. These jobs only check out code, auth to GCP, and up/download artifacts, so contents: read at the workflow level (overriding per-job where needed) is sufficient.
🔒 Suggestion
name: UI E2E
+
+permissions:
+ contents: read
on:📝 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.
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| defaults: | |
| run: | |
| shell: bash | |
| permissions: | |
| contents: read | |
| jobs: |
🤖 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/ui-e2e.yaml around lines 27 - 31, Add a top-level
permissions block to the ui-e2e workflow so the default GITHUB_TOKEN scope is
least-privilege; since the jobs only need checkout, GCP auth, and artifact
upload/download, set workflow-level permissions to contents: read and override
per-job only if a later step needs more access. Place it alongside the existing
defaults/jobs section so the workflow uses the narrower token by default.
Source: Linters/SAST tools
| outputs: | ||
| cluster-name: ${{ env.CLUSTER_NAME }} | ||
| gke-zone: ${{ env.ZONE }} |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm provision_gke_cluster (or related) writes ZONE to GITHUB_ENV
fd -t f 'gke.sh' scripts | xargs -r rg -nC3 'ZONE'
rg -nC2 'GITHUB_ENV' scripts/ci/gke.sh 2>/dev/nullRepository: stackrox/stackrox
Length of output: 1029
🏁 Script executed:
#!/bin/bash
# Search for ZONE export or usage and how ZONE is propagated from the ci_export function
grep -n 'ZONE' scripts/ci/gke.sh | head -20
# Verify what ci_export does with the ZONE variable
grep -A 5 -B 5 'ci_export\|ZONE' scripts/ci/gke.sh | head -40
# Check if GITHUB_ENV is written with ZONE
grep -n "ZONE" scripts/ci/gke.sh | grep -i "GITHUB_ENV"Repository: stackrox/stackrox
Length of output: 1591
🏁 Script executed:
#!/bin/bash
# Investigate the ci_export function to see if it writes to GITHUB_ENV
grep -n "^ci_export" scripts/ci/gke.sh -A 20Repository: stackrox/stackrox
Length of output: 155
🏁 Script executed:
#!/bin/bash
# Search for the definition of ci_export function in gke.sh and surrounding utils functions
grep -n "ci_export" scripts/ci/gke.sh
# Also search for where GITHUB_ENV is used to export variables
grep -n "GITHUB_ENV" scripts/ci/gke.shRepository: stackrox/stackrox
Length of output: 236
🏁 Script executed:
#!/bin/bash
# Locate the definition of ci_export function to see if it appends to GITHUB_ENV
grep -n "ci_export" scripts/ci/gke.sh
# Search for the function definition in this file or sourced files
sed -n '1,200p' scripts/ci/gke.sh | grep -n "ci_export"
# Look for the function body definition, likely near the top of the file or in a sourced file
head -100 scripts/ci/gke.sh | grep -n "^ci_export\|function ci_export\|ci_export()"
# Search for 'GITHUB_ENV' in context of script files to find where exports happen
grep -rn "GITHUB_ENV" scripts/ci/ --include="*.sh" | head -20Repository: stackrox/stackrox
Length of output: 641
🏁 Script executed:
#!/bin/bash
# Read the ci_export function definition from lib.sh
sed -n '30,50p' scripts/ci/lib.shRepository: stackrox/stackrox
Length of output: 698
The gke-zone output relies on ZONE being exported to $GITHUB_ENV.
The provision-gke job defines outputs: gke-zone: ${{ env.ZONE }}, but the job environment does not explicitly set ZONE. Verification of scripts/ci/gke.sh confirms that the ZONE variable is set via the ci_export helper function (line 169), which is defined in scripts/ci/lib.sh to append variables to $GITHUB_ENV when running in a GitHub Actions context. While this mechanism should propagate the value to subsequent steps in the same job, ensuring the step running ci_export create-gke-cluster is correctly executed earlier in the workflow chain is required to prevent the gke-e2e and cleanup-gke jobs from failing with an empty zone.
Expand to view verification details
The variable is set as follows:
scripts/ci/gke.sh
169: ci_export ZONE "$zone"The ci_export function handles the $GITHUB_ENV writing:
scripts/ci/lib.sh
37: if [[ -n "${GITHUB_ENV:-}" ]]; then
38: printf '%s=%q\n' "${env_name}" "${env_value}" >> "$GITHUB_ENV"🤖 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/ui-e2e.yaml around lines 118 - 120, The `gke-zone`
workflow output is reading `env.ZONE`, but `ZONE` is only populated indirectly
by `ci_export` in `scripts/ci/gke.sh` and must be available before the job
output is evaluated. Make sure the `provision-gke` job step that runs
`create-gke-cluster` executes before the outputs are consumed, and verify the
workflow passes the exported `ZONE` through correctly so `gke-e2e` and
`cleanup-gke` receive a non-empty zone. Use `provision-gke`,
`create-gke-cluster`, and `ci_export` to locate the relevant places.
| cy.get(networkGraphSelectors.deploymentNode('sensor'), { timeout: 30000 }); | ||
|
|
||
| // Click on sensor node to open sidebar (force: nodes may overlap in topology) | ||
| cy.get(networkGraphSelectors.deploymentNode('sensor')).click({ force: true }); | ||
|
|
||
| cy.get(networkGraphSelectors.drawerTitle).contains('sensor'); | ||
| cy.get(`${networkGraphSelectors.drawerSubtitle}:contains("stackrox")`); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Use exact matching here to avoid false-positive E2E passes.
networkGraphSelectors.deploymentNode('sensor') expands to a :contains("sensor") selector, and the drawer checks also use substring matching. That means this test can still pass if it hits any node/title containing sensor rather than the exact deployment, which weakens the signal for the new shard-gated UI workflow.
Suggested tightening
- cy.get(networkGraphSelectors.deploymentNode('sensor'), { timeout: 30000 });
+ cy.contains(
+ `${networkGraphSelectors.nodes} [data-type="node"] .pf-topology__node__label`,
+ /^sensor$/,
+ { timeout: 30000 }
+ );
- cy.get(networkGraphSelectors.deploymentNode('sensor')).click({ force: true });
+ cy.contains(
+ `${networkGraphSelectors.nodes} [data-type="node"] .pf-topology__node__label`,
+ /^sensor$/
+ ).click({ force: true });
- cy.get(networkGraphSelectors.drawerTitle).contains('sensor');
- cy.get(`${networkGraphSelectors.drawerSubtitle}:contains("stackrox")`);
+ cy.get(networkGraphSelectors.drawerTitle).should('have.text', 'sensor');
+ cy.get(networkGraphSelectors.drawerSubtitle).should('contain.text', 'stackrox');As per path instructions, focus on major issues impacting maintainability and test reliability.
📝 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.
| cy.get(networkGraphSelectors.deploymentNode('sensor'), { timeout: 30000 }); | |
| // Click on sensor node to open sidebar (force: nodes may overlap in topology) | |
| cy.get(networkGraphSelectors.deploymentNode('sensor')).click({ force: true }); | |
| cy.get(networkGraphSelectors.drawerTitle).contains('sensor'); | |
| cy.get(`${networkGraphSelectors.drawerSubtitle}:contains("stackrox")`); | |
| cy.contains( | |
| `${networkGraphSelectors.nodes} [data-type="node"] .pf-topology__node__label`, | |
| /^sensor$/, | |
| { timeout: 30000 } | |
| ); | |
| // Click on sensor node to open sidebar (force: nodes may overlap in topology) | |
| cy.contains( | |
| `${networkGraphSelectors.nodes} [data-type="node"] .pf-topology__node__label`, | |
| /^sensor$/ | |
| ).click({ force: true }); | |
| cy.get(networkGraphSelectors.drawerTitle).should('have.text', 'sensor'); | |
| cy.get(networkGraphSelectors.drawerSubtitle).should('contain.text', 'stackrox'); |
🤖 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
`@ui/apps/platform/cypress/integration/networkGraph/networkDeploymentSidebar.test.js`
around lines 23 - 29, The Cypress sidebar test is using substring-based
selectors that can pass on the wrong deployment, so tighten it to exact matching
in the networkDeploymentSidebar test. Update the assertions around
networkGraphSelectors.deploymentNode('sensor'),
networkGraphSelectors.drawerTitle, and networkGraphSelectors.drawerSubtitle so
they verify the intended deployment and subtitle exactly rather than relying on
:contains() behavior. This should make the sidebar flow fail unless the correct
sensor node and matching drawer content are selected.
Source: Path instructions
🚀 Build Images ReadyImages are ready for commit 566e4d4. To use with deploy scripts: export MAIN_IMAGE_TAG=4.12.x-325-g566e4d4fcc |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #21421 +/- ##
==========================================
- Coverage 50.12% 50.07% -0.05%
==========================================
Files 2835 2835
Lines 217546 217546
==========================================
- Hits 109049 108945 -104
- Misses 100615 100698 +83
- Partials 7882 7903 +21
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The Cypress before() hook already waits for process events — the workflow-level wait is redundant. Keeps this PR as a pure test fix with no workflow file overlap with PR #21421. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Data readiness waits belong in the Cypress tests that need them, not scattered across the workflow. Tests use before() hooks to poll APIs for their specific data dependencies. Keep only the image scan trigger (seeds initial scan data for all shards to use). Partially generated by AI. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove test changes from the workflow PR — test fixes belong in separate PRs. The network flow data wait in PR #21422 should make this test work without modifications. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 @.github/workflows/ui-e2e.yaml:
- Around line 238-241: Fail fast in the seeded image scan step instead of
swallowing errors with `|| true`; the `curl ... | jq ...` pipeline in the UI e2e
workflow should surface auth/API/scan/JSON failures so the job stops immediately
if the seed scan cannot be triggered. Update the scan command in this workflow
to remove the unconditional success override and, if needed, make the pipeline
itself fail on bad responses while still keeping the `jq` extraction for the
successful case.
🪄 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: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: 982173e7-980c-45d8-aab9-56f87aa51e62
📒 Files selected for processing (1)
.github/workflows/ui-e2e.yaml
| curl -sk -u "admin:${ADMIN_PASSWORD}" \ | ||
| "https://${API_ENDPOINT}/v1/images/scan" \ | ||
| -X POST -d '{"imageName":"docker.io/nginx:1.12","force":true}' 2>&1 \ | ||
| | jq -r '.name // .error // .message' || true |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Fail fast if the seed image scan cannot be triggered.
Line 240 currently swallows auth/API/scan/JSON failures with || true, so shards can proceed without the seeded scan data and fail later with less actionable Cypress errors.
Suggested change
- curl -sk -u "admin:${ADMIN_PASSWORD}" \
+ curl -skS --fail --retry 3 -u "admin:${ADMIN_PASSWORD}" \
+ -H "Content-Type: application/json" \
"https://${API_ENDPOINT}/v1/images/scan" \
-X POST -d '{"imageName":"docker.io/nginx:1.12","force":true}' 2>&1 \
- | jq -r '.name // .error // .message' || true
+ | jq -r '.name // .error // .message'📝 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.
🤖 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/ui-e2e.yaml around lines 238 - 241, Fail fast in the
seeded image scan step instead of swallowing errors with `|| true`; the `curl
... | jq ...` pipeline in the UI e2e workflow should surface auth/API/scan/JSON
failures so the job stops immediately if the seed scan cannot be triggered.
Update the scan command in this workflow to remove the unconditional success
override and, if needed, make the pipeline itself fail on bad responses while
still keeping the `jq` extraction for the successful case.

Description
Adds Cypress UI E2E tests running on GKE in GitHub Actions. Uses a shared GKE cluster with 9 parallel Cypress shards, triggered by the
e2e-ui-gkelabel on PRs or viaworkflow_dispatch.Components:
ui-e2e.yamlworkflow: setup-shards (waterline bin-packing), provision-gke, sharded gke-e2e, cleanup-gkedeploy-stackroxaction: deploys StackRox via roxie with scanner v2 and API token generationcreate-gke-clusteraction: addsauto-cleanupinput so multi-job workflows can disable the post-step cleanupbuild.yaml: addsui-e2ejob gated one2e-ui-gkelabelnetworkDeploymentSidebar.test.js: usesdeploymentNodeselector instead of fragileselectDeploymentdropdown filterStripped-down version of #20345 with only GKE support (no KinD, no infra, no OCP).
User-facing documentation
Testing and quality
Automated testing
How I validated my change
3 verification runs on the
davdhacs/ui-e2ebranch with 9/9 GKE shards passing. This PR is a minimal extraction of the proven workflow.