fix(ci): cache kubeconform schemas across Test/Coverage jobs - #476
Conversation
Consumers whose Go tests exercise kubeconform-based schema validation (ksail's pkg/client/kubeconform) re-fetch every JSON schema from raw.githubusercontent.com on every cold CI job, since nothing persisted the local cache dir the client already builds across runs. This is what tripped upstream 429 rate-limiting portfolio-wide (2026-07-09), failing Test/Coverage on effectively every open ksail PR. Restore (and re-save) ~/.cache/ksail/kubeconform via actions/cache in both the Test and Coverage jobs — additive, harmless no-op for repos that never populate the path. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis change updates 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
Code Coverage OverviewLanguages: Go, C# Go / code-coverage/testThe overall coverage remains at 50%, unchanged from the C# / code-coverage/dotnetThe overall coverage remains at 100%, unchanged from the Updated |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/validate-go-project.yaml:
- Around line 645-661: The kubeconform cache save key is colliding between the
`test` and `coverage` jobs because both `actions/cache` steps in the workflow
use the same `kubeconform-schema-cache-v1-${{ github.run_id }}` key. Update the
cache key in both restore/save steps to include a per-job discriminator such as
`${{ github.job }}` (while keeping the existing prefix and restore-keys pattern)
so `test` and `coverage` can save distinct cache entries without overwriting
each other.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 48d343bf-cbcc-4d25-a713-9cd08f2205b6
📒 Files selected for processing (1)
.github/workflows/validate-go-project.yaml
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
.github/workflows/*.yaml
📄 CodeRabbit inference engine (AGENTS.md)
.github/workflows/*.yaml: Reusable workflows must use theworkflow_calltrigger.
Reusable workflows must pin all remote actions to commit SHAs, usingowner/repo@<sha> # <version>; first-party self-references must not be remote references.
Reusable workflows must includestep-security/harden-runneras the first step of every job, withegress-policy: audit.
Reusable workflows must set top-levelpermissions: {}and grant permissions per job.
Reusable workflows must setpersist-credentials: falseonactions/checkoutunless the job pushes changes.
Workflows used as org-level repository rulesets must include bothpull_requestandmerge_grouptriggers in addition toworkflow_call.
Every new action or reusable workflow must have a corresponding self-test job inci.yaml, wired intoci-required-checksin both theneeds:list and thejob-resultsinput.
Theci-required-checksjob must run withif: ${{ always() }}and fail if any listed job result is notsuccess.
Files:
.github/workflows/validate-go-project.yaml
🔇 Additional comments (1)
.github/workflows/validate-go-project.yaml (1)
655-655: 🔒 Security & PrivacyNo change needed for the
actions/cachepin.> Likely an incorrect or invalid review comment.
✅MegaLinter analysis: Success
Notices📣 MegaLinter 9.5.0 is out! Discover the new features and security recommendations in the release announcement. (Skip this info by defining See detailed reports in MegaLinter artifacts Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining
|
CodeRabbit: both jobs used the identical
kubeconform-schema-cache-v1-${{ github.run_id }} key, so their end-of-job
saves collided (only one job's cache entry actually persists). Scope each
job's key/restore-keys by ${{ github.job }} so both entries save
independently.
🤖 Generated by the Daily AI Assistant
Same defect as the platform companion fix: the single actions/cache step only saves via its automatic post-job hook, so a Test/Coverage failure — e.g. the very rate-limit this cache exists to avoid — could skip persisting schemas already fetched that run. Split restore/save so save runs with if: always() in both jobs. 🤖 Generated by the Daily AI Assistant
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/validate-go-project.yaml (1)
663-665: 🧹 Nitpick | 🔵 TrivialRun-id-based key means the save step runs (and creates a new cache entry) on nearly every job execution.
Since the key embeds
github.run_id,cache-hitwill only be'true'on a re-run of the same run (samerun_id); on any fresh run it's always a miss, so the save step fires every time regardless of prior guard, continuously creating new cache entries under thekubeconform-schema-cache-v1-${{ github.job }}-prefix. This is presumably intentional for the "persist on failure" goal, but it means cache storage will accumulate many short-lived entries subject to GitHub's repo-wide LRU eviction rather than converging on a stable, reusable entry. Worth being aware of for capacity planning if the repo's overall cache usage grows tight.Also applies to: 742-744
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/validate-go-project.yaml around lines 663 - 665, The kubeconform schema cache key in the cache step is tied to github.run_id, which forces a new cache entry on almost every run. Update the cache configuration in the affected workflow sections to use a stable primary key based on the job and cache version, and keep the restore-keys prefix for reuse across runs; if you still need “persist on failure” behavior, handle that separately so the main cache entry can actually be reused.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/validate-go-project.yaml:
- Around line 671-677: The kubeconform cache save step is currently guarded only
by always(), which still runs during job cancellation and can persist partial
state. Update both cache save steps in the workflow to use the same
cancellation-safe condition by adding !cancelled() alongside the existing
cache-hit check, referencing the kubeconform cache save actions so they are
skipped when the job is being cancelled.
---
Outside diff comments:
In @.github/workflows/validate-go-project.yaml:
- Around line 663-665: The kubeconform schema cache key in the cache step is
tied to github.run_id, which forces a new cache entry on almost every run.
Update the cache configuration in the affected workflow sections to use a stable
primary key based on the job and cache version, and keep the restore-keys prefix
for reuse across runs; if you still need “persist on failure” behavior, handle
that separately so the main cache entry can actually be reused.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: a8f0030a-1cfb-46db-a143-1709b4effc98
📒 Files selected for processing (1)
.github/workflows/validate-go-project.yaml
📜 Review details
⏰ Context from checks skipped due to timeout. (26)
- GitHub Check: [Test] Validate Go Project / 🧹 Lint - mega-linter
- GitHub Check: [Test] Zizmor - Default Settings / zizmor
- GitHub Check: [Test] Delete Workflow Runs - Specific Pattern / Delete workflow runs
- GitHub Check: [Test] Create Release - Dry Run / Release
- GitHub Check: [Test] Delete Workflow Runs - Minimal Parameters / Delete workflow runs
- GitHub Check: [Test] Run .NET Tests / test (windows-latest)
- GitHub Check: [Test] Run .NET Tests / test (ubuntu-latest)
- GitHub Check: [Test] Delete Workflow Runs - All Workflows / Delete workflow runs
- GitHub Check: [Test] Govulncheck Allowlist - Strict Path Blocks
- GitHub Check: [Test] Govulncheck Allowlist - Allowlisted Advisory Passes
- GitHub Check: [Test] Validate Go Project - Test Gate Blocks
- GitHub Check: [Test] Validate Go Project - Lint Gate Blocks
- GitHub Check: test-setup-go-toolchain (windows-latest)
- GitHub Check: test-run-dotnet-tests (macos-latest)
- GitHub Check: test-setup-go-toolchain (macos-latest)
- GitHub Check: test-setup-ksail-cli (macos-latest)
- GitHub Check: test-run-dotnet-tests (ubuntu-latest)
- GitHub Check: test-free-disk-space
- GitHub Check: test-run-dotnet-tests (windows-latest)
- GitHub Check: test-setup-ksail-cli (ubuntu-latest)
- GitHub Check: test-update-agent-skills-noop (macos-latest)
- GitHub Check: test-setup-agent-skills-inline (macos-latest)
- GitHub Check: [Test] Run .NET Tests - Gate Blocks
- GitHub Check: zizmor
- GitHub Check: Analyze (actions)
- GitHub Check: zizmor
🧰 Additional context used
📓 Path-based instructions (1)
.github/workflows/*.yaml
📄 CodeRabbit inference engine (AGENTS.md)
.github/workflows/*.yaml: Reusable workflows must use theworkflow_calltrigger.
Reusable workflows must pin all remote actions to commit SHAs, usingowner/repo@<sha> # <version>; first-party self-references must not be remote references.
Reusable workflows must includestep-security/harden-runneras the first step of every job, withegress-policy: audit.
Reusable workflows must set top-levelpermissions: {}and grant permissions per job.
Reusable workflows must setpersist-credentials: falseonactions/checkoutunless the job pushes changes.
Workflows used as org-level repository rulesets must include bothpull_requestandmerge_grouptriggers in addition toworkflow_call.
Every new action or reusable workflow must have a corresponding self-test job inci.yaml, wired intoci-required-checksin both theneeds:list and thejob-resultsinput.
Theci-required-checksjob must run withif: ${{ always() }}and fail if any listed job result is notsuccess.
Files:
.github/workflows/validate-go-project.yaml
🔇 Additional comments (1)
.github/workflows/validate-go-project.yaml (1)
645-677: Cache key collision fix confirmed.The
${{ github.job }}discriminator now added to both the key and restore-keys prefix correctly resolves the previously-flagged collision between thetestandcoveragejobs.Also applies to: 734-759
CodeRabbit: if: always() also fires while the job is being cancelled, where attempting a cache save is unnecessary and can race the runner teardown. Use !cancelled() instead — still saves on failure, skips on cancellation. 🤖 Generated by the Daily AI Assistant
Re: the "run-id-based key accumulates many cache entries" outside-diff nitpick — this is intentional, not an oversight. A stable (non-run-id) key would hit exact-match on the second run and skip the save step (per its own Applied the other two findings (cache-key collision → job-scoped key; save-on-failure → explicit restore/save split, now refined to @coderabbitai review |
|
Kicking off a fresh review now to check the job-scoped key fix and the ✏️ Learnings added
✅ Action performedReview finished.
|

Why
A portfolio-wide
raw.githubusercontent.com429 rate-limit is currently failing the🧪 Test/📊 Code Coveragejobs (and ksail's own System-Test matrix) on effectively every open ksail PR, including two of the Daily AI Assistant's own promoted PRs. Root cause: ksail's Go tests exercise real kubeconform schema validation with no cache persisted across CI jobs, so every job re-fetches every JSON schema from GitHub's raw CDN — heavy, repeated traffic across the whole matrix is what trips the upstream rate limit.What
Adds an
actions/cachestep to this reusable workflow'stestandcoveragejobs that restores/persists~/.cache/ksail/kubeconform— the local schema-cache directory ksail's kubeconform client already builds internally (validator.Opts.Cache), just never had anywhere to persist between ephemeral runners. Purely additive; a harmless no-op for any consumer repo that doesn't exercise this code path.Fixes the recurring rate-limit breakage blocking
ksail#5950/ksail#5951(both CI-blocked, otherwise merge-ready) and the wider dependabot/system-test queue.