fix(ci): reject incompatible Kubernetes and Talos pins - #3583
Conversation
@coderabbitai review |
|
✅ Action performedReview finished.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Team Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (8)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📜 Recent review details🧰 Additional context used🧠 Learnings (1)📚 Learning: 2026-08-04T13:06:25.700ZApplied to files:
🪛 golangci-lint (2.13.2)scripts/validate-talos-kubernetes-compatibility/main.go[error] 60-60: comparing with != will fail on wrapped errors. Use errors.Is to check for a specific error (errorlint) scripts/validate-talos-kubernetes-compatibility/main_test.go[error] 204-204: QF1001: could apply De Morgan's law (staticcheck) 🪛 OSV Scanner (2.5.0)go.mod[LOW] 15-15: golang.org/x/net 0.55.0: Parsing an invalid SVCB or HTTPS RR can panic in golang.org/x/net/dns/dnsmessage (GO-2026-5942) [LOW] 17-17: golang.org/x/text 0.37.0: Infinite loop on invalid input in golang.org/x/text (GO-2026-5970) [HIGH] 19-19: google.golang.org/grpc 1.81.0: Vulnerabilities in the xDS RBAC authorization engine and the HTTP/2 transport server implementation in google.golang.org/grpc (GO-2026-6061) [HIGH] 19-19: google.golang.org/grpc 1.81.0: gRPC-Go: xDS RBAC and HTTP/2 Vulnerabilities [HIGH] 19-19: google.golang.org/grpc 1.81.0: gRPC-Go: Heap Memory Exhaustion (OOM) via HTTP/2 DATA Frame Fragmentation 🔇 Additional comments (8)
📝 WalkthroughWalkthroughThe change adds a Go validator that reads Kubernetes and Talos version pins from Merge Risk: ⚪ Minimal · up to This adds pre-deployment validation for Kubernetes and Talos version pins across production paths. Unsupported or malformed combinations are blocked before deployment, with no remaining concrete merge-readiness risk identified. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 3 files. (5 skipped: 5 unsupported.) Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…points The sibling validator scripts in scripts/ document their functions (6/8 to 52/54); this one documented 0/2, which CodeRabbit's current-head pre-merge docstring check reported. Comment-only: no behaviour change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Readiness evaluation — exercised as a user, not reasoned about. Built the validator from this branch and ran the real binary against real inputs. Observed behaviour, exit codes as printed:
The middle row is the one that matters: this is the pairing Also run at this head: focused One review finding fixed since the green. CodeRabbit's current-head pre-merge docstring check reported 16.67% against an 80% threshold. Assessed on merit rather than waved: the sibling validators under That push stales the green review at |
@coderabbitai full review |
|
|
CodeRabbit refused this round at Recorded as CI is green at this head — |
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1baa2838c4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
ci.yaml's validate-talos job is pull_request-only, so a pairing pushed straight to main reached the manually dispatched CD route unchecked. Mirror the compatibility check onto the push event in validate-main.yaml, the same way validate-shared-publish-pin mirrors its PR gate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai full review |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Current commit and changed files =='
git rev-parse HEAD
git diff --name-status HEAD^ HEAD
printf '%s\n' '== Diff =='
git diff --unified=80 HEAD^ HEAD -- \
.github/workflows/ci.yaml \
go.mod \
go.sum \
scripts/validate-talos-kubernetes-compatibility
printf '%s\n' '== Validator structure =='
ast-grep outline scripts/validate-talos-kubernetes-compatibility --items all
printf '%s\n' '== Relevant workflow context =='
rg -n -C 12 'validate-talos|talos:|ksail\.prod\.yaml|setup-go|validate-talos-kubernetes-compatibility' .github/workflows/ci.yaml
printf '%s\n' '== Production pins =='
rg -n -C 3 'kubernetesVersion|talosVersion' ksail.prod.yaml
printf '%s\n' '== Sibling validator entry points =='
fd -t f 'main\.go|README\.md|main_test\.go' scripts -d 3 | sortLength of output: 21784 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Pull request metadata =='
gh pr view 3583 --repo devantler-tech/platform --json baseRefName,baseRefOid,headRefName,headRefOid,changedFiles,commits
base_oid="$(gh pr view 3583 --repo devantler-tech/platform --json baseRefOid --jq .baseRefOid)"
head_oid="$(git rev-parse HEAD)"
printf '%s\n' '== Full pull request changed files =='
git diff --name-status "${base_oid}...${head_oid}"
printf '%s\n' '== Full pull request diff for review targets =='
git diff --unified=100 "${base_oid}...${head_oid}" -- \
.github/workflows/ci.yaml \
.github/workflows/validate-main.yaml \
go.mod \
go.sum \
scripts/validate-talos-kubernetes-compatibility
printf '%s\n' '== Validator implementation =='
cat -n scripts/validate-talos-kubernetes-compatibility/main.go
printf '%s\n' '== Validator tests =='
cat -n scripts/validate-talos-kubernetes-compatibility/main_test.go
printf '%s\n' '== Current-head validate-main workflow change =='
git diff --unified=80 HEAD^ HEAD -- .github/workflows/validate-main.yaml
printf '%s\n' '== Full validate-main job context =='
rg -n -C 30 'validate-talos|CI - Required Checks|workflow_call|workflow_dispatch|merge_group|pull_request' .github/workflows/validate-main.yamlLength of output: 88151 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== CI workflow triggers and merge-group consumers =='
sed -n '1,80p' .github/workflows/ci.yaml
rg -n -C 12 'merge_group|deploy-prod|validate-talos|ci-required-checks' .github/workflows/ci.yaml
printf '%s\n' '== Production Talos pin and surrounding schema =='
rg -n -C 12 '^[[:space:]]*talos:|^[[:space:]]*version:[[:space:]]*v[0-9]' ksail.prod.yaml
printf '%s\n' '== Deployment and main-validation workflow references =='
rg -n -C 10 'validate-talos-kubernetes-compatibility|validate-talos|workflow_dispatch|ksail\.prod\.yaml' \
.github/workflows/cd.yaml \
.github/workflows/validate-main.yaml \
.github/workflows/ci.yaml
printf '%s\n' '== Existing workflow-wiring tests and validators =='
rg -n -C 8 'validate-main|validate-shared-publish-pin|workflow.*job|job.*workflow|paths-filter' \
scripts --glob '*.go' --glob '*.sh' --glob '*.yaml'
printf '%s\n' '== Talos compatibility API source, if available in module cache =='
mod_dir="$(go env GOMODCACHE 2>/dev/null || true)"
if [ -n "$mod_dir" ] && [ -d "$mod_dir" ]; then
fd -HI 'compatibility.*\.go|version.*\.go' "$mod_dir/github.com/siderolabs/talos/pkg/machinery@v1.13.9" \
-x sh -c 'printf "\n-- %s --\n" "$1"; rg -n -C 5 "func .*SupportedWith|func ParseTalosVersion|func ParseKubernetesVersion" "$1"' sh {} \; \
2>/dev/null || true
fiLength of output: 224538
You are interacting with an AI system. |
Two P1s reported by CodeRabbit at P1-1 — merge-group revision is unguarded. Confirmed: P1-2 — my Recording rather than fixing: both are real workflow-wiring changes across two files with a deploy path attached, and this run is out of time. Fixing them tired at the end of a run is how a deploy gate acquires a quiet hole. Next run picks this up with the two remedies above already specified. Method note, second occurrence today. This finding arrived through a CodeRabbit reply that again opened with "For best results, initiate chat on the files or code changes" and an |
|
Tip For best results, initiate chat on the files or code changes.
Both P1 findings remain open. Pull request The response formatting does not invalidate its findings. A chat-oriented CodeRabbit response can still contain substantive review results and must be assessed on its technical evidence. 🐇 ✏️ Learnings added
You are interacting with an AI system. |
Resolved both current-head P1s from CodeRabbit's review output in
Validation at this head: This push also merges Platform |
@coderabbitai full review |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== PR metadata =='
gh pr view 3583 --repo devantler-tech/platform \
--json baseRefName,baseRefOid,headRefName,headRefOid,changedFiles,commits
base_oid="$(gh pr view 3583 --repo devantler-tech/platform --json baseRefOid --jq .baseRefOid)"
head_oid="$(git rev-parse HEAD)"
printf '\n== Checked out HEAD ==\n%s\n' "$head_oid"
printf '%s\n' '== Full changed-file list =='
git diff --name-status "${base_oid}...${head_oid}"
printf '%s\n' '== Full PR diff =='
git diff --check "${base_oid}...${head_oid}"
git diff --unified=100 "${base_oid}...${head_oid}" -- \
.github/workflows/ci.yaml \
.github/workflows/cd.yaml \
.github/workflows/validate-main.yaml \
go.mod \
go.sum \
scripts/validate-talos-kubernetes-compatibility
printf '%s\n' '== Changed source outlines =='
ast-grep outline scripts/validate-talos-kubernetes-compatibility --items all
printf '%s\n' '== CI workflow gate context =='
rg -n -C 35 '^[[:space:]]*(validate-talos|deploy-prod):|merge_group|pull_request|needs:|validate-talos-kubernetes-compatibility' .github/workflows/ci.yaml
printf '%s\n' '== CD workflow gate context =='
rg -n -C 35 '^[[:space:]]*(validate-talos|deploy-prod):|workflow_dispatch|needs:|validate-talos-kubernetes-compatibility' .github/workflows/cd.yaml
printf '%s\n' '== Validator implementation and tests =='
cat -n scripts/validate-talos-kubernetes-compatibility/main.go
cat -n scripts/validate-talos-kubernetes-compatibility/main_test.go
printf '%s\n' '== Production pin context =='
rg -n -C 8 'kubernetesVersion|talosVersion|^[[:space:]]*talos:' ksail.prod.yamlLength of output: 150979 🏁 Script executed: #!/bin/bash
set -euo pipefail
base_oid="$(gh pr view 3583 --repo devantler-tech/platform --json baseRefOid --jq .baseRefOid)"
head_oid="$(git rev-parse HEAD)"
printf '%s\n' '== k8s path filter =='
sed -n '150,460p' .github/workflows/ci.yaml
printf '%s\n' '== Changed DR-signing tests =='
git diff --unified=120 "${base_oid}...${head_oid}" -- scripts/validate-dr-signing/main_test.go
ast-grep outline scripts/validate-dr-signing/main_test.go --items all
printf '%s\n' '== Production deploy workflow references =='
rg -n -C 12 'deploy-prod|deploy.*[Pp]rod|workflow_dispatch|merge_group' .github/workflows
printf '%s\n' '== Compatibility-validator uses and workflow graph tests =='
rg -n -C 8 'validate-talos-kubernetes-compatibility|TestMergeGroupDeployRequiresCompatibilityValidation|TestManualDeployRequiresCompatibilityValidation' \
.github scripts --glob '*.yaml' --glob '*.go' --glob '*.md'
printf '%s\n' '== Workflow YAML parser behavior in repository tests =='
rg -n -C 6 'yaml\.Unmarshal|workflowJob|jobNeeds|repositoryWorkflow' scripts --glob '*_test.go'
printf '%s\n' '== Check production configuration selection by k8s filter =='
python3 - <<'PY'
from pathlib import Path
import re
text = Path(".github/workflows/ci.yaml").read_text()
match = re.search(r'(?ms)^ k8s:\n(?P<body>.*?)(?=^ [A-Za-z_][A-Za-z0-9_]*:\n)', text)
if not match:
raise SystemExit("could not locate k8s filter")
patterns = re.findall(r"^\s+- '([^']+)'", match.group("body"))
print("\n".join(patterns))
print("ksail.prod.yaml explicitly selected:", "ksail.prod.yaml" in patterns)
PYLength of output: 180928
The normal merge-queue route and the manual CD route now have the required compatibility gate. You are interacting with an AI system. |
Resolved both current-head findings from CodeRabbit's review output in
RED→GREEN: the new heal-route test first failed because the validator was absent, then passed after the gate was added. Validation at this head: full The PR remains draft while exact-head CI and a fresh substantive review run; the previous review is stale after this push. |
Both P1s are closed by One finding — the The condition became: while the comment above it still reads:
That rationale is now false in both halves: the render+validate does run in the merge group, and because Suggested replacement for the rationale clause: state that it runs on the PR event for fast feedback and on the merge-group revision because that is the revision production deploys, so a patch that only breaks under the speculative merge is caught before Not a blocker on the fix itself — Deliberately not raised as findings, having checked them: the heal job's new validation step sits before its re-deploy, but that job already validated main the same way (RGD templates, isolated chart namespaces), so this follows the established pattern rather than introducing a new failure mode; and the |
Resolved the remaining as-is documentation finding from this current-head review in
|
@coderabbitai full review |
|
✅ Action performedFull review finished. |
Genuine-readiness evaluation for
The head is clean against the live base and the Conventional Commit title remains |
Summary
ksail.prod.yamlusing Talos's versionedKubernetesVersion.SupportedWithpredicate, also used by its runtime configuration validation.Closes #3536. Related to #3534, which remains blocked independently until the staged Talos upgrade has completed. This does not change production versions, Renovate automerge policy, or merge-queue/deployment behavior.
Why this catches the failure
The existing offline
talosctl validate, even with--strict, accepts Kubernetes v1.37.0 with Talos v1.13.9. It does not execute the runtime compatibility predicate. Calling the pinned upstream machinery library directly exercises the same version-range decision without a cluster, credentials, generated machine secrets, or a copied compatibility table.Verification
actionlint .github/workflows/ci.yamlandgit diff --checkpass.go test ./...suite passes with its required network fixtures available.The PR remains a draft until current-head CI and substantive review complete. A passing declared pairing is not evidence that an OS rollout has finished and does not clear #3534 for merging.