Skip to content

fix: stabilize kind-smoke CI deps (drop flaky Bitnami charts) - #29

Merged
cosmicBboy merged 9 commits into
mainfrom
fix/kind-smoke-deps
Jul 28, 2026
Merged

fix: stabilize kind-smoke CI deps (drop flaky Bitnami charts)#29
cosmicBboy merged 9 commits into
mainfrom
fix/kind-smoke-deps

Conversation

@cosmicBboy

Copy link
Copy Markdown
Collaborator

Problem

The kind-smoke CI job fails at Error: context deadline exceeded — the Bitnami minio Helm chart's --wait --timeout 5m deadline expires without the pod becoming Ready (failing run).

Root cause: Bitnami deprecated its free image catalog (Aug 2025), so the bitnami/postgresql and bitnami/minio charts now pull rolling :latest tags from a shrinking registry (visible in the Rolling tag detected warnings in the log). On 2-CPU GitHub runners this is slow and flaky — postgres barely made it, minio timed out.

Fix

Replace the pg and minio Bitnami charts with plain, pinned manifests using official upstream images:

  • postgres:16-alpine
  • minio/minio:RELEASE.2025-04-08T15-41-24Z (tag existence verified on Docker Hub)

These are throwaway smoke-test deps — the deploy-flyte-kind skill itself uses external hosted Postgres + S3/R2 — so determinism matters more than fidelity here. Details:

  • The Postgres Service keeps the name pg-postgresql that the flyte-binary step wires its DB host to (default user postgres / password flyte / db flyte all match).
  • Readiness probes (pg_isready, /minio/health/ready) gate kubectl rollout status instead of helm --wait.
  • No more Bitnami repo / rolling :latest dependency.

Validation

Ran the exact changed deps block on a real isolated kind cluster: both pods reach 1/1 Running in ~32s, versus the 5-min timeout that was being blown. bash -n passes.

🤖 Generated with Claude Code

cosmicBboy and others added 9 commits July 28, 2026 10:59
The kind-smoke CI job failed at `Error: context deadline exceeded` when the
Bitnami `minio` Helm chart's `--wait --timeout 5m` deadline expired without the
pod becoming Ready. Bitnami deprecated its free image catalog (Aug 2025), so
those charts now pull rolling `:latest` tags from a shrinking registry (see the
"Rolling tag detected" warnings), which is slow/flaky on 2-CPU GitHub runners.

Replace the `pg` and `minio` Bitnami charts with plain, pinned manifests using
official upstream images (postgres:16-alpine, minio/minio:RELEASE...). These are
throwaway smoke-test deps — the skill itself uses external hosted Postgres +
S3/R2 — so determinism matters more than fidelity. The Postgres Service keeps
the name `pg-postgresql` the flyte-binary step wires to, and readiness probes
gate `kubectl rollout status` instead of helm `--wait`.

Validated on a real kind cluster: both pods reach 1/1 Running in ~32s.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
No-op marker on the deploy-flyte-kind skill so the selector picks
skills=[deploy-flyte-kind] (runs flyte-evals) and run_kind=true (runs the
kind-smoke job against the updated deps). Revert before merge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two CI fixes:

1. kind-smoke: the flyte-binary install used flat v1 values keys
   (configuration.database.host/password, configuration.storage.provider) that
   the v2 flyte-binary chart silently ignores. The DB host stayed at its
   127.0.0.1 default, so the wait-for-db init container polled the wrong host
   forever and helm's --wait hit 'context deadline exceeded' (Init:0/1 for 10m —
   a hang, not slowness, so a longer timeout would not have helped). Switch to
   the v2 schema (configuration.database.postgres.*,
   configuration.storage.providerConfig.s3.*) via a values file mirroring the
   skill's values-local.yaml, pointing db at the in-cluster pg and storage at the
   in-cluster minio, and pre-create the bucket the chart expects. Drop the
   '|| true' so a real failure surfaces. Validated end-to-end on kind:
   flyte-binary reaches 1/1 Ready in ~75s.

2. flyte-evals: the job set UNION_API_KEY, but the flyte v2 CLI reads its API key
   from FLYTE_API_KEY. Source it from the repo secret DEMO_HOSTED_API_KEY.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The flyte-evals job used `flyte run`, which is fire-and-forget: it exits 0 as
soon as the run is launched, so CI went green even when the run failed on the
backend (e.g. the missing glm-api-key secret). Two changes make the job report
the real outcome:

- Add evals/workflows/run_ci.py: authenticates headlessly via FLYTE_API_KEY
  (init_from_api_key), submits the workflow, blocks on run.wait(), and exits
  non-zero unless the terminal phase is ACTION_PHASE_SUCCEEDED. The workflow
  invokes this instead of `flyte run`.
- eval_wf.main now raises when any scenario fails, so a completed-but-failing
  run ends in a non-SUCCEEDED phase and the job reflects eval results (this is
  what the old YAML comment claimed but nothing enforced). aggregate() still
  attaches the HTML scorecard before the raise, so the report survives.

Also drop GLM_API_KEY from the CI env — the judge key reaches task pods via the
Flyte secret `glm-api-key`, not the CI environment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The run reached the backend but failed with `No module named 'evals.harness'`.
copy_style="loaded_modules" only bundles modules imported at submission time,
but the harness imports evals.harness.* lazily inside the tasks and also reads
data files off disk (evals/manifest.yaml, evals/scenarios/**, and the skill dirs
under plugins/flyte/skills/**), all resolved relative to the repo root.

Switch the CI driver to copy_style="all" and pin root_dir to the repo root so the
entire tree is shipped. "all" still excludes .git/__pycache__/.venv via the
standard ignore list, and the tree is <1MB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A failing run only said "27 of 47 eval scenarios failed" with no indication of
which ones or why. Add per-scenario visibility:

- report.py: add reason() (one-line failure cause — first failing check, arm
  error, or failed judge with rationale) and failure_report() (plaintext
  per-scenario breakdown), reusable by the workflow and CI.
- eval_unit logs a PASS/FAIL line per scenario (with the reason) so each failure
  shows in its own map action's logs, live as the run progresses.
- main prints the full failure_report to the aggregate action's logs and names
  the failing scenarios in the RuntimeError, so they appear in the UI error
  banner too (not just the HTML scorecard on the report tab).
- run_ci.py points the operator at the run logs / report tab on failure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… on static-lint regressions

The 27 "failures" were all one infra cause — the default harness matrix
(opencode, pi, hermes) isn't installed in the eval image, so every trajectory
arm errored with "CLI not available" and, under binary pass/fail, counted as a
failure. That's not a skill regression, and binary pass/fail is the wrong signal
for LLM-driven trajectory evals anyway.

Rework the eval into a tracked rating rather than binary pass/fail:

- Unavailable harness -> SKIPPED, not failed. Excluded from the rating and from
  gating (you can't measure a skill from an agent that never ran). main filters
  unavailable harnesses up front so they show on the scorecard without spending
  a task pod per skip.
- Rating scale: each scenario already yields a [0,1] score (deterministic checks
  gate + LLM judge) and a treatment-control lift. aggregate now reports overall
  rating, mean lift, per-skill rating, and scored/skipped/errored/regression
  counts — a signal to track over time (HTML scorecard + logs).
- CI gates on REGRESSIONS only: scored *static* SKILL.md lint failures, the one
  deterministic, non-stochastic signal. Trajectory arms run a stochastic LLM
  agent, so their failures lower the tracked rating instead of hard-failing CI
  (which would flake per PR). Optional FLYTE_EVALS_MIN_RATING adds a floor.
- Status-aware scorecard/logs (✅ scored+pass · 🟡 scored soft · ❌ static
  regression · ⏭ skipped · ⚠ harness error) with per-scenario reasons.

Current repo: 20 static scored (rating 1.000, 0 regressions), 27 trajectory
skipped -> green. Trajectory ratings light up automatically once an agent CLI is
present in the image.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…name

The eval run SUCCEEDED (rating 1.0, 0 regressions) but the CI driver reported
failure: run.phase is a flyte.models.ActionPhase (a str-enum, e.g.
ActionPhase.SUCCEEDED / .name "SUCCEEDED" / .value "succeeded"), not the
protobuf name string "ACTION_PHASE_SUCCEEDED" the comparison assumed, so the
success check never matched. Compare against ActionPhase.SUCCEEDED and log the
phase name.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…--all

Remove the temporary ci-trigger comment from the deploy-flyte-kind skill now that
the fixes are validated (the PR's own eval changes are shared-infra, so both jobs
still run on the PR).

Make the nightly/manual full-matrix run explicit: add `evals.select --all`
(force_all -> all skills, run_kind, run_real) instead of the indirect "pretend
evals/manifest.yaml changed" trick. The schedule (07:00 UTC) and workflow_dispatch
now select the full matrix, so flyte-evals (incl. real tier) and kind-smoke run
nightly regardless of any diff.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cosmicBboy
cosmicBboy merged commit 8beebfc into main Jul 28, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant