From e339af03ad0b9c0a683c861a4c5163c5a4493ffc Mon Sep 17 00:00:00 2001 From: Swarup Ghosh Date: Fri, 8 May 2026 01:46:27 +0530 Subject: [PATCH 1/2] poc(prow): Run a Claude agent orchestrated by Prow Job in an ephemeral namespace using the oape-ai-e2e agent Co-authored-by: Claude Opus 4.6 Signed-off-by: Swarup Ghosh --- .../openshift-eng-oape-ai-e2e-main.yaml | 200 +++++++++++++++++- ...shift-eng-oape-ai-e2e-main-presubmits.yaml | 74 +++++++ 2 files changed, 273 insertions(+), 1 deletion(-) diff --git a/ci-operator/config/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main.yaml b/ci-operator/config/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main.yaml index 82f7a68a1bf93..4bb055ff50a67 100644 --- a/ci-operator/config/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main.yaml +++ b/ci-operator/config/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main.yaml @@ -12,9 +12,13 @@ images: to: gh-token-minter - dockerfile_path: images/go-server.Dockerfile to: go-server + - dockerfile_path: prow-workflow/input.Dockerfile + to: workflow-input promotion: to: - - name: ai-e2e-agent + - excluded_images: + - workflow-input + name: ai-e2e-agent namespace: oape tag_by_commit: true resources: @@ -24,6 +28,200 @@ resources: requests: cpu: 100m memory: 200Mi +tests: +- always_run: false + as: run-workflow + run_if_changed: ^prow-workflow/ + steps: + env: + BONFIRE_NAMESPACE_DURATION: 3h + test: + - as: extract-params + commands: | + cp /params.env "${SHARED_DIR}/params.env" + cat "${SHARED_DIR}/params.env" + from: workflow-input + resources: + requests: + cpu: 100m + memory: 128Mi + - as: deploy-and-run + commands: | + set -euo pipefail + + # --- Ephemeral namespace access --- + export KUBECONFIG="${SHARED_DIR}/ephemeral-kubeconfig" + NAMESPACE=$(cat "${SHARED_DIR}/ephemeral-namespace") + oc project "${NAMESPACE}" + + # Load workflow params + source "${SHARED_DIR}/params.env" + + # --- Create secrets from mounted CI credentials --- + oc create secret generic gcloud-adc \ + --from-file=application_default_credentials.json=/var/run/gcloud-adc/application_default_credentials.json + oc create secret generic github-app \ + --from-file=private-key.pem=/var/run/github-app/private-key.pem + + # --- Create worker ConfigMap (env vars) --- + oc create configmap shift-worker-config \ + --from-literal=CLAUDE_CODE_USE_VERTEX=1 \ + --from-literal=CLOUD_ML_REGION=global \ + --from-literal=ANTHROPIC_VERTEX_PROJECT_ID=itpc-gcp-hcm-pe-eng-claude \ + --from-literal=ANTHROPIC_MODEL=claude-opus-4-6 + + # --- Deploy gh-token-minter --- + cat </dev/null; then + echo "Workflow completed successfully." + else + echo "Workflow failed." + exit 1 + fi + credentials: + - mount_path: /var/run/gcloud-adc + name: oap-lts-claude-gcp-vertex-sa + namespace: test-credentials + - mount_path: /var/run/github-app + name: openshift-app-platform-shift-github-bot + namespace: test-credentials + dependencies: + - env: AGENT_WORKER_IMAGE + name: agent-worker + - env: GH_TOKEN_MINTER_IMAGE + name: gh-token-minter + from_image: + name: cli-jq + namespace: ocp + tag: latest + resources: + requests: + cpu: 100m + memory: 256Mi + timeout: 2h0m0s + workflow: ephemeral-namespace zz_generated_metadata: branch: main org: openshift-eng diff --git a/ci-operator/jobs/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main-presubmits.yaml b/ci-operator/jobs/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main-presubmits.yaml index 35fd270a3bda0..67c75f322859c 100644 --- a/ci-operator/jobs/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main-presubmits.yaml +++ b/ci-operator/jobs/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main-presubmits.yaml @@ -55,3 +55,77 @@ presubmits: secret: secretName: result-aggregator trigger: (?m)^/test( | .* )images,?($|\s.*) + - agent: kubernetes + always_run: false + branches: + - ^main$ + - ^main- + cluster: build05 + context: ci/prow/run-workflow + decorate: true + decoration_config: + skip_cloning: true + labels: + ci.openshift.io/generator: prowgen + pj-rehearse.openshift.io/can-be-rehearsed: "true" + name: pull-ci-openshift-eng-oape-ai-e2e-main-run-workflow + rerun_command: /test run-workflow + run_if_changed: ^prow-workflow/ + spec: + containers: + - args: + - --gcs-upload-secret=/secrets/gcs/service-account.json + - --image-import-pull-secret=/etc/pull-secret/.dockerconfigjson + - --lease-server-credentials-file=/etc/boskos/credentials + - --report-credentials-file=/etc/report/credentials + - --target=run-workflow + command: + - ci-operator + env: + - name: HTTP_SERVER_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + image: quay-proxy.ci.openshift.org/openshift/ci:ci_ci-operator_latest + imagePullPolicy: Always + name: "" + ports: + - containerPort: 8080 + name: http + resources: + requests: + cpu: 10m + volumeMounts: + - mountPath: /etc/boskos + name: boskos + readOnly: true + - mountPath: /secrets/gcs + name: gcs-credentials + readOnly: true + - mountPath: /secrets/manifest-tool + name: manifest-tool-local-pusher + readOnly: true + - mountPath: /etc/pull-secret + name: pull-secret + readOnly: true + - mountPath: /etc/report + name: result-aggregator + readOnly: true + serviceAccountName: ci-operator + volumes: + - name: boskos + secret: + items: + - key: credentials + path: credentials + secretName: boskos-credentials + - name: manifest-tool-local-pusher + secret: + secretName: manifest-tool-local-pusher + - name: pull-secret + secret: + secretName: registry-pull-credentials + - name: result-aggregator + secret: + secretName: result-aggregator + trigger: (?m)^/test( | .* )run-workflow,?($|\s.*) From 3e8ff568e40ba0af8d8bf2a37fb89fce0b14968b Mon Sep 17 00:00:00 2001 From: Swarup Ghosh Date: Fri, 8 May 2026 12:32:37 +0530 Subject: [PATCH 2/2] poc(prow): [2/2 approach] use inline built-ins w/o using ephemeral namespace Signed-off-by: Swarup Ghosh --- .../openshift-eng-oape-ai-e2e-main.yaml | 218 +++++------------- 1 file changed, 53 insertions(+), 165 deletions(-) diff --git a/ci-operator/config/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main.yaml b/ci-operator/config/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main.yaml index 4bb055ff50a67..166ef78592eef 100644 --- a/ci-operator/config/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main.yaml +++ b/ci-operator/config/openshift-eng/oape-ai-e2e/openshift-eng-oape-ai-e2e-main.yaml @@ -33,9 +33,7 @@ tests: as: run-workflow run_if_changed: ^prow-workflow/ steps: - env: - BONFIRE_NAMESPACE_DURATION: 3h - test: + pre: - as: extract-params commands: | cp /params.env "${SHARED_DIR}/params.env" @@ -45,183 +43,73 @@ tests: requests: cpu: 100m memory: 128Mi - - as: deploy-and-run + - as: mint-gh-token commands: | set -euo pipefail + GH_APP_ID=$(cat /var/run/github-app/app-id) + PEM_PATH="/var/run/github-app/private-key.pem" - # --- Ephemeral namespace access --- - export KUBECONFIG="${SHARED_DIR}/ephemeral-kubeconfig" - NAMESPACE=$(cat "${SHARED_DIR}/ephemeral-namespace") - oc project "${NAMESPACE}" - - # Load workflow params - source "${SHARED_DIR}/params.env" - - # --- Create secrets from mounted CI credentials --- - oc create secret generic gcloud-adc \ - --from-file=application_default_credentials.json=/var/run/gcloud-adc/application_default_credentials.json - oc create secret generic github-app \ - --from-file=private-key.pem=/var/run/github-app/private-key.pem - - # --- Create worker ConfigMap (env vars) --- - oc create configmap shift-worker-config \ - --from-literal=CLAUDE_CODE_USE_VERTEX=1 \ - --from-literal=CLOUD_ML_REGION=global \ - --from-literal=ANTHROPIC_VERTEX_PROJECT_ID=itpc-gcp-hcm-pe-eng-claude \ - --from-literal=ANTHROPIC_MODEL=claude-opus-4-6 - - # --- Deploy gh-token-minter --- - cat < "${SHARED_DIR}/gh-token" + credentials: + - mount_path: /var/run/github-app + name: openshift-app-platform-shift-github-bot + namespace: test-credentials + from: agent-worker + resources: + requests: + cpu: 100m + memory: 128Mi + test: + - as: agent-workflow + commands: | + set -euo pipefail + source "${SHARED_DIR}/params.env" + export EP_URL REPO_URL BASE_BRANCH - echo "Agent-worker Job shift-workflow-${JOB_ID} created." + set +x + export GH_TOKEN + GH_TOKEN=$(cat "${SHARED_DIR}/gh-token") - # --- Wait for pod, stream logs, check result --- - oc wait --for=condition=Ready pod -l job-name=shift-workflow-${JOB_ID} --timeout=300s || true - POD=$(oc get pods -l job-name=shift-workflow-${JOB_ID} -o jsonpath='{.items[0].metadata.name}') - oc logs -f "${POD}" || true + export GOOGLE_APPLICATION_CREDENTIALS="/var/run/gcloud-adc/application_default_credentials.json" + export CLAUDE_CODE_USE_VERTEX="1" + export CLOUD_ML_REGION="global" + export ANTHROPIC_VERTEX_PROJECT_ID="itpc-gcp-hcm-pe-eng-claude" + export ANTHROPIC_MODEL="claude-opus-4-6" + export PYTHONUNBUFFERED=1 - # Check final status - if oc wait --for=condition=complete --timeout=30s job/shift-workflow-${JOB_ID} 2>/dev/null; then - echo "Workflow completed successfully." - else - echo "Workflow failed." - exit 1 - fi + gh auth setup-git && python3.11 main.py credentials: - mount_path: /var/run/gcloud-adc name: oap-lts-claude-gcp-vertex-sa namespace: test-credentials - - mount_path: /var/run/github-app - name: openshift-app-platform-shift-github-bot - namespace: test-credentials - dependencies: - - env: AGENT_WORKER_IMAGE - name: agent-worker - - env: GH_TOKEN_MINTER_IMAGE - name: gh-token-minter - from_image: - name: cli-jq - namespace: ocp - tag: latest + from: agent-worker resources: requests: - cpu: 100m - memory: 256Mi - timeout: 2h0m0s - workflow: ephemeral-namespace + cpu: "1" + memory: 500Mi + timeout: 2h30m0s zz_generated_metadata: branch: main org: openshift-eng