Add gomodcheck script to compare go.mod dependencies (#1161)

* Add gomodcheck script to compare go.mod dependencies

* fix: update go-logr and k8s.io/utils dependencies to latest versions
This commit is contained in:
Enrico Candino
2026-08-19 16:30:04 +02:00
committed by GitHub
parent af7fd3918a
commit 45d6bc2ec3
4 changed files with 114 additions and 7 deletions
+6 -1
View File
@@ -143,12 +143,17 @@ endif
lint-yaml: ## Lint the GitHub Actions YAML files
$(YAMLLINT) .github/
.PHONY: check-gomod
check-gomod: ## Check that the root and pkg/apis go.mod agree on common dependency versions
go run scripts/gomodcheck.go go.mod pkg/apis/go.mod
.PHONY: validate
validate: generate docs fmt ## Validate the project checking for any dependency or doc mismatch
$(GINKGO) unfocus
go mod tidy
go mod verify
git status --porcelain
$(MAKE) check-gomod
git status --porcelain
git --no-pager diff --exit-code
.PHONY: install
+2 -2
View File
@@ -9,7 +9,7 @@ require (
require (
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/logr v1.4.4 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -21,7 +21,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/klog/v2 v2.140.0 // indirect
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.3 // indirect
+4 -4
View File
@@ -5,8 +5,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8=
github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -56,8 +56,8 @@ k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hkbPJgdATINPMAxaynU2Ovg=
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM=
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
+102
View File
@@ -0,0 +1,102 @@
//go:build ignore
// gomodcheck compares the require sets of two go.mod files and reports every
// module required by both at a different version.
//
// Usage:
//
// go run scripts/gomodcheck.go go.mod pkg/apis/go.mod
//
// Exit codes: 0 in sync, 1 version mismatch, 2 usage/read/parse error.
package main
import (
"fmt"
"os"
"sort"
"golang.org/x/mod/modfile"
)
func main() {
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "usage: go run scripts/gomodcheck.go <go.mod> <go.mod>\n")
os.Exit(2)
}
pathA, pathB := os.Args[1], os.Args[2]
reqA, err := requires(pathA)
if err != nil {
fmt.Fprintf(os.Stderr, "gomodcheck: %v\n", err)
os.Exit(2)
}
reqB, err := requires(pathB)
if err != nil {
fmt.Fprintf(os.Stderr, "gomodcheck: %v\n", err)
os.Exit(2)
}
var common, mismatched []string
for mod, verA := range reqA {
verB, ok := reqB[mod]
if !ok {
continue
}
common = append(common, mod)
if verA != verB {
mismatched = append(mismatched, mod)
}
}
sort.Strings(mismatched)
if len(mismatched) == 0 {
fmt.Printf("all %d common modules match\n", len(common))
return
}
pad := max(len(pathA), len(pathB))
for _, mod := range mismatched {
fmt.Printf("MISMATCH %s\n", mod)
fmt.Printf(" %-*s %s\n", pad, pathA, reqA[mod])
fmt.Printf(" %-*s %s\n\n", pad, pathB, reqB[mod])
}
fmt.Printf("%s across %d common modules\n", plural(len(mismatched), "mismatch", "mismatches"), len(common))
os.Exit(1)
}
// requires parses the go.mod file at path and returns its require directives,
// both direct and indirect, as a module path to version map.
func requires(path string) (map[string]string, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
file, err := modfile.Parse(path, data, nil)
if err != nil {
return nil, err
}
reqs := make(map[string]string, len(file.Require))
for _, req := range file.Require {
reqs[req.Mod.Path] = req.Mod.Version
}
return reqs, nil
}
func plural(n int, singular, plural string) string {
if n == 1 {
return fmt.Sprintf("%d %s", n, singular)
}
return fmt.Sprintf("%d %s", n, plural)
}