Skip to content

fix(ci): cache kubeconform schemas across Test/Coverage jobs - #476

Merged
botantler-1[bot] merged 4 commits into
mainfrom
claude/kubeconform-schema-cache
Jul 9, 2026
Merged

fix(ci): cache kubeconform schemas across Test/Coverage jobs#476
botantler-1[bot] merged 4 commits into
mainfrom
claude/kubeconform-schema-cache

Conversation

@devantler

Copy link
Copy Markdown
Contributor

🤖 Generated by the Daily AI Assistant

Why

A portfolio-wide raw.githubusercontent.com 429 rate-limit is currently failing the 🧪 Test / 📊 Code Coverage jobs (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/cache step to this reusable workflow's test and coverage jobs 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.

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>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change updates validate-go-project.yaml to add caching for the kubeconform schema directory. The test and coverage jobs now restore and save ~/.cache/ksail/kubeconform with a versioned cache key based on github.job and github.run_id, plus a matching restore prefix.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: caching kubeconform schemas across CI test and coverage jobs.
Description check ✅ Passed The description is directly related to the workflow cache change and its motivation, so it matches the changeset.

Comment @coderabbitai help to get the list of available commands.

@github-code-quality

github-code-quality Bot commented Jul 9, 2026

Copy link
Copy Markdown

Code Coverage Overview

Languages: Go, C#

Go / code-coverage/test

The overall coverage remains at 50%, unchanged from the main branch.

C# / code-coverage/dotnet

The overall coverage remains at 100%, unchanged from the main branch.


Updated July 09, 2026 02:38 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between a233fab and d686490.

📒 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 the workflow_call trigger.
Reusable workflows must pin all remote actions to commit SHAs, using owner/repo@<sha> # <version>; first-party self-references must not be remote references.
Reusable workflows must include step-security/harden-runner as the first step of every job, with egress-policy: audit.
Reusable workflows must set top-level permissions: {} and grant permissions per job.
Reusable workflows must set persist-credentials: false on actions/checkout unless the job pushes changes.
Workflows used as org-level repository rulesets must include both pull_request and merge_group triggers in addition to workflow_call.
Every new action or reusable workflow must have a corresponding self-test job in ci.yaml, wired into ci-required-checks in both the needs: list and the job-results input.
The ci-required-checks job must run with if: ${{ always() }} and fail if any listed job result is not success.

Files:

  • .github/workflows/validate-go-project.yaml
🔇 Additional comments (1)
.github/workflows/validate-go-project.yaml (1)

655-655: 🔒 Security & Privacy

No change needed for the actions/cache pin.

			> Likely an incorrect or invalid review comment.

Comment thread .github/workflows/validate-go-project.yaml
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

MegaLinter analysis: Success

Descriptor Linter Files Fixed Errors Warnings Elapsed time
✅ COPYPASTE jscpd yes no no 0.39s
✅ GO golangci-lint yes yes no no 16.93s
✅ GO revive 2 0 0 0.18s
✅ REPOSITORY betterleaks yes no no 0.6s
✅ REPOSITORY checkov yes no no 23.59s
✅ REPOSITORY gitleaks yes no no 0.06s
✅ REPOSITORY git_diff yes no no 0.02s
✅ REPOSITORY grype yes no no 54.93s
✅ REPOSITORY osv-scanner yes no no 0.27s
✅ REPOSITORY secretlint yes no no 1.44s
✅ REPOSITORY syft yes no no 1.86s
✅ REPOSITORY trivy yes no no 14.38s
✅ REPOSITORY trivy-sbom yes no no 0.22s
✅ REPOSITORY trufflehog yes no no 3.47s

Notices

📣 MegaLinter 9.5.0 is out! Discover the new features and security recommendations in the release announcement. (Skip this info by defining SECURITY_SUGGESTIONS: false)

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 FLAVOR_SUGGESTIONS: false)

  • Documentation: Custom Flavors
  • Command: npx mega-linter-runner@9.6.0 --custom-flavor-setup --custom-flavor-linters COPYPASTE_JSCPD,GO_GOLANGCI_LINT,GO_REVIVE,REPOSITORY_CHECKOV,REPOSITORY_GIT_DIFF,REPOSITORY_GITLEAKS,REPOSITORY_BETTERLEAKS,REPOSITORY_GRYPE,REPOSITORY_OSV_SCANNER,REPOSITORY_SECRETLINT,REPOSITORY_SYFT,REPOSITORY_TRIVY,REPOSITORY_TRIVY_SBOM,REPOSITORY_TRUFFLEHOG

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🔵 Trivial

Run-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-hit will only be 'true' on a re-run of the same run (same run_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 the kubeconform-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

📥 Commits

Reviewing files that changed from the base of the PR and between fae7678 and 6f74f14.

📒 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 the workflow_call trigger.
Reusable workflows must pin all remote actions to commit SHAs, using owner/repo@<sha> # <version>; first-party self-references must not be remote references.
Reusable workflows must include step-security/harden-runner as the first step of every job, with egress-policy: audit.
Reusable workflows must set top-level permissions: {} and grant permissions per job.
Reusable workflows must set persist-credentials: false on actions/checkout unless the job pushes changes.
Workflows used as org-level repository rulesets must include both pull_request and merge_group triggers in addition to workflow_call.
Every new action or reusable workflow must have a corresponding self-test job in ci.yaml, wired into ci-required-checks in both the needs: list and the job-results input.
The ci-required-checks job must run with if: ${{ always() }} and fail if any listed job result is not success.

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 the test and coverage jobs.

Also applies to: 734-759

Comment thread .github/workflows/validate-go-project.yaml
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
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 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 cache-hit != 'true' guard), so any schema fetched for the first time after that point would never persist — GitHub's actions/cache also refuses to overwrite an existing key, so a stable key can't self-update either. The run-id suffix with restore-keys prefix matching is the standard "ever-growing/rolling cache" pattern for exactly this reason (schemas are added to the catalog over time, not fixed). Entry growth is bounded by GitHub's own per-repo cache eviction (10GB LRU), which is the intended backstop here — not a capacity risk worth engineering around. Keeping the run-id key as-is.

Applied the other two findings (cache-key collision → job-scoped key; save-on-failure → explicit restore/save split, now refined to !cancelled() per the follow-up review).

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

@devantler Thanks for the detailed explanation — that makes sense. Given that actions/cache won't overwrite an existing key and the save step is gated on cache-hit != 'true', a stable key would indeed get stuck after the first cache hit and never pick up newly-fetched schemas. The run-id + restore-keys prefix pattern is the right call here, with GitHub's 10GB LRU eviction as the natural backstop. Withdrawing that nitpick.

Kicking off a fresh review now to check the job-scoped key fix and the !cancelled() restore/save split.


✏️ Learnings added
Learnt from: devantler
URL: https://github.com/devantler-tech/actions/pull/476

Timestamp: 2026-07-09T02:38:29.124Z
Learning: Repo: devantler-tech/actions. In .github/workflows/validate-go-project.yaml, the kubeconform schema cache uses a run-id-based cache key (e.g., `kubeconform-schema-cache-v1-${{ github.job }}-${{ github.run_id }}`) with `restore-keys` prefix matching, combined with a save step guarded by `cache-hit != 'true'`. This is an intentional "rolling/ever-growing cache" pattern, not an oversight: a stable (non-run-id) key would exact-match on the second run, causing the save step to be skipped (due to its own cache-hit guard) so any newly fetched schemas would never persist; also `actions/cache` refuses to overwrite an existing key, so a stable key cannot self-update anyway. Cache size growth is bounded by GitHub's per-repo 10GB LRU eviction, which is the intended backstop rather than something to engineer around.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler
devantler marked this pull request as ready for review July 9, 2026 03:16
@botantler-1
botantler-1 Bot merged commit ee2354d into main Jul 9, 2026
106 checks passed
@botantler-1
botantler-1 Bot deleted the claude/kubeconform-schema-cache branch July 9, 2026 03:16
@github-project-automation github-project-automation Bot moved this from 🏃🏻‍♂️ In Progress to ✅ Done in 🌊 Project Board Jul 9, 2026
@botantler-1 botantler-1 Bot mentioned this pull request Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

1 participant