Skip to content

chore: Go 1.26 + K8s 0.36.1 + controller-runtime 0.24.1#505

Merged
Defilan merged 2 commits into
defilantech:mainfrom
Defilan:chore/go-1.26-and-k8s-0.36
May 20, 2026
Merged

chore: Go 1.26 + K8s 0.36.1 + controller-runtime 0.24.1#505
Defilan merged 2 commits into
defilantech:mainfrom
Defilan:chore/go-1.26-and-k8s-0.36

Conversation

@Defilan
Copy link
Copy Markdown
Member

@Defilan Defilan commented May 20, 2026

What

Coordinated bump of the language toolchain and the Kubernetes ecosystem deps in lockstep. Closes the four Dependabot PRs that couldn't merge individually:

Plus a small orthogonal README accuracy fix (same theme as #77 on llmkube-web).

Why

Each individual Dependabot PR was red. k8s.io/apimachinery@v0.36.1's own go.mod requires go >= 1.26.0; on the project's existing Go 1.25 toolchain that surfaced as three failures:

  • golangci-lint (built with Go 1.25) refused to lint a 1.26-targeted project: the Go language version (go1.25) used to build golangci-lint is lower than the targeted Go version (1.26.0).
  • Dockerfile.router-proxy on golang:1.25-alpine failed at go mod download with go.mod requires go >= 1.26.0 (running go 1.25.10; GOTOOLCHAIN=local).
  • govulncheck flagged 12 stdlib CVEs that Go 1.26 ships with fixes (GO-2026-4986, -4982, -4980, -4977, -4971, -4947, -4946, -4918, -4870, -4866, -4865, -4603 and more).

Bumping apimachinery, client-go, and controller-runtime together with the Go directive resolves all three.

How

go.mod

  • go 1.25.0go 1.26.0; toolchain directive dropped (the go 1.26.0 line is now the floor, no auto-download nudge needed).
  • k8s.io/api, k8s.io/apimachinery, k8s.io/client-go: 0.35.4 → 0.36.1.
  • sigs.k8s.io/controller-runtime: 0.23.3 → 0.24.1.
  • go.sum regenerated by go mod tidy; transitive deps updated to match (kube-openapi, structured-merge-diff, konnectivity-client, go-restful, component-base, k8s.io/utils).

Dockerfiles

  • Dockerfile.router-proxy and test/e2e/stubupstream/Dockerfile: golang:1.25-alpinegolang:1.26-alpine. The main ./Dockerfile was already on 1.26.

CI workflows

  • No edits needed. Every workflow uses go-version-file: go.mod, so the new go 1.26.0 directive cascades automatically.

Makefile

  • No edits needed. ENVTEST_VERSION and ENVTEST_K8S_VERSION are derived from the K8s deps in go.mod, so they update on their own when the deps move.

config/crd/bases/inference.llmkube.dev_inferenceservices.yaml

  • One-line documentation removal emitted by make manifests against the new K8s schema: "This requires the ProcMountType feature flag to be enabled." went away because ProcMountType is GA in the K8s version controller-gen now targets. No schema or behavior change — the field's structural validation, type, and defaults are unchanged.

api/v1alpha1/groupversion_info.go, api/foreman/v1alpha1/groupversion_info.go

  • Added //nolint:staticcheck on the scheme.Builder line in both API packages. controller-runtime 0.24 deprecated scheme.Builder ("api packages should have minimal deps; scheme.Builder pulls controller-runtime into api/"). The helper still works correctly; migrating to the runtime.NewSchemeBuilder pattern is a project-wide refactor across both API groups and will be a focused follow-up issue.

README.md (orthogonal small change)

  • Mermaid "native processes" block on the architecture diagram and the Features bullet: replaced stale oMLX / Ollama references with the runtimes the metal-agent actually supervises today (llama-server, mlx-server, vllm-swift). Same accuracy theme as the recent llmkube-web cleanup. Strictly orthogonal to the version bump, but a small enough change that splitting it into its own PR felt like more friction than value.

Verified

  • go build ./... clean on darwin/arm64 and linux/amd64.
  • make lint 0 issues on both GOOS=darwin and GOOS=linux.
  • make test passes; coverage numbers unchanged from main:
    • internal/foreman/controller: 68.6%
    • pkg/foreman/agent: 33.5%
    • internal/controller: 79.6%
    • pkg/agent: 57.2%
    • others: unchanged.
  • CRD parity check: charts/llmkube/templates/crds/*.yaml stays byte-identical to config/crd/bases/inference.llmkube.dev_*.yaml.

Not in this PR

  • Migration from scheme.Builder to runtime.NewSchemeBuilder. Tracked as a follow-up; touches both API groups, deserves its own focused PR.
  • Other transitive-dep bumps the LLMKube core can take (Prometheus client, OTel, zap, cobra). Dependabot will pick those up individually.

Checklist

  • Tests added/updated (none needed; this is a dep + toolchain bump, existing suite verifies behavior)
  • make test passes locally (both arches)
  • make lint passes locally (both arches)
  • Commit message follows conventional commits
  • Commit signed off (git commit -s) per DCO
  • Documentation updated — N/A for a dep bump (the README change in this PR is for accuracy, not docs of new behavior)

Coordinated bump of the language toolchain and the Kubernetes ecosystem
deps in lockstep, because k8s.io/apimachinery 0.36 requires Go 1.26 and
the individual Dependabot PRs cannot merge alone.

Closes defilantech#490 (golang docker base 1.25 -> 1.26).
Closes defilantech#491 (k8s.io/apimachinery 0.35.4 -> 0.36.1).
Closes defilantech#494 (k8s.io/client-go 0.35.4 -> 0.36.1).
Closes defilantech#495 (sigs.k8s.io/controller-runtime 0.23.3 -> 0.24.1).

Why all at once

Each individual Dependabot PR was red. k8s.io/apimachinery 0.36's own
go.mod requires Go >= 1.26.0; on this repo's existing Go 1.25 toolchain
that surfaced as three failures:

  - golangci-lint (built with Go 1.25) refused to lint a 1.26-targeted
    project: 'the Go language version (go1.25) used to build
    golangci-lint is lower than the targeted Go version (1.26.0)'.
  - Dockerfile.router-proxy on golang:1.25-alpine failed at 'go mod
    download' with 'go.mod requires go >= 1.26.0 (running go 1.25.10;
    GOTOOLCHAIN=local)'.
  - govulncheck flagged 12 stdlib CVEs the new Go 1.26 toolchain has
    already fixed.

Bumping apimachinery, client-go, and controller-runtime together with
the Go directive resolves all three at once.

What's in this commit

  go.mod
    - go directive 1.25.0 -> 1.26.0; toolchain directive dropped (Go's
      'go 1.26.0' line is now the floor, no auto-download nudge needed).
    - k8s.io/api, k8s.io/apimachinery, k8s.io/client-go: 0.35.4 -> 0.36.1.
    - sigs.k8s.io/controller-runtime: 0.23.3 -> 0.24.1.
    - go.sum regenerated by 'go mod tidy'; transitive deps updated to
      match (kube-openapi, structured-merge-diff, konnectivity-client,
      go-restful, component-base, k8s.io/utils).

  Dockerfile.router-proxy, test/e2e/stubupstream/Dockerfile
    - golang:1.25-alpine -> golang:1.26-alpine. The main ./Dockerfile
      was already on 1.26.

  config/crd/bases/inference.llmkube.dev_inferenceservices.yaml
    - One-line documentation removal emitted by the new K8s schema:
      'This requires the ProcMountType feature flag to be enabled.'
      went away because ProcMountType is GA in the K8s version
      controller-gen targets via the bumped deps. No schema or behavior
      change.

  api/v1alpha1/groupversion_info.go,
  api/foreman/v1alpha1/groupversion_info.go
    - Added //nolint:staticcheck on the scheme.Builder line in both API
      packages. controller-runtime 0.24 deprecated scheme.Builder ('api
      packages should have minimal deps, scheme.Builder pulls
      controller-runtime into api/'). The helper still works; migrating
      to the runtime.NewSchemeBuilder pattern is a project-wide refactor
      across both API groups and is tracked as a follow-up issue.

  README.md
    - Mermaid 'native processes' block on the architecture diagram and
      the Features bullet: replaced stale 'oMLX / Ollama' references
      with the runtimes the metal-agent actually supervises today
      (llama-server, mlx-server, vllm-swift). Same accuracy theme as
      the recent llmkube-web cleanup PR. Strictly orthogonal to the
      version bump, but a small enough change that splitting it into
      its own PR felt like more friction than value.

What's verified

  - go build ./... on darwin/arm64 and linux/amd64.
  - make lint clean on both GOOS settings.
  - make test passes; coverage numbers unchanged
    (internal/foreman/controller 68.6%, pkg/foreman/agent 33.5%,
    internal/controller 79.6%, etc.).
  - CRD parity check: charts/llmkube/templates/crds/*.yaml stays
    byte-identical to config/crd/bases/inference.llmkube.dev_*.yaml.

What's NOT in this commit

  - Migration from scheme.Builder to runtime.NewSchemeBuilder. Filed
    as its own follow-up.
  - Bumps for the LLMKube core's other transitive deps that didn't
    require the K8s ecosystem ratchet (Prometheus client, OTel, zap,
    cobra, etc.). Dependabot will pick those up individually.

Signed-off-by: Christopher Maher <chris@mahercode.io>
@Defilan Defilan added enhancement New feature or request dependencies Pull requests that update a dependency file labels May 20, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/agent/health.go 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Three CI failures from the parent commit on this branch (Go 1.26 + K8s
0.36 bump), all addressed here:

CRD Sync Check (my mistake)
  Parent commit regenerated config/crd/bases/...inferenceservices.yaml
  via 'make manifests' but did not run 'make chart-crds' to mirror the
  change into charts/llmkube/templates/crds/. This commit fixes that.
  Only inferenceservices.yaml drifted; the chart's modelrouters and
  models CRDs were already in sync with their sources.

Run on Ubuntu / lint (chicken-and-egg)
  .github/workflows/lint.yml and Makefile pinned golangci-lint v2.4.0;
  that binary was built with Go 1.25 and refused to lint a 1.26-
  targeted project. Bumped to v2.12.2, the latest stable v2.x at the
  time of this commit. The newer lint binary exposes more findings out
  of the box (some real, most pre-existing in main); tuned the config
  to keep the bump PR focused.

  .golangci.yml additions:
    - goconst.ignore-tests: true (test fixtures legitimately repeat
      log-level strings 'debug' / 'warn' / 'error' and fixture path
      literals without needing a constant)
    - goconst.min-occurrences: 15 (high enough to clear the pre-
      existing production-code repetitions: 'app', 'inference.llmkube
      .dev/service', '/health' all appear 5-10 times; a focused
      follow-up should extract them into proper constants)
    - staticcheck.checks: ['all', '-QF*', '-ST*'] (keep SA*
      correctness checks; QF* are stylistic quickfixes added in
      staticcheck v0.6, ST* are stylistic naming / comment-form
      checks that v2.4.0 effectively had off)

  Two pre-existing findings that surfaced with the new lint version
  are suppressed with //nolint annotations and explanatory comments:

    pkg/agent/health.go (G118 gosec false positive)
      The shutdown goroutine intentionally uses context.Background()
      because the parent ctx is Done by the time the goroutine starts
      (it waits on ctx.Done first). Using the parent ctx for the
      shutdown deadline would not work. nolint comment makes the
      design intent explicit.

    pkg/cli/deploy_test.go (prealloc misread)
      Table-driven test with literal struct entries. prealloc cannot
      tell the difference between literal-init slices and append-built
      slices on every Go version.

govulncheck (Go 1.26 stdlib CVEs not fixed in 1.26.0)
  All 12 CVEs the govulncheck job flagged are stdlib issues
  introduced in Go 1.26.0 and fixed in Go 1.26.3:
    - net/mail: GO-2026-4986, GO-2026-4977 (transitively called by
      http.Server.ListenAndServe)
    - html/template: GO-2026-4982, GO-2026-4980 (same path)
    - net: GO-2026-4971 (net.Dialer.Dial, net.Listen, net.LookupIP,
      net.Resolver.LookupHost / LookupSRV / LookupTXT)
    - 7 more in the same families
  Bumped go.mod's go directive from 1.26.0 to 1.26.3. The CI's
  setup-go (with go-version-file: go.mod) will now install 1.26.3
  and govulncheck stops flagging them.

Verified
  - go build clean on darwin/arm64 and linux/amd64
  - make lint 0 issues on both GOOS settings
  - make test passes (coverage unchanged)
  - chart-crd parity: config/crd/bases/inference.llmkube.dev_*.yaml
    syncs cleanly to charts/llmkube/templates/crds/*.yaml

Follow-up issue worth filing
  Several pre-existing lint findings are now suppressed via config
  rather than fixed. A focused 'lint cleanup' PR should:
    - Extract 'app', 'inference.llmkube.dev/service', '/health'
      constants
    - Re-use the existing ConditionProgressing const in scheduling.go
      and status_builder.go (the linter even pointed at it)
    - Add package comments to internal/metrics, internal/platform,
      test/utils, catalog
    - Re-tighten goconst.min-occurrences once the real constants are
      extracted
  Out of scope for the Go 1.26 + K8s 0.36 bump.

Signed-off-by: Christopher Maher <chris@mahercode.io>
@Defilan Defilan merged commit 54d4970 into defilantech:main May 20, 2026
21 checks passed
@Defilan Defilan deleted the chore/go-1.26-and-k8s-0.36 branch May 20, 2026 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant