-
Notifications
You must be signed in to change notification settings - Fork 2.2k
NO-JIRA: Add E2E coverage reporting for secrets-store-csi-driver-operator #79231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,21 @@ images: | |
| - dockerfile_path: Dockerfile.mustgather | ||
| from: ocp_4.14_cli | ||
| to: secrets-store-csi-mustgather | ||
| - dockerfile_literal: | | ||
| FROM registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.25-openshift-4.22 AS builder | ||
| WORKDIR /go/src/github.com/openshift/secrets-store-csi-driver-operator | ||
| COPY . . | ||
| RUN CGO_ENABLED=1 GOEXPERIMENT=strictfipsruntime go build \ | ||
| -mod=vendor -trimpath \ | ||
| -tags strictfipsruntime,openssl \ | ||
| -cover -covermode=atomic -coverpkg=./... \ | ||
| -o secrets-store-csi-driver-operator \ | ||
| ./cmd/secrets-store-csi-driver-operator | ||
| FROM registry.ci.openshift.org/ocp/4.22:base-rhel9 | ||
| COPY --from=builder /go/src/github.com/openshift/secrets-store-csi-driver-operator/secrets-store-csi-driver-operator /usr/bin/ | ||
| ENV GOCOVERDIR=/tmp/e2e-cover | ||
| ENTRYPOINT ["/bin/sh", "-c", "mkdir -p /tmp/e2e-cover && exec /usr/bin/secrets-store-csi-driver-operator \"$@\"", "--"] | ||
| to: secrets-store-csi-driver-operator-coverage | ||
| operator: | ||
| bundles: | ||
| - as: secrets-store-csi-driver-operator-bundle | ||
|
|
@@ -96,9 +111,136 @@ tests: | |
| OO_INSTALL_NAMESPACE: openshift-cluster-csi-drivers | ||
| OO_PACKAGE: secrets-store-csi-driver-operator | ||
| OO_TARGET_NAMESPACES: '!all' | ||
| post: | ||
| - as: collect-coverage | ||
| best_effort: true | ||
| cli: latest | ||
| commands: | | ||
| set -euo pipefail | ||
| NAMESPACE="openshift-cluster-csi-drivers" | ||
| DEPLOYMENT="secrets-store-csi-driver-operator" | ||
| POD_LABEL="app=secrets-store-csi-driver-operator" | ||
| GOCOVERDIR_PATH="/tmp/e2e-cover" | ||
| CODECOV_SECRET="/var/run/secrets/codecov/CODECOV_TOKEN" | ||
|
|
||
| artifact_dir="${ARTIFACT_DIR:-.}" | ||
| coverage_dir="${artifact_dir}/e2e-cover-data" | ||
| coverage_profile="${artifact_dir}/coverage-e2e.out" | ||
|
|
||
| if [ -z "${CODECOV_TOKEN:-}" ] && [ -f "${CODECOV_SECRET}" ]; then | ||
| CODECOV_TOKEN=$(cat "${CODECOV_SECRET}") | ||
| export CODECOV_TOKEN | ||
| fi | ||
|
|
||
| pod=$(oc get pods -n "${NAMESPACE}" -l "${POD_LABEL}" \ | ||
| -o jsonpath='{.items[0].metadata.name}' 2>/dev/null) | ||
| if [ -z "${pod}" ]; then | ||
| echo "Error: no operator pod found"; exit 1 | ||
| fi | ||
| echo "Found operator pod: ${pod}" | ||
|
|
||
| echo "Sending SIGTERM to flush coverage data (container will restart)..." | ||
| oc exec -n "${NAMESPACE}" "${pod}" -- /bin/sh -c 'kill -TERM 1' 2>/dev/null || true | ||
|
|
||
| echo "Waiting for container to restart and become ready..." | ||
| sleep 5 | ||
| oc wait pod "${pod}" -n "${NAMESPACE}" --for=condition=Ready --timeout=120s | ||
|
|
||
| echo "Copying coverage data from restarted container..." | ||
| mkdir -p "${coverage_dir}" | ||
| oc cp "${NAMESPACE}/${pod}:${GOCOVERDIR_PATH}/." "${coverage_dir}" | ||
|
|
||
| echo "Coverage files:" | ||
| ls -la "${coverage_dir}/" 2>/dev/null || true | ||
|
|
||
| if ls "${coverage_dir}"/covmeta.* >/dev/null 2>&1; then | ||
| echo "Converting coverage data..." | ||
| go tool covdata textfmt -i="${coverage_dir}" -o="${coverage_profile}" | ||
| echo "=== E2E Coverage Summary ===" | ||
| go tool covdata percent -i="${coverage_dir}" | ||
| echo "=============================" | ||
|
|
||
| if [ -n "${CODECOV_TOKEN:-}" ]; then | ||
| echo "Uploading to Codecov..." | ||
| codecov_bin="${artifact_dir}/codecov" | ||
| curl -sS -o "${codecov_bin}" https://uploader.codecov.io/latest/linux/codecov | ||
| curl -sS -o "${codecov_bin}.SHA256SUM" https://uploader.codecov.io/latest/linux/codecov.SHA256SUM | ||
| cd "$(dirname "${codecov_bin}")" && sha256sum -c "$(basename "${codecov_bin}").SHA256SUM" && cd - >/dev/null | ||
| chmod +x "${codecov_bin}" | ||
|
|
||
| codecov_flags="--file=${coverage_profile} --flags=e2e --name=E2E-Coverage --verbose" | ||
| job_type="${JOB_TYPE:-local}" | ||
| if [ "${job_type}" = "presubmit" ]; then | ||
| [ -n "${PULL_NUMBER:-}" ] && codecov_flags="${codecov_flags} --pr ${PULL_NUMBER}" | ||
| [ -n "${PULL_PULL_SHA:-}" ] && codecov_flags="${codecov_flags} --sha ${PULL_PULL_SHA}" | ||
| [ -n "${PULL_BASE_REF:-}" ] && codecov_flags="${codecov_flags} --branch ${PULL_BASE_REF}" | ||
| [ -n "${REPO_OWNER:-}" ] && [ -n "${REPO_NAME:-}" ] && codecov_flags="${codecov_flags} --slug ${REPO_OWNER}/${REPO_NAME}" | ||
| elif [ "${job_type}" = "postsubmit" ]; then | ||
| [ -n "${PULL_BASE_SHA:-}" ] && codecov_flags="${codecov_flags} --sha ${PULL_BASE_SHA}" | ||
| [ -n "${PULL_BASE_REF:-}" ] && codecov_flags="${codecov_flags} --branch ${PULL_BASE_REF}" | ||
| [ -n "${REPO_OWNER:-}" ] && [ -n "${REPO_NAME:-}" ] && codecov_flags="${codecov_flags} --slug ${REPO_OWNER}/${REPO_NAME}" | ||
| fi | ||
|
|
||
| ${codecov_bin} ${codecov_flags} || echo "Warning: Codecov upload failed (non-fatal)" | ||
| rm -f "${codecov_bin}" "${codecov_bin}.SHA256SUM" | ||
| else | ||
| echo "CODECOV_TOKEN not set -- skipping upload. Profile saved: ${coverage_profile}" | ||
| fi | ||
| else | ||
| echo "Warning: No coverage data found" | ||
| fi | ||
| credentials: | ||
| - mount_path: /var/run/secrets/codecov | ||
| name: sscsi-driver-operator-codecov-token | ||
| namespace: test-credentials | ||
| from: src | ||
| resources: | ||
| requests: | ||
| cpu: 100m | ||
| timeout: 15m0s | ||
| - chain: gather | ||
| test: | ||
| - ref: fips-check-fips-or-die | ||
| - ref: fips-check-node-scan | ||
| - as: setup-coverage | ||
| cli: latest | ||
| commands: | | ||
| set -euo pipefail | ||
| NAMESPACE="openshift-cluster-csi-drivers" | ||
| DEPLOYMENT="secrets-store-csi-driver-operator" | ||
| GOCOVERDIR_PATH="/tmp/e2e-cover" | ||
|
|
||
| echo "--- E2E Coverage Setup ---" | ||
| echo "Coverage image: ${COVERAGE_IMAGE}" | ||
|
|
||
| echo "Discovering CSV from deployment ownerReference..." | ||
| csv=$(oc get deployment "${DEPLOYMENT}" -n "${NAMESPACE}" \ | ||
| -o jsonpath='{.metadata.ownerReferences[?(@.kind=="ClusterServiceVersion")].name}') | ||
| if [ -z "${csv}" ]; then | ||
| echo "Error: no CSV found for ${DEPLOYMENT}"; exit 1 | ||
| fi | ||
| echo "Found CSV: ${csv}" | ||
|
|
||
| echo "Patching CSV with coverage image and GOCOVERDIR env..." | ||
| oc patch csv "${csv}" -n "${NAMESPACE}" --type=json -p "[ | ||
| {\"op\": \"replace\", \"path\": \"/spec/install/spec/deployments/0/spec/template/spec/containers/0/image\", \"value\": \"${COVERAGE_IMAGE}\"}, | ||
| {\"op\": \"add\", \"path\": \"/spec/install/spec/deployments/0/spec/template/spec/containers/0/env/-\", \"value\": {\"name\": \"GOCOVERDIR\", \"value\": \"${GOCOVERDIR_PATH}\"}} | ||
| ]" | ||
|
Comment on lines
+225
to
+228
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JSON patch may fail if The Consider using a test-then-add approach or ensure the operator container always has at least one env var defined: Suggested defensive approach- oc patch csv "${csv}" -n "${NAMESPACE}" --type=json -p "[
- {\"op\": \"replace\", \"path\": \"/spec/install/spec/deployments/0/spec/template/spec/containers/0/image\", \"value\": \"${COVERAGE_IMAGE}\"},
- {\"op\": \"add\", \"path\": \"/spec/install/spec/deployments/0/spec/template/spec/containers/0/env/-\", \"value\": {\"name\": \"GOCOVERDIR\", \"value\": \"${GOCOVERDIR_PATH}\"}}
- ]"
+ # Check if env array exists, create if needed
+ has_env=$(oc get csv "${csv}" -n "${NAMESPACE}" -o jsonpath='{.spec.install.spec.deployments[0].spec.template.spec.containers[0].env}' 2>/dev/null)
+ if [ -z "${has_env}" ] || [ "${has_env}" = "null" ]; then
+ env_patch='{"op": "add", "path": "/spec/install/spec/deployments/0/spec/template/spec/containers/0/env", "value": [{"name": "GOCOVERDIR", "value": "'"${GOCOVERDIR_PATH}"'"}]}'
+ else
+ env_patch='{"op": "add", "path": "/spec/install/spec/deployments/0/spec/template/spec/containers/0/env/-", "value": {"name": "GOCOVERDIR", "value": "'"${GOCOVERDIR_PATH}"'"}}'
+ fi
+ oc patch csv "${csv}" -n "${NAMESPACE}" --type=json -p "[
+ {\"op\": \"replace\", \"path\": \"/spec/install/spec/deployments/0/spec/template/spec/containers/0/image\", \"value\": \"${COVERAGE_IMAGE}\"},
+ ${env_patch}
+ ]"🤖 Prompt for AI Agents |
||
|
|
||
| echo "Waiting for operator rollout with coverage image..." | ||
| sleep 5 | ||
| oc rollout status "deployment/${DEPLOYMENT}" -n "${NAMESPACE}" --timeout=180s | ||
|
|
||
| oc exec -n "${NAMESPACE}" "deploy/${DEPLOYMENT}" -- env | grep GOCOVERDIR || \ | ||
| echo "Warning: GOCOVERDIR not found in pod env (non-fatal)" | ||
| echo "--- Coverage setup complete ---" | ||
| dependencies: | ||
| - env: COVERAGE_IMAGE | ||
| name: secrets-store-csi-driver-operator-coverage | ||
| from: src | ||
| resources: | ||
| requests: | ||
| cpu: 100m | ||
| - as: test-e2e | ||
| cli: latest | ||
| commands: make test-e2e | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: openshift/release
Length of output: 8693
🏁 Script executed:
Repository: openshift/release
Length of output: 2048
🏁 Script executed:
Repository: openshift/release
Length of output: 1000
🏁 Script executed:
Repository: openshift/release
Length of output: 43
🏁 Script executed:
Repository: openshift/release
Length of output: 14132
Coverage data will be lost after sending SIGTERM to the container.
When SIGTERM is sent to PID 1, the Go runtime flushes coverage to
/tmp/e2e-coverin the current container instance. However,/tmpis part of the container's ephemeral filesystem with no persistent volume backing it. When the container restarts, Kubernetes creates a new container instance with a fresh/tmp, discarding the old container's filesystem entirely. The subsequentoc cpwill copy from the new container's empty/tmp/e2e-coverdirectory.To fix this, use a persistent volume (emptyDir or hostPath) mounted at the coverage directory path, or refactor to collect coverage data before triggering the container restart.
🤖 Prompt for AI Agents