Skip to content

Commit 86ad2dc

Browse files
🌱 verify go modules are in sync with upstream k/k
This commit addresses issues were go modules aren't in sync with upstream k/k by adding these changes: - add `tools/cmd/gomodcheck/main.go` to: - Parse and compares k/k direct dependencies to controller-runtime's direct deps. - If any version diffs is found, returns a payload describing the diffs and exit 1. - The user may exclude packages by passing them as arguments. - extend the `verify-modules` make target with `gomodcheck`. Signed-off-by: Alexandre Mahdhaoui <[email protected]>
1 parent 45e166d commit 86ad2dc

File tree

3 files changed

+136
-1
lines changed

3 files changed

+136
-1
lines changed

.gomodcheck.ignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
github.com/onsi/gomega
2+
github.com/onsi/ginkgo/v2
3+
4+
k8s.io/api
5+
k8s.io/apimachinery
6+
k8s.io/apiextensions-apiserver
7+
k8s.io/apiserver
8+
k8s.io/client-go
9+
k8s.io/component-base

Makefile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ GOLANGCI_LINT_PKG := github.com/golangci/golangci-lint/cmd/golangci-lint
9292
$(GOLANGCI_LINT): # Build golangci-lint from tools folder.
9393
GOBIN=$(TOOLS_BIN_DIR) $(GO_INSTALL) $(GOLANGCI_LINT_PKG) $(GOLANGCI_LINT_BIN) $(GOLANGCI_LINT_VER)
9494

95+
GO_MOD_CHECK_DIR := $(abspath ./tools/cmd/gomodcheck)
96+
GO_MOD_CHECK := $(abspath $(TOOLS_BIN_DIR)/gomodcheck)
97+
GO_MOD_CHECK_IGNORE := $(abspath ./.gomodcheck.ignore)
98+
$(GO_MOD_CHECK): # Build gomodcheck
99+
go build -C $(GO_MOD_CHECK_DIR) -o $(GO_MOD_CHECK)
100+
95101
## --------------------------------------
96102
## Linting
97103
## --------------------------------------
@@ -134,11 +140,12 @@ clean-bin: ## Remove all generated binaries.
134140
rm -rf hack/tools/bin
135141

136142
.PHONY: verify-modules
137-
verify-modules: modules ## Verify go modules are up to date
143+
verify-modules: modules $(GO_MOD_CHECK) ## Verify go modules are up to date
138144
@if !(git diff --quiet HEAD -- go.sum go.mod $(TOOLS_DIR)/go.mod $(TOOLS_DIR)/go.sum $(ENVTEST_DIR)/go.mod $(ENVTEST_DIR)/go.sum $(SCRATCH_ENV_DIR)/go.sum); then \
139145
git diff; \
140146
echo "go module files are out of date, please run 'make modules'"; exit 1; \
141147
fi
148+
cat $(GO_MOD_CHECK_IGNORE) | xargs $(GO_MOD_CHECK)
142149

143150
APIDIFF_OLD_COMMIT ?= $(shell git rev-parse origin/main)
144151

tools/cmd/gomodcheck/main.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
"os"
9+
"regexp"
10+
"strings"
11+
12+
"sigs.k8s.io/controller-runtime/pkg/log/zap"
13+
)
14+
15+
const (
16+
kkModUrl = "https://raw.githubusercontent.com/kubernetes/kubernetes/master/go.mod"
17+
modFile = "./go.mod"
18+
)
19+
20+
var (
21+
cleanMods = regexp.MustCompile(`\t| *//.*`)
22+
modDelimStart = regexp.MustCompile(`^require.*`)
23+
modDelimEnd = ")"
24+
)
25+
26+
type oosMod struct {
27+
Name string `json:"name"`
28+
Version string `json:"version"`
29+
UpstreamVersion string `json:"upstreamVersion"`
30+
}
31+
32+
func main() {
33+
logger := zap.New()
34+
excludedMods := getExcludedMods()
35+
36+
// 1. kk
37+
resp, err := http.Get(kkModUrl)
38+
if err != nil {
39+
panic(err.Error())
40+
}
41+
42+
b, err := io.ReadAll(resp.Body)
43+
if err != nil {
44+
panic(err.Error())
45+
}
46+
47+
kkMods := parseMod(b)
48+
49+
// 2. go.mod
50+
b, err = os.ReadFile(modFile)
51+
if err != nil {
52+
return
53+
}
54+
55+
oosMods := make([]oosMod, 0)
56+
57+
mods := parseMod(b)
58+
for k, v := range mods {
59+
if _, ok := excludedMods[k]; ok {
60+
logger.Info(fmt.Sprintf("skipped module: %s", k))
61+
continue
62+
}
63+
64+
if upstreamVersion, ok := kkMods[k]; ok && v != upstreamVersion {
65+
oosMods = append(oosMods, oosMod{
66+
Name: k,
67+
Version: v,
68+
UpstreamVersion: upstreamVersion,
69+
})
70+
}
71+
}
72+
73+
if len(oosMods) == 0 {
74+
fmt.Println("Success! 🎉")
75+
os.Exit(0)
76+
}
77+
78+
b, err = json.MarshalIndent(map[string]any{"outOfSyncModules": oosMods}, "", " ")
79+
if err != nil {
80+
panic(err)
81+
}
82+
83+
fmt.Println(string(b))
84+
os.Exit(1)
85+
}
86+
87+
func parseMod(b []byte) map[string]string {
88+
in := string(cleanMods.ReplaceAll(b, []byte("")))
89+
out := make(map[string]string)
90+
91+
start := false
92+
for _, s := range strings.Split(in, "\n") {
93+
switch {
94+
case modDelimStart.MatchString(s) && !start:
95+
start = true
96+
case s == modDelimEnd:
97+
return out
98+
case start:
99+
kv := strings.SplitN(s, " ", 2)
100+
if len(kv) < 2 {
101+
panic(fmt.Sprintf("unexpected format for module: %q", s))
102+
}
103+
104+
out[kv[0]] = kv[1]
105+
}
106+
}
107+
108+
return out
109+
}
110+
111+
func getExcludedMods() map[string]any {
112+
out := make(map[string]any)
113+
114+
for _, mod := range os.Args[1:] {
115+
out[mod] = nil
116+
}
117+
118+
return out
119+
}

0 commit comments

Comments
 (0)