Skip to content

Adopt Renovate: nothing currently bumps our Go version, and Dependabot structurally cannot #494

Description

@lockwobr

Summary

Nothing keeps our Go version current. operator/go.mod and agent/go/go.mod both pin go 1.26.5, ten workflows resolve their toolchain from those files via go-version-file:, and Dependabot structurally cannot bump either line. A Go stdlib CVE fixed in a patch release produces no PR here and no signal at all.

Dependabot is not going to close this gap. Renovate can. NVIDIA/aicr already runs it, self-hosted, and has worked through most of the decisions we would face. Proposing we follow.

The gap, precisely

Dependabot has no Go-toolchain ecosystem. dependabot-core#13520, "Bump Go toolchain directive in go.mod files", has been an open feature request since November 2025.

The one thing it does do is reactive: dependabot-core#9527 was fixed in September 2025 by removing the code that forced the old go directive back, so native go tooling may now raise the directive as a side effect of a dependency bump that requires it. That has a wrinkle of its own: our Go version can move inside a PR titled chore(deps): bump the kubernetes group, silently changing the toolchain for CI, releases, and CodeQL.

For reference on how far behind that leaves us: aicr is on Go 1.26.6, we are on 1.26.5.

What Renovate actually gives us

Worth being precise, because it is not free. Renovate's gomod manager splits the two directives:

We have no toolchain line and a patch-level go 1.26.5 directive, so out of the box Renovate would do nothing for us either. Closing the gap is an explicit choice between two shapes:

  1. Keep go.mod as the source of truth and enable the golang depType. Smallest change, preserves the current go-version-file: wiring across all ten workflows.
  2. Introduce a .go-version file as the source of truth, bumped by a customManager on the golang-version datasource, with the gomod manager's golang depType explicitly disabled so the directive cannot move out of band. This is what aicr does.

(1) fits this repo better, since we already centralized on go.mod deliberately. (2) is the proven-here option and decouples "the toolchain we build with" from "the minimum language version we claim to support", which is the distinction the Go team actually intends. Worth deciding, not assuming.

What aicr's rollout already answers

NVIDIA/aicr/.github/renovate.json5 plus .github/workflows/renovate.yaml are the reference. Things they hit that we would otherwise rediscover:

  • Self-hosted via renovatebot/github-action on a cron, not the Mend app. No app install, no org approval.
  • Dependabot is kept for github-actions and Renovate's equivalent manager is disabled. GitHub's auto-issued GITHUB_TOKEN cannot push changes to .github/workflows/* no matter what permissions: says. Renovate would need a GitHub App or a PAT with workflows scope. This means the end state is a hybrid, not a clean replacement, and we should plan for that from the start.
  • statuses: write and security-events: read are required. Without the first, Renovate 403s writing its stability check, misreports it as "Repository has changed during renovation", and aborts the entire run.
  • minimumReleaseAge as supply-chain defense. 3 days globally, 7 for anything that auto-merges, so a poisoned-then-yanked release cannot reach us.
  • Conventional-commit prefixes via :semanticCommitTypeAll(chore) / :semanticCommitScope(deps), which is what our own commit-linting PR-title check needs, same reason include: "scope" is set in our dependabot.yml today.
  • Our existing kubernetes and golang-x groups port over directly as matchPackageNames rules, including the !k8s.io/klog/v2 exclusion.

Things specific to us

  • vendor/ must be in ignorePaths, and postUpdateOptions: ["gomodTidy", "gomodUpdateImportPaths"] has to run, or every PR breaks the -mod=vendor build.
  • Two Go modules (/operator, /agent/go) that should stay on the same Go version. Whatever shape we pick has to bump both together or the mismatch shows up as a confusing CI failure.
  • .github/labels.yml is a closed set and has dependencies but no renovate label. If we want aicr's labeling, that is a PR to labels.yml first. Nobody creates it by hand.
  • Our docker ecosystem entry covers /containers/**. Renovate's dockerfile manager would take that over, and there is no golang base image in those files today, so no version-skew coupling to worry about (dependabot-core#15135 is the trap we happen to avoid).
  • Auto-merge is worth considering for gomod patch bumps, but only after we have seen a few weeks of Renovate PRs pass CI unattended.

Proposed rollout

Mirror aicr's soft launch rather than a cutover:

  1. Add .github/renovate.json5 and a self-hosted .github/workflows/renovate.yaml, running alongside the existing dependabot.yml
  2. Start with dryRun on workflow_dispatch to see what it proposes before it can open anything
  3. Port the kubernetes and golang-x groups so PR shape does not change for reviewers
  4. Turn on Go version updates in whichever shape we pick above, and confirm both modules move together
  5. Once Renovate has covered a full cycle, strip dependabot.yml down to the github-actions ecosystem only
  6. Revisit auto-merge for gomod patch updates

Acceptance criteria

  • A decision is recorded on go.mod-as-source-of-truth versus .go-version
  • A new Go patch release opens a PR against both operator/go.mod and agent/go/go.mod within a week of upstream release
  • That PR is a standalone, reviewable Go-version bump, not a side effect buried in a dependency group
  • Renovate PR titles satisfy the commit-linting PR-title check
  • Vendored builds pass on Renovate PRs without a manual go mod vendor
  • dependabot.yml retains only the github-actions ecosystem, with a comment explaining why it cannot move
  • Any new label is added to .github/labels.yml in a PR, not created on GitHub

Metadata

Metadata

Assignees

No one assigned

    Labels

    component/agentSkyhook agent (package executor)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions