From 50a7d0490bf749944cfd840d3e57ba2d32ff60ef Mon Sep 17 00:00:00 2001 From: Chai Bot Date: Mon, 3 Aug 2026 18:37:38 +0000 Subject: [PATCH 1/7] Add ACS CI pipeline steps for OPP interop (Phase 1) Add stackrox-opp-readiness and stackrox-opp-smoke step-registry components for running ACS SMOKE tests as part of the OPP interop pipeline. Phase 1a: stackrox-opp-readiness step - Polling loop with 30s interval / 5min timeout - Namespace discovery via Central and SecuredCluster CRs - Central route, API health, cluster connectivity checks - Sensor pod status with OOMKilled detection - Default policy count validation (>80) - Credential extraction with xtrace protection - Writes ROX_ADMIN_PASSWORD, CENTRAL_URL, CENTRAL_NS, SC_NS to SHARED_DIR Phase 1b: stackrox-opp-smoke step - Sparse-clones stackrox/stackrox and stackrox/scanner repos - Runs ./gradlew testSMOKE from qa-tests-backend/ - Copies JUnit XML results to ARTIFACT_DIR - Uses acs-smoke-runner image (UBI9 + OpenJDK 17) Phase 1c: OPP 4.22 config update - Adds dockerfile_literal image build for acs-smoke-runner - Inserts readiness and smoke refs into interop-opp-aws test chain after cucushift-installer-check-cluster-health Co-Authored-By: Claude Opus 4.6 --- ...stron-policy-collection-main__ocp4.22.yaml | 9 + .../stackrox/opp-readiness/OWNERS | 4 + .../stackrox-opp-readiness-commands.sh | 192 ++++++++++++++++++ .../stackrox-opp-readiness-ref.metadata.json | 4 + .../stackrox-opp-readiness-ref.yaml | 16 ++ .../step-registry/stackrox/opp-smoke/OWNERS | 4 + .../opp-smoke/stackrox-opp-smoke-commands.sh | 92 +++++++++ .../stackrox-opp-smoke-ref.metadata.json | 4 + .../opp-smoke/stackrox-opp-smoke-ref.yaml | 16 ++ 9 files changed, 341 insertions(+) create mode 100644 ci-operator/step-registry/stackrox/opp-readiness/OWNERS create mode 100755 ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-commands.sh create mode 100644 ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.metadata.json create mode 100644 ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.yaml create mode 100644 ci-operator/step-registry/stackrox/opp-smoke/OWNERS create mode 100755 ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh create mode 100644 ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.metadata.json create mode 100644 ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.yaml diff --git a/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml b/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml index d1a27998e1f04..cbb04f181f336 100644 --- a/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml +++ b/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml @@ -48,6 +48,13 @@ images: from: cli optional: true to: cli-with-git + - dockerfile_literal: | + FROM registry.access.redhat.com/ubi9/openjdk-17:latest + USER root + RUN microdnf install -y git && microdnf clean all + RUN curl -sL https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz \ + | tar xz -C /usr/local/bin oc kubectl + to: acs-smoke-runner releases: latest: candidate: @@ -119,6 +126,8 @@ tests: - ref: acm-policies-openshift-plus-setup - ref: acm-policies-openshift-plus - chain: cucushift-installer-check-cluster-health + - ref: stackrox-opp-readiness + - ref: stackrox-opp-smoke - ref: acm-tests-clc-create - ref: acm-fetch-managed-clusters - ref: acm-opp-app diff --git a/ci-operator/step-registry/stackrox/opp-readiness/OWNERS b/ci-operator/step-registry/stackrox/opp-readiness/OWNERS new file mode 100644 index 0000000000000..0ce20c59fb95d --- /dev/null +++ b/ci-operator/step-registry/stackrox/opp-readiness/OWNERS @@ -0,0 +1,4 @@ +approvers: +- cspi-qe-ocp-lp +reviewers: +- cspi-qe-ocp-lp diff --git a/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-commands.sh b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-commands.sh new file mode 100755 index 0000000000000..6df678239cf02 --- /dev/null +++ b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-commands.sh @@ -0,0 +1,192 @@ +#!/bin/bash +set -euo pipefail + +# --------------------------------------------------------------------------- +# ACS OPP Readiness Gate +# +# Verifies that ACS Central and SecuredCluster are operational before +# running SMOKE tests. Discovers namespaces dynamically via CRs. +# Writes credentials and connection details to $SHARED_DIR for +# downstream steps. +# --------------------------------------------------------------------------- + +if [[ -f "${SHARED_DIR}/kubeconfig" ]]; then + export KUBECONFIG="${SHARED_DIR}/kubeconfig" +fi + +POLL_INTERVAL=30 +TIMEOUT=300 # 5 minutes +ELAPSED=0 + +# --------------------------------------------------------------------------- +# wait_for - retry a check function with backoff until TIMEOUT +# --------------------------------------------------------------------------- +wait_for() { + local description="$1" + shift + local check_fn="$1" + shift + + ELAPSED=0 + echo "[readiness] Waiting for: ${description}" + while true; do + if "${check_fn}" "$@"; then + echo "[readiness] OK: ${description}" + return 0 + fi + ELAPSED=$((ELAPSED + POLL_INTERVAL)) + if [[ ${ELAPSED} -ge ${TIMEOUT} ]]; then + echo "[readiness] TIMEOUT after ${TIMEOUT}s waiting for: ${description}" + return 1 + fi + echo "[readiness] ...retrying in ${POLL_INTERVAL}s (${ELAPSED}/${TIMEOUT}s)" + sleep "${POLL_INTERVAL}" + done +} + +# --------------------------------------------------------------------------- +# Namespace discovery via CRs (never hardcode) +# --------------------------------------------------------------------------- +discover_central_ns() { + CENTRAL_NS="$(oc get centrals.platform.stackrox.io --all-namespaces \ + -o jsonpath='{.items[0].metadata.namespace}' 2>/dev/null)" \ + && [[ -n "${CENTRAL_NS}" ]] +} + +discover_sc_ns() { + SC_NS="$(oc get securedclusters.platform.stackrox.io --all-namespaces \ + -o jsonpath='{.items[0].metadata.namespace}' 2>/dev/null)" \ + && [[ -n "${SC_NS}" ]] +} + +CENTRAL_NS="" +SC_NS="" + +wait_for "Central CR namespace discovery" discover_central_ns +echo "[readiness] Central namespace: ${CENTRAL_NS}" + +wait_for "SecuredCluster CR namespace discovery" discover_sc_ns +echo "[readiness] SecuredCluster namespace: ${SC_NS}" + +# --------------------------------------------------------------------------- +# Check 1: Central route exists +# --------------------------------------------------------------------------- +check_central_route() { + oc get route central -n "${CENTRAL_NS}" -o jsonpath='{.spec.host}' >/dev/null 2>&1 +} + +wait_for "Central route" check_central_route + +CENTRAL_URL="$(oc get route central -n "${CENTRAL_NS}" -o jsonpath='{.spec.host}')" +echo "[readiness] Central URL: ${CENTRAL_URL}" + +# --------------------------------------------------------------------------- +# Check 2: Central API health (v1/metadata returns 200) +# --------------------------------------------------------------------------- +check_central_api() { + local http_code + http_code="$(curl -sk -o /dev/null -w '%{http_code}' \ + "https://${CENTRAL_URL}/v1/metadata" --max-time 10)" || return 1 + [[ "${http_code}" == "200" ]] +} + +wait_for "Central API health (v1/metadata)" check_central_api + +# --------------------------------------------------------------------------- +# Check 3: At least 1 secured cluster connected +# --------------------------------------------------------------------------- +check_clusters_connected() { + # Disable xtrace to protect admin password in curl args + set +x + local cluster_count + cluster_count="$(curl -sk -u "admin:${ROX_ADMIN_PASSWORD}" \ + "https://${CENTRAL_URL}/v1/clusters" --max-time 10 \ + | jq '.clusters | length' 2>/dev/null)" || { set -x 2>/dev/null || true; return 1; } + set -x 2>/dev/null || true + [[ "${cluster_count}" -ge 1 ]] +} + +# --------------------------------------------------------------------------- +# Check 6 (early): Extract ROX_ADMIN_PASSWORD before cluster check +# --------------------------------------------------------------------------- +echo "[readiness] Extracting ROX_ADMIN_PASSWORD..." +ROX_ADMIN_PASSWORD="" +set +x +ROX_ADMIN_PASSWORD="$(oc get secret -n "${CENTRAL_NS}" central-htpasswd \ + -o json | jq -r '.data.password' | base64 -d)" +set -x 2>/dev/null || true + +if [[ -z "${ROX_ADMIN_PASSWORD}" ]]; then + echo "[readiness] FATAL: could not extract ROX_ADMIN_PASSWORD" + exit 1 +fi +echo "[readiness] ROX_ADMIN_PASSWORD extracted successfully" + +wait_for "secured cluster connected (v1/clusters)" check_clusters_connected + +# --------------------------------------------------------------------------- +# Check 4: Sensor pods Running (detect OOMKilled) +# --------------------------------------------------------------------------- +check_sensor_pods() { + local pod_json + pod_json="$(oc get pods -n "${SC_NS}" -l app=sensor -o json 2>/dev/null)" + + local pod_count + pod_count="$(echo "${pod_json}" | jq '.items | length')" + if [[ "${pod_count}" -eq 0 ]]; then + echo "[readiness] no sensor pods found yet" + return 1 + fi + + # Check for OOMKilled containers + local oom + oom="$(echo "${pod_json}" | jq -r ' + .items[].status.containerStatuses[]? + | select(.lastState.terminated.reason == "OOMKilled") + | .name + ')" + if [[ -n "${oom}" ]]; then + echo "[readiness] WARNING: OOMKilled detected in sensor containers: ${oom}" + fi + + # All sensor pods must be Running + local not_running + not_running="$(echo "${pod_json}" | jq -r ' + .items[] | select(.status.phase != "Running") + | "\(.metadata.name):\(.status.phase)" + ')" + [[ -z "${not_running}" ]] +} + +wait_for "sensor pods Running in ${SC_NS}" check_sensor_pods + +# --------------------------------------------------------------------------- +# Check 5: Default policies loaded (count > 80) +# --------------------------------------------------------------------------- +check_policies_loaded() { + set +x + local policy_count + policy_count="$(curl -sk -u "admin:${ROX_ADMIN_PASSWORD}" \ + "https://${CENTRAL_URL}/v1/policies?query=" --max-time 10 \ + | jq '.policies | length' 2>/dev/null)" || { set -x 2>/dev/null || true; return 1; } + set -x 2>/dev/null || true + echo "[readiness] policy count: ${policy_count}" + [[ "${policy_count}" -gt 80 ]] +} + +wait_for "default policies loaded (>80)" check_policies_loaded + +# --------------------------------------------------------------------------- +# Write outputs to SHARED_DIR for downstream steps +# --------------------------------------------------------------------------- +echo "[readiness] Writing connection details to SHARED_DIR..." + +set +x +echo "${ROX_ADMIN_PASSWORD}" > "${SHARED_DIR}/ROX_ADMIN_PASSWORD" +set -x 2>/dev/null || true + +echo "${CENTRAL_URL}" > "${SHARED_DIR}/CENTRAL_URL" +echo "${CENTRAL_NS}" > "${SHARED_DIR}/CENTRAL_NS" +echo "${SC_NS}" > "${SHARED_DIR}/SC_NS" + +echo "[readiness] All checks passed. ACS is ready for SMOKE tests." diff --git a/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.metadata.json b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.metadata.json new file mode 100644 index 0000000000000..8c2d89a4ed9e9 --- /dev/null +++ b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.metadata.json @@ -0,0 +1,4 @@ +{ + "labels": [], + "description": "Verify ACS Central and SecuredCluster are operational before running SMOKE tests." +} diff --git a/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.yaml b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.yaml new file mode 100644 index 0000000000000..fc691692a8568 --- /dev/null +++ b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.yaml @@ -0,0 +1,16 @@ +ref: + as: stackrox-opp-readiness + commands: stackrox-opp-readiness-commands.sh + resources: + requests: + cpu: 100m + memory: 200Mi + from: cli + timeout: 10m0s + documentation: |- + Verify ACS Central and SecuredCluster are operational before running + SMOKE tests. Discovers namespaces dynamically via Central and + SecuredCluster CRs, then polls Central API health, secured-cluster + connectivity, sensor pod status, and default policy count. Writes + ROX_ADMIN_PASSWORD, CENTRAL_URL, CENTRAL_NS, and SC_NS to SHARED_DIR + for downstream steps. diff --git a/ci-operator/step-registry/stackrox/opp-smoke/OWNERS b/ci-operator/step-registry/stackrox/opp-smoke/OWNERS new file mode 100644 index 0000000000000..0ce20c59fb95d --- /dev/null +++ b/ci-operator/step-registry/stackrox/opp-smoke/OWNERS @@ -0,0 +1,4 @@ +approvers: +- cspi-qe-ocp-lp +reviewers: +- cspi-qe-ocp-lp diff --git a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh new file mode 100755 index 0000000000000..55bb1c493009c --- /dev/null +++ b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh @@ -0,0 +1,92 @@ +#!/bin/bash +set -euo pipefail + +# --------------------------------------------------------------------------- +# ACS OPP SMOKE Test Runner +# +# Runs the stackrox qa-tests-backend testSMOKE suite against an ACS +# instance whose credentials were written to $SHARED_DIR by the +# stackrox-opp-readiness step. +# +# Image: acs-smoke-runner (UBI9 + OpenJDK 17 + git + oc) +# --------------------------------------------------------------------------- + +if [[ -f "${SHARED_DIR}/kubeconfig" ]]; then + export KUBECONFIG="${SHARED_DIR}/kubeconfig" +fi + +# --------------------------------------------------------------------------- +# Read credentials from SHARED_DIR (written by readiness gate) +# --------------------------------------------------------------------------- +echo "[smoke] Reading connection details from SHARED_DIR..." + +CENTRAL_URL="$(cat "${SHARED_DIR}/CENTRAL_URL")" +CENTRAL_NS="$(cat "${SHARED_DIR}/CENTRAL_NS")" +SC_NS="$(cat "${SHARED_DIR}/SC_NS")" + +set +x +ROX_ADMIN_PASSWORD="$(cat "${SHARED_DIR}/ROX_ADMIN_PASSWORD")" +set -x 2>/dev/null || true + +echo "[smoke] Central URL : ${CENTRAL_URL}" +echo "[smoke] Central NS : ${CENTRAL_NS}" +echo "[smoke] SC NS : ${SC_NS}" + +# --------------------------------------------------------------------------- +# Sparse clone of stackrox/stackrox (qa-tests-backend + proto) +# --------------------------------------------------------------------------- +echo "[smoke] Sparse-cloning stackrox/stackrox..." +cd /tmp +git clone --depth 1 --filter=blob:none --sparse \ + https://github.com/stackrox/stackrox.git stackrox +cd stackrox +git sparse-checkout set qa-tests-backend/ proto/ + +# --------------------------------------------------------------------------- +# Fetch scanner protos (no Go toolchain needed) +# --------------------------------------------------------------------------- +echo "[smoke] Fetching scanner protos..." +git clone --depth 1 --filter=blob:none --sparse \ + https://github.com/stackrox/scanner.git /tmp/scanner +cd /tmp/scanner +git sparse-checkout set proto/scanner +cp -r proto/scanner /tmp/stackrox/qa-tests-backend/src/main/proto/scanner +chmod -R u+w /tmp/stackrox/qa-tests-backend/src/main/proto/scanner + +# --------------------------------------------------------------------------- +# Set environment for the Gradle test suite +# --------------------------------------------------------------------------- +export API_HOSTNAME="${CENTRAL_URL}" +export API_PORT="443" +export ROX_USERNAME="admin" +export ROX_ADMIN_PASSWORD +export CLUSTER="OPENSHIFT" +export CI="true" + +# --------------------------------------------------------------------------- +# Run testSMOKE +# --------------------------------------------------------------------------- +echo "[smoke] Running testSMOKE..." +cd /tmp/stackrox/qa-tests-backend + +./gradlew testSMOKE -i --no-daemon || TEST_EXIT=$? +TEST_EXIT="${TEST_EXIT:-0}" + +# --------------------------------------------------------------------------- +# Copy JUnit XML results to ARTIFACT_DIR +# --------------------------------------------------------------------------- +echo "[smoke] Copying JUnit results to ARTIFACT_DIR..." +if [[ -d build/test-results/testSMOKE ]]; then + cp -v build/test-results/testSMOKE/*.xml "${ARTIFACT_DIR}/" 2>/dev/null || true +else + echo "[smoke] WARNING: No test results directory found at build/test-results/testSMOKE/" +fi + +# Also copy HTML report if available +if [[ -d build/reports/tests/testSMOKE ]]; then + mkdir -p "${ARTIFACT_DIR}/smoke-report" + cp -r build/reports/tests/testSMOKE/* "${ARTIFACT_DIR}/smoke-report/" 2>/dev/null || true +fi + +echo "[smoke] Test run finished with exit code: ${TEST_EXIT}" +exit "${TEST_EXIT}" diff --git a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.metadata.json b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.metadata.json new file mode 100644 index 0000000000000..017c12ece139f --- /dev/null +++ b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.metadata.json @@ -0,0 +1,4 @@ +{ + "labels": [], + "description": "Run ACS qa-tests-backend SMOKE suite and produce JUnit XML results." +} diff --git a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.yaml b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.yaml new file mode 100644 index 0000000000000..a93e20d78137a --- /dev/null +++ b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.yaml @@ -0,0 +1,16 @@ +ref: + as: stackrox-opp-smoke + commands: stackrox-opp-smoke-commands.sh + resources: + requests: + cpu: 2000m + memory: 4Gi + from: acs-smoke-runner + timeout: 1h0m0s + documentation: |- + Run the ACS qa-tests-backend SMOKE suite against a live ACS + instance. Reads connection credentials from SHARED_DIR + (written by stackrox-opp-readiness). Sparse-clones the + stackrox/stackrox and stackrox/scanner repos, then executes + ./gradlew testSMOKE. JUnit XML results are copied to + ARTIFACT_DIR for Prow / Sippy consumption. From dcd29b74f26a0ebe43bf65db470cc91c302de1e8 Mon Sep 17 00:00:00 2001 From: Chai Bot Date: Mon, 3 Aug 2026 18:45:04 +0000 Subject: [PATCH 2/7] Regenerate metadata.json via make registry-metadata The generate-registry-metadata tool rewrites metadata.json files to canonical format with path and owners (derived from OWNERS files), replacing the manual labels/description fields. Co-Authored-By: Claude Opus 4.6 --- .../stackrox-opp-readiness-ref.metadata.json | 13 ++++++++++--- .../opp-smoke/stackrox-opp-smoke-ref.metadata.json | 13 ++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.metadata.json b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.metadata.json index 8c2d89a4ed9e9..cb61d5b78e49a 100644 --- a/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.metadata.json +++ b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.metadata.json @@ -1,4 +1,11 @@ { - "labels": [], - "description": "Verify ACS Central and SecuredCluster are operational before running SMOKE tests." -} + "path": "stackrox/opp-readiness/stackrox-opp-readiness-ref.yaml", + "owners": { + "approvers": [ + "cspi-qe-ocp-lp" + ], + "reviewers": [ + "cspi-qe-ocp-lp" + ] + } +} \ No newline at end of file diff --git a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.metadata.json b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.metadata.json index 017c12ece139f..0b518035376be 100644 --- a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.metadata.json +++ b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.metadata.json @@ -1,4 +1,11 @@ { - "labels": [], - "description": "Run ACS qa-tests-backend SMOKE suite and produce JUnit XML results." -} + "path": "stackrox/opp-smoke/stackrox-opp-smoke-ref.yaml", + "owners": { + "approvers": [ + "cspi-qe-ocp-lp" + ], + "reviewers": [ + "cspi-qe-ocp-lp" + ] + } +} \ No newline at end of file From c20f375123a2c42f761e47f002f5885a628f0c9c Mon Sep 17 00:00:00 2001 From: Chai Bot Date: Tue, 4 Aug 2026 14:24:52 +0000 Subject: [PATCH 3/7] Address review feedback: security, timeout, and container hardening - Remove sensitive URL/namespace values from CI logs - Remove incorrect set -x re-enablement (tracing was never on) - Increase readiness step timeout from 10m to 40m - Add non-root USER 1001 to acs-smoke-runner Dockerfile Co-Authored-By: Claude Opus 4.6 --- ...stolostron-policy-collection-main__ocp4.22.yaml | 1 + .../stackrox-opp-readiness-commands.sh | 14 +++++--------- .../opp-readiness/stackrox-opp-readiness-ref.yaml | 2 +- .../opp-smoke/stackrox-opp-smoke-commands.sh | 7 +------ 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml b/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml index cbb04f181f336..957ce38072ce2 100644 --- a/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml +++ b/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml @@ -54,6 +54,7 @@ images: RUN microdnf install -y git && microdnf clean all RUN curl -sL https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz \ | tar xz -C /usr/local/bin oc kubectl + USER 1001 to: acs-smoke-runner releases: latest: diff --git a/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-commands.sh b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-commands.sh index 6df678239cf02..eb75182d74702 100755 --- a/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-commands.sh +++ b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-commands.sh @@ -63,10 +63,10 @@ CENTRAL_NS="" SC_NS="" wait_for "Central CR namespace discovery" discover_central_ns -echo "[readiness] Central namespace: ${CENTRAL_NS}" +echo "[readiness] Central namespace discovered" wait_for "SecuredCluster CR namespace discovery" discover_sc_ns -echo "[readiness] SecuredCluster namespace: ${SC_NS}" +echo "[readiness] SecuredCluster namespace discovered" # --------------------------------------------------------------------------- # Check 1: Central route exists @@ -78,7 +78,7 @@ check_central_route() { wait_for "Central route" check_central_route CENTRAL_URL="$(oc get route central -n "${CENTRAL_NS}" -o jsonpath='{.spec.host}')" -echo "[readiness] Central URL: ${CENTRAL_URL}" +echo "[readiness] Central route discovered" # --------------------------------------------------------------------------- # Check 2: Central API health (v1/metadata returns 200) @@ -101,8 +101,7 @@ check_clusters_connected() { local cluster_count cluster_count="$(curl -sk -u "admin:${ROX_ADMIN_PASSWORD}" \ "https://${CENTRAL_URL}/v1/clusters" --max-time 10 \ - | jq '.clusters | length' 2>/dev/null)" || { set -x 2>/dev/null || true; return 1; } - set -x 2>/dev/null || true + | jq '.clusters | length' 2>/dev/null)" || return 1 [[ "${cluster_count}" -ge 1 ]] } @@ -114,7 +113,6 @@ ROX_ADMIN_PASSWORD="" set +x ROX_ADMIN_PASSWORD="$(oc get secret -n "${CENTRAL_NS}" central-htpasswd \ -o json | jq -r '.data.password' | base64 -d)" -set -x 2>/dev/null || true if [[ -z "${ROX_ADMIN_PASSWORD}" ]]; then echo "[readiness] FATAL: could not extract ROX_ADMIN_PASSWORD" @@ -168,8 +166,7 @@ check_policies_loaded() { local policy_count policy_count="$(curl -sk -u "admin:${ROX_ADMIN_PASSWORD}" \ "https://${CENTRAL_URL}/v1/policies?query=" --max-time 10 \ - | jq '.policies | length' 2>/dev/null)" || { set -x 2>/dev/null || true; return 1; } - set -x 2>/dev/null || true + | jq '.policies | length' 2>/dev/null)" || return 1 echo "[readiness] policy count: ${policy_count}" [[ "${policy_count}" -gt 80 ]] } @@ -183,7 +180,6 @@ echo "[readiness] Writing connection details to SHARED_DIR..." set +x echo "${ROX_ADMIN_PASSWORD}" > "${SHARED_DIR}/ROX_ADMIN_PASSWORD" -set -x 2>/dev/null || true echo "${CENTRAL_URL}" > "${SHARED_DIR}/CENTRAL_URL" echo "${CENTRAL_NS}" > "${SHARED_DIR}/CENTRAL_NS" diff --git a/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.yaml b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.yaml index fc691692a8568..41ea4e4aa5e43 100644 --- a/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.yaml +++ b/ci-operator/step-registry/stackrox/opp-readiness/stackrox-opp-readiness-ref.yaml @@ -6,7 +6,7 @@ ref: cpu: 100m memory: 200Mi from: cli - timeout: 10m0s + timeout: 40m0s documentation: |- Verify ACS Central and SecuredCluster are operational before running SMOKE tests. Discovers namespaces dynamically via Central and diff --git a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh index 55bb1c493009c..834e48e945e2f 100755 --- a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh +++ b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh @@ -21,16 +21,11 @@ fi echo "[smoke] Reading connection details from SHARED_DIR..." CENTRAL_URL="$(cat "${SHARED_DIR}/CENTRAL_URL")" -CENTRAL_NS="$(cat "${SHARED_DIR}/CENTRAL_NS")" -SC_NS="$(cat "${SHARED_DIR}/SC_NS")" set +x ROX_ADMIN_PASSWORD="$(cat "${SHARED_DIR}/ROX_ADMIN_PASSWORD")" -set -x 2>/dev/null || true -echo "[smoke] Central URL : ${CENTRAL_URL}" -echo "[smoke] Central NS : ${CENTRAL_NS}" -echo "[smoke] SC NS : ${SC_NS}" +echo "[smoke] Connection details loaded from SHARED_DIR" # --------------------------------------------------------------------------- # Sparse clone of stackrox/stackrox (qa-tests-backend + proto) From 27c76c8e766cf405bad84a84d563c17f7f39fecb Mon Sep 17 00:00:00 2001 From: Chai Bot Date: Tue, 4 Aug 2026 14:42:26 +0000 Subject: [PATCH 4/7] Address nitpick review feedback: pin clone refs and base image - Make stackrox/scanner clone refs overridable via env vars - Pin ubi9/openjdk-17 base image to tag 1.21 - Add SHA-256 checksum verification for oc client download Co-Authored-By: Claude Opus 4.6 --- .../stolostron-policy-collection-main__ocp4.22.yaml | 8 +++++--- .../stackrox/opp-smoke/stackrox-opp-smoke-commands.sh | 8 ++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml b/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml index 957ce38072ce2..854076325b306 100644 --- a/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml +++ b/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml @@ -49,11 +49,13 @@ images: optional: true to: cli-with-git - dockerfile_literal: | - FROM registry.access.redhat.com/ubi9/openjdk-17:latest + FROM registry.access.redhat.com/ubi9/openjdk-17:1.21 USER root RUN microdnf install -y git && microdnf clean all - RUN curl -sL https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz \ - | tar xz -C /usr/local/bin oc kubectl + RUN curl -sLo /tmp/oc-client.tar.gz https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz \ + && curl -sL https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/sha256sum.txt | grep openshift-client-linux.tar.gz | sha256sum -c - \ + && tar xzf /tmp/oc-client.tar.gz -C /usr/local/bin oc kubectl \ + && rm -f /tmp/oc-client.tar.gz USER 1001 to: acs-smoke-runner releases: diff --git a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh index 834e48e945e2f..a3cd912329b1d 100755 --- a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh +++ b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh @@ -27,12 +27,16 @@ ROX_ADMIN_PASSWORD="$(cat "${SHARED_DIR}/ROX_ADMIN_PASSWORD")" echo "[smoke] Connection details loaded from SHARED_DIR" +# Allow pinning to a known-good ref for reproducibility +STACKROX_REF="${STACKROX_REF:-main}" +SCANNER_REF="${SCANNER_REF:-main}" + # --------------------------------------------------------------------------- # Sparse clone of stackrox/stackrox (qa-tests-backend + proto) # --------------------------------------------------------------------------- echo "[smoke] Sparse-cloning stackrox/stackrox..." cd /tmp -git clone --depth 1 --filter=blob:none --sparse \ +git clone --depth 1 --filter=blob:none --sparse --branch "${STACKROX_REF}" \ https://github.com/stackrox/stackrox.git stackrox cd stackrox git sparse-checkout set qa-tests-backend/ proto/ @@ -41,7 +45,7 @@ git sparse-checkout set qa-tests-backend/ proto/ # Fetch scanner protos (no Go toolchain needed) # --------------------------------------------------------------------------- echo "[smoke] Fetching scanner protos..." -git clone --depth 1 --filter=blob:none --sparse \ +git clone --depth 1 --filter=blob:none --sparse --branch "${SCANNER_REF}" \ https://github.com/stackrox/scanner.git /tmp/scanner cd /tmp/scanner git sparse-checkout set proto/scanner From 12743d6399d14beabfc3805402b7cf1625cedbcf Mon Sep 17 00:00:00 2001 From: Chai Bot Date: Tue, 4 Aug 2026 18:41:54 +0000 Subject: [PATCH 5/7] fix(opp-smoke): pre-initialize TEST_EXIT for deterministic exit code Co-Authored-By: Claude Opus 4.6 --- .../stackrox/opp-smoke/stackrox-opp-smoke-commands.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh index a3cd912329b1d..c44176effe663 100755 --- a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh +++ b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh @@ -68,8 +68,8 @@ export CI="true" echo "[smoke] Running testSMOKE..." cd /tmp/stackrox/qa-tests-backend +TEST_EXIT=0 ./gradlew testSMOKE -i --no-daemon || TEST_EXIT=$? -TEST_EXIT="${TEST_EXIT:-0}" # --------------------------------------------------------------------------- # Copy JUnit XML results to ARTIFACT_DIR From cdc0f79e1937cda9ea173bc423d4358b9bb42984 Mon Sep 17 00:00:00 2001 From: Chai Bot Date: Tue, 4 Aug 2026 19:11:43 +0000 Subject: [PATCH 6/7] Address review findings: env vars, artifact safety, memory, clone retry - Declare STACKROX_REF and SCANNER_REF in smoke ref YAML - Guard artifact collection against masking test exit code - Increase memory request to 6Gi with JVM heap cap - Add retry wrapper for sparse git clones --- .../opp-smoke/stackrox-opp-smoke-commands.sh | 46 +++++++++++++------ .../opp-smoke/stackrox-opp-smoke-ref.yaml | 9 +++- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh index c44176effe663..4a15bf4ea48a7 100755 --- a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh +++ b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-commands.sh @@ -31,12 +31,30 @@ echo "[smoke] Connection details loaded from SHARED_DIR" STACKROX_REF="${STACKROX_REF:-main}" SCANNER_REF="${SCANNER_REF:-main}" +# --------------------------------------------------------------------------- +# Retry wrapper for network-dependent operations +# --------------------------------------------------------------------------- +retry_clone() { + local max_attempts=3 + local attempt=1 + while [[ $attempt -le $max_attempts ]]; do + if "$@"; then + return 0 + fi + echo "[smoke] Clone attempt $attempt/$max_attempts failed, retrying in 10s..." + sleep 10 + attempt=$((attempt + 1)) + done + echo "[smoke] ERROR: Clone failed after $max_attempts attempts" + return 1 +} + # --------------------------------------------------------------------------- # Sparse clone of stackrox/stackrox (qa-tests-backend + proto) # --------------------------------------------------------------------------- echo "[smoke] Sparse-cloning stackrox/stackrox..." cd /tmp -git clone --depth 1 --filter=blob:none --sparse --branch "${STACKROX_REF}" \ +retry_clone git clone --depth 1 --filter=blob:none --sparse --branch "${STACKROX_REF}" \ https://github.com/stackrox/stackrox.git stackrox cd stackrox git sparse-checkout set qa-tests-backend/ proto/ @@ -45,7 +63,7 @@ git sparse-checkout set qa-tests-backend/ proto/ # Fetch scanner protos (no Go toolchain needed) # --------------------------------------------------------------------------- echo "[smoke] Fetching scanner protos..." -git clone --depth 1 --filter=blob:none --sparse --branch "${SCANNER_REF}" \ +retry_clone git clone --depth 1 --filter=blob:none --sparse --branch "${SCANNER_REF}" \ https://github.com/stackrox/scanner.git /tmp/scanner cd /tmp/scanner git sparse-checkout set proto/scanner @@ -69,23 +87,21 @@ echo "[smoke] Running testSMOKE..." cd /tmp/stackrox/qa-tests-backend TEST_EXIT=0 -./gradlew testSMOKE -i --no-daemon || TEST_EXIT=$? +./gradlew testSMOKE -i --no-daemon -Dorg.gradle.jvmargs="-Xmx3g" || TEST_EXIT=$? # --------------------------------------------------------------------------- # Copy JUnit XML results to ARTIFACT_DIR # --------------------------------------------------------------------------- -echo "[smoke] Copying JUnit results to ARTIFACT_DIR..." -if [[ -d build/test-results/testSMOKE ]]; then - cp -v build/test-results/testSMOKE/*.xml "${ARTIFACT_DIR}/" 2>/dev/null || true -else - echo "[smoke] WARNING: No test results directory found at build/test-results/testSMOKE/" -fi - -# Also copy HTML report if available -if [[ -d build/reports/tests/testSMOKE ]]; then - mkdir -p "${ARTIFACT_DIR}/smoke-report" - cp -r build/reports/tests/testSMOKE/* "${ARTIFACT_DIR}/smoke-report/" 2>/dev/null || true -fi +collect_artifacts() { + if [[ -d build/test-results/testSMOKE ]]; then + cp -v build/test-results/testSMOKE/*.xml "${ARTIFACT_DIR}/" 2>/dev/null || true + fi + if [[ -d build/reports/tests/testSMOKE ]]; then + mkdir -p "${ARTIFACT_DIR}/smoke-report" 2>/dev/null || true + cp -r build/reports/tests/testSMOKE/* "${ARTIFACT_DIR}/smoke-report/" 2>/dev/null || true + fi +} +collect_artifacts || true echo "[smoke] Test run finished with exit code: ${TEST_EXIT}" exit "${TEST_EXIT}" diff --git a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.yaml b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.yaml index a93e20d78137a..e3ea4dabbd240 100644 --- a/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.yaml +++ b/ci-operator/step-registry/stackrox/opp-smoke/stackrox-opp-smoke-ref.yaml @@ -4,9 +4,16 @@ ref: resources: requests: cpu: 2000m - memory: 4Gi + memory: 6Gi from: acs-smoke-runner timeout: 1h0m0s + env: + - name: STACKROX_REF + default: "main" + documentation: Git ref (branch/tag) for stackrox/stackrox sparse clone + - name: SCANNER_REF + default: "main" + documentation: Git ref (branch/tag) for stackrox/scanner proto clone documentation: |- Run the ACS qa-tests-backend SMOKE suite against a live ACS instance. Reads connection credentials from SHARED_DIR From f19cb22efcecbfd91865b6dcb328f246d50b3417 Mon Sep 17 00:00:00 2001 From: Chai Bot Date: Wed, 5 Aug 2026 12:02:29 +0000 Subject: [PATCH 7/7] Fix acs-smoke-runner Dockerfile sha256sum verification The RUN command downloaded the OC client tarball as /tmp/oc-client.tar.gz but sha256sum.txt references openshift-client-linux.tar.gz. When sha256sum -c reads from stdin, it looks for a file named openshift-client-linux.tar.gz which does not exist, causing the verification to always fail. Fix by cd-ing into /tmp and using curl -LO to save the file with its original name (openshift-client-linux.tar.gz), matching what sha256sum expects. Co-Authored-By: Claude Opus 4.6 --- .../stolostron-policy-collection-main__ocp4.22.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml b/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml index 854076325b306..4187d2fbeaa3e 100644 --- a/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml +++ b/ci-operator/config/stolostron/policy-collection/stolostron-policy-collection-main__ocp4.22.yaml @@ -52,10 +52,11 @@ images: FROM registry.access.redhat.com/ubi9/openjdk-17:1.21 USER root RUN microdnf install -y git && microdnf clean all - RUN curl -sLo /tmp/oc-client.tar.gz https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz \ + RUN cd /tmp \ + && curl -sLO https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-client-linux.tar.gz \ && curl -sL https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/sha256sum.txt | grep openshift-client-linux.tar.gz | sha256sum -c - \ - && tar xzf /tmp/oc-client.tar.gz -C /usr/local/bin oc kubectl \ - && rm -f /tmp/oc-client.tar.gz + && tar xzf openshift-client-linux.tar.gz -C /usr/local/bin oc kubectl \ + && rm -f openshift-client-linux.tar.gz USER 1001 to: acs-smoke-runner releases: