The ODH Dashboard calls Kubernetes APIs to manage Kueue and Kubeflow Trainer resources. The dashboard team does not control those upstream operators. When they change — and they do, without warning — the dashboard breaks.
Until recently, the team found out the same way every time: a nightly E2E test failed, someone filed a Jira ticket, and the fix happened after the fact. There was no proactive detection. No early warning. Two Jira blockers confirmed the pattern — RHOAIENG-58488 (Kueue API version change) and RHOAIENG-88520 (Trainer immutability change) — both discovered in production.
The missing piece was noticed by multiple engineers independently:
"I think we should be notified/informed about any upcoming Kueue version upgrades so we could track these and keep an eye out for them."
"I see this was done at very last moment… way after code freeze for 3.5 GA. Is there any channel which communicates this?"
"I have some concerns on how we will handle the fact RHBoK can be lifecycled independent of RHOAI — if RHBoK 2.0 suddenly becomes available, how is Dashboard intended to react on an unsupported API?"
Three separate engineers. Three separate messages. All asking for the same thing. This pipeline is the answer.
The pipeline runs every night. It fetches the latest releases of Kueue and Kubeflow Trainer from GitHub, spins up a real Kubernetes cluster, and runs three layers of tests against it. If anything breaks, a Slack notification goes to the team before anyone starts their day.
The three layers each catch a different class of problem:
kubectl --dry-run=server. Webhook rejections and label errors surface here.The Kueue and Trainer versions tested are always the latest from GitHub releases — whatever upstream shipped that week. Layer 1 runs on every PR; Layers 2 and 3 run nightly on a fresh Kind cluster.
Four specific incidents drove the design of the pipeline. Each one had already caused a production problem before the sentinel existed. Each maps to one of the layers above.
RHOAIENG-58488What happened: Kueue promoted its storage API from v1beta1 to v1beta2. The dashboard was still calling v1beta1 — pausing and resuming RayJobs failed silently on any cluster running Kueue 1.3.x. No error surfaced in the UI. The workloads just never transitioned.
Steps taken:
v1beta1 to v1beta2 across the codebase✓ Covered by Layer 1 — Contract Tests
RHOAIENG-88520What happened: Kubeflow Trainer made spec.trainer immutable after job creation in v2.3.0. The dashboard's scale feature was PATCHing that field. The cluster silently rejected the request. The scale operation appeared to succeed in the UI but nothing changed on the cluster.
Steps taken:
✓ Covered by Layer 2 + Layer 3
What happened: Kueue's admission webhook requires the kueue.x-k8s.io/queue-name label on all managed workloads. If the label is absent, or the webhook changes how it validates label format, workloads are silently rejected at the cluster. The dashboard shows the resource as created; it never actually runs.
Steps taken:
kubeconform checks with live kubectl --dry-run=server against a real cluster✓ Covered by Layer 2 — API Dry-Run
RHOAIENG-85382What happened: A timing issue between Kueue's admission webhook and the scheduler caused priority classes to not always be applied on HardwareProfile-backed workloads. The failure was intermittent and cluster-configuration-dependent — hard to reproduce locally, invisible in unit tests.
Steps taken:
✓ Covered by Layer 3 — Integration Smoke
GitHub Actions workflow in odh-automations, scheduled at 06:30 UTC daily. Three jobs: Schema Check, API & Integration Tests, Report & Notify. Each job writes a per-test summary table to the workflow run page — pass/fail, version tested, detail text. No log digging required.
🔗 Sample pipeline run — Kueue v0.19.3 + Trainer v2.3.0, all layers green
Every run posts to Slack. Pass looks like this: