npx skills add ...
npx skills add openshift/lightspeed-service --skill investigate-ci-failure
npx skills add openshift/lightspeed-service --skill investigate-ci-failure
Investigate CI/Prow job failures on a GitHub pull request. Use when the user pastes a PR URL and asks about CI failures, red checks, test failures, or wants to understand why a job failed.
Given a PR URL (e.g. https://github.com/openshift/lightspeed-service/pull/2825), diagnose why CI jobs failed.
Parse org, repo, and PR number from the URL. Fetch metadata with gh:
This gives you the list of failed jobs and their Prow dashboard URLs.
From a Prow target_url like:
Derive:
https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/pr-logs/pull/{org}_{repo}/{pr}/{job_name}/{build_id}/https://storage.googleapis.com/test-platform-results/pr-logs/pull/{org}_{repo}/{pr}/{job_name}/{build_id}/{path}For each failed job, fetch artifacts in this order:
Check "passed": false and "result": "FAILURE".
This is the main ci-operator build log. It can be large (200KB+). Search from the end for:
failed / FAILED / error / ERRORstep .* failedTraceback, AssertionError, FAILED tests/)CrashLoopBackOff, OOMKilled, Error from server)The build log alone often doesn't tell the full story. Browse the GCS artifact directory to find step-specific logs, cluster state, and pod logs:
Full artifact tree for an e2e job:
Where to look by failure type:
| Symptom | Check these artifacts |
|---|---|
| Test assertion failure | e2e/build-log.txt + junit_e2e_*.xml |
| OLS service error/crash | {provider}/cluster/podlogs/lightspeed-app-server-*.log |
| Postgres issues | {provider}/cluster/podlogs/lightspeed-postgres-server-*.log |
| Deployment failure | {provider}/cluster/pods.yaml + deployments.yaml |
| Image build failure | build-logs/*.log |
| Cluster infra issue | gather-must-gather/artifacts/camgi.html + event-filter.html |
| CI namespace issues | build-resources/events.json + pods.json |
When you need to search across many files or the artifacts are too large
for WebFetch, download them to a temp directory using gsutil or gcloud storage:
The GCS bucket path mirrors the Prow URL: strip https://prow.ci.openshift.org/view/gs/
and prepend gs://.
When multiple jobs have failed, investigate each in a separate subagent (Task tool) to keep build-log context isolated and run fetches in parallel.
Compare the failure with the files changed in the PR. Common patterns:
| Failure type | Likely cause |
|---|---|
| Unit/integration test failure | Direct code bug in changed files |
| e2e cluster test failure | Infrastructure issue OR deployment-breaking change |
| Verify/lint failure | Formatting, type errors, or import issues |
| Image build failure | Dependency or Dockerfile issue |
| Flaky (passes on retest) | Known flake, not PR-related |
Check if the same job fails on main branch (flaky test) by looking at job history:
Summarize:
| Context | What it tests |
|---|---|
ci/prow/unit | make test-unit — pytest unit tests |
ci/prow/integration | make test-integration — integration tests |
ci/prow/verify | make verify — black, ruff, pylint, mypy, woke |
ci/prow/security | make security-check — bandit |
ci/prow/images | Container image build |
ci/prow/fips-image-scan-service | FIPS compliance scan |
ci/prow/e2e-ols-cluster | Full cluster e2e — deploys OLS + operator on OpenShift, runs make test-e2e |
tide | Merge readiness (labels, approvals) — not a test |
| Konflux | Supply chain security pipeline (separate from Prow) |
gh CLI for all GitHub API calls (PR metadata, statuses, checks, comments, files).WebFetch to browse GCS directories (gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/...).WebFetch to fetch raw log/JSON content (storage.googleapis.com/test-platform-results/...).https://prow.ci.openshift.org/view/gs/test-platform-results/pr-logs/pull/{org}_{repo}/{pr}/{job_name}/{build_id}GET storage.googleapis.com/.../finished.jsonGET storage.googleapis.com/.../build-log.txtGET gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/.../artifacts/{build_id}/
├── build-log.txt ← main ci-operator log (start here)
├── finished.json ← pass/fail + metadata
├── artifacts/
│ ├── ci-operator.log ← detailed ci-operator log
│ ├── junit_operator.xml ← top-level JUnit results
│ ├── ci-operator-step-graph.json ← step dependency graph
│ ├── ci-operator-metrics.json
│ ├── metadata.json
│ ├── build-logs/ ← container image build logs
│ │ ├── lightspeed-service-api-amd64.log
│ │ ├── root-amd64.log
│ │ └── src-amd64.log
│ ├── build-resources/ ← CI namespace state
│ │ ├── pods.json ← all pods in CI namespace
│ │ ├── events.json ← k8s events (useful for crashes)
│ │ ├── builds.json
│ │ ├── imagestreams.json
│ │ └── clusterClaim.json
│ ├── release/ ← cluster provisioning step
│ │ ├── build-log.txt
│ │ └── finished.json
│ └── e2e-ols-cluster/ ← test workflow steps
│ ├── ipi-install-rbac/ ← cluster RBAC setup
│ │ └── build-log.txt
│ ├── e2e/ ← THE ACTUAL TEST STEP
│ │ ├── build-log.txt ← test runner output (pytest)
│ │ ├── finished.json
│ │ └── artifacts/ ← per-provider test results
│ │ ├── junit_e2e_azure_openai.xml
│ │ ├── junit_e2e_openai.xml
│ │ ├── junit_e2e_watsonx.xml
│ │ ├── junit_e2e_rhelai_vllm.xml
│ │ ├── junit_e2e_rhoai_vllm.xml
│ │ ├── junit_e2e_*_tool_calling.xml
│ │ ├── junit_e2e_quota_limits.xml
│ │ └── {provider}/cluster/ ← cluster state per provider
│ │ ├── podlogs/
│ │ │ ├── lightspeed-app-server-*.log ← OLS service logs
│ │ │ ├── lightspeed-postgres-server-*.log
│ │ │ └── lightspeed-console-plugin-*.log
│ │ ├── olsconfig.yaml ← OLS config used
│ │ ├── pods.yaml
│ │ ├── deployments.yaml
│ │ ├── configmap.yaml
│ │ ├── services.yaml
│ │ └── routes.yaml
│ ├── gather-must-gather/ ← cluster diagnostics
│ │ └── artifacts/
│ │ ├── must-gather.tar ← full must-gather (large, ~25MB)
│ │ ├── camgi.html ← must-gather analysis report
│ │ └── event-filter.html
│ └── openshift-configure-cincinnati/TMPDIR=$(mktemp -d)
# Download a specific subdirectory
gcloud storage cp -r \
gs://test-platform-results/pr-logs/pull/{org}_{repo}/{pr}/{job_name}/{build_id}/artifacts/e2e-ols-cluster/e2e/artifacts/ \
"$TMPDIR/"https://prow.ci.openshift.org/job-history/gs/test-platform-results/pr-logs/directory/{job_name}