Skip to content

Commit 77ff305

Browse files
authored
feat: version-check (#237)
* feat: version-check Signed-off-by: bakito <github@bakito.ch> * matcher * versioned test * versioned test * regenerate * file diff matcher * silent * version num not hardcoded * helper * cleanup --------- Signed-off-by: bakito <github@bakito.ch>
1 parent dbcf008 commit 77ff305

12 files changed

+339
-141
lines changed

.toolbox.mk

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,70 +8,57 @@ TB_LOCALBIN ?= $(TB_LOCALDIR)/bin
88
$(TB_LOCALBIN):
99
if [ ! -e $(TB_LOCALBIN) ]; then mkdir -p $(TB_LOCALBIN); fi
1010

11+
# Helper functions
12+
STRIP_V = $(patsubst v%,%,$(1))
13+
1114
## Tool Binaries
12-
TB_DEEPCOPY_GEN ?= $(TB_LOCALBIN)/deepcopy-gen
1315
TB_GINKGO ?= $(TB_LOCALBIN)/ginkgo
1416
TB_GOLANGCI_LINT ?= $(TB_LOCALBIN)/golangci-lint
1517
TB_GORELEASER ?= $(TB_LOCALBIN)/goreleaser
16-
TB_OAPI_CODEGEN ?= $(TB_LOCALBIN)/oapi-codegen
1718
TB_SEMVER ?= $(TB_LOCALBIN)/semver
1819

1920
## Tool Versions
20-
# renovate: packageName=github.com/kubernetes/code-generator
21-
TB_DEEPCOPY_GEN_VERSION ?= v0.34.0
2221
# renovate: packageName=github.com/golangci/golangci-lint/v2
2322
TB_GOLANGCI_LINT_VERSION ?= v2.4.0
23+
TB_GOLANGCI_LINT_VERSION_NUM ?= $(call STRIP_V,$(TB_GOLANGCI_LINT_VERSION))
2424
# renovate: packageName=github.com/goreleaser/goreleaser/v2
2525
TB_GORELEASER_VERSION ?= v2.11.2
26-
# renovate: packageName=github.com/deepmap/oapi-codegen/v2
27-
TB_OAPI_CODEGEN_VERSION ?= v2.5.0
26+
TB_GORELEASER_VERSION_NUM ?= $(call STRIP_V,$(TB_GORELEASER_VERSION))
2827
# renovate: packageName=github.com/bakito/semver
2928
TB_SEMVER_VERSION ?= v1.1.5
3029

3130
## Tool Installer
32-
.PHONY: tb.deepcopy-gen
33-
tb.deepcopy-gen: $(TB_DEEPCOPY_GEN) ## Download deepcopy-gen locally if necessary.
34-
$(TB_DEEPCOPY_GEN): $(TB_LOCALBIN)
35-
test -s $(TB_LOCALBIN)/deepcopy-gen || GOBIN=$(TB_LOCALBIN) go install k8s.io/code-generator/cmd/deepcopy-gen@$(TB_DEEPCOPY_GEN_VERSION)
3631
.PHONY: tb.ginkgo
37-
tb.ginkgo: $(TB_GINKGO) ## Download ginkgo locally if necessary.
38-
$(TB_GINKGO): $(TB_LOCALBIN)
39-
test -s $(TB_LOCALBIN)/ginkgo || GOBIN=$(TB_LOCALBIN) go install github.com/onsi/ginkgo/v2/ginkgo
32+
tb.ginkgo: ## Download ginkgo locally if necessary.
33+
@test -s $(TB_GINKGO) || \
34+
GOBIN=$(TB_LOCALBIN) go install github.com/onsi/ginkgo/v2/ginkgo
4035
.PHONY: tb.golangci-lint
41-
tb.golangci-lint: $(TB_GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
42-
$(TB_GOLANGCI_LINT): $(TB_LOCALBIN)
43-
test -s $(TB_LOCALBIN)/golangci-lint || GOBIN=$(TB_LOCALBIN) go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(TB_GOLANGCI_LINT_VERSION)
36+
tb.golangci-lint: ## Download golangci-lint locally if necessary.
37+
@test -s $(TB_GOLANGCI_LINT) && $(TB_GOLANGCI_LINT) --version | grep -q $(TB_GOLANGCI_LINT_VERSION_NUM) || \
38+
GOBIN=$(TB_LOCALBIN) go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(TB_GOLANGCI_LINT_VERSION)
4439
.PHONY: tb.goreleaser
45-
tb.goreleaser: $(TB_GORELEASER) ## Download goreleaser locally if necessary.
46-
$(TB_GORELEASER): $(TB_LOCALBIN)
47-
test -s $(TB_LOCALBIN)/goreleaser || GOBIN=$(TB_LOCALBIN) go install github.com/goreleaser/goreleaser/v2@$(TB_GORELEASER_VERSION)
48-
.PHONY: tb.oapi-codegen
49-
tb.oapi-codegen: $(TB_OAPI_CODEGEN) ## Download oapi-codegen locally if necessary.
50-
$(TB_OAPI_CODEGEN): $(TB_LOCALBIN)
51-
test -s $(TB_LOCALBIN)/oapi-codegen || GOBIN=$(TB_LOCALBIN) go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@$(TB_OAPI_CODEGEN_VERSION)
40+
tb.goreleaser: ## Download goreleaser locally if necessary.
41+
@test -s $(TB_GORELEASER) && $(TB_GORELEASER) --version | grep -q $(TB_GORELEASER_VERSION_NUM) || \
42+
GOBIN=$(TB_LOCALBIN) go install github.com/goreleaser/goreleaser/v2@$(TB_GORELEASER_VERSION)
5243
.PHONY: tb.semver
53-
tb.semver: $(TB_SEMVER) ## Download semver locally if necessary.
54-
$(TB_SEMVER): $(TB_LOCALBIN)
55-
test -s $(TB_LOCALBIN)/semver || GOBIN=$(TB_LOCALBIN) go install github.com/bakito/semver@$(TB_SEMVER_VERSION)
44+
tb.semver: ## Download semver locally if necessary.
45+
@test -s $(TB_SEMVER) || \
46+
GOBIN=$(TB_LOCALBIN) go install github.com/bakito/semver@$(TB_SEMVER_VERSION)
5647

5748
## Reset Tools
5849
.PHONY: tb.reset
5950
tb.reset:
6051
@rm -f \
61-
$(TB_LOCALBIN)/deepcopy-gen \
62-
$(TB_LOCALBIN)/ginkgo \
63-
$(TB_LOCALBIN)/golangci-lint \
64-
$(TB_LOCALBIN)/goreleaser \
65-
$(TB_LOCALBIN)/oapi-codegen \
66-
$(TB_LOCALBIN)/semver
52+
$(TB_GINKGO) \
53+
$(TB_GOLANGCI_LINT) \
54+
$(TB_GORELEASER) \
55+
$(TB_SEMVER)
6756

6857
## Update Tools
6958
.PHONY: tb.update
7059
tb.update: tb.reset
7160
toolbox makefile --renovate -f $(TB_LOCALDIR)/Makefile \
72-
k8s.io/code-generator/cmd/deepcopy-gen@github.com/kubernetes/code-generator \
73-
github.com/golangci/golangci-lint/v2/cmd/golangci-lint \
74-
github.com/goreleaser/goreleaser/v2 \
75-
github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen \
61+
github.com/golangci/golangci-lint/v2/cmd/golangci-lint?--version \
62+
github.com/goreleaser/goreleaser/v2?--version \
7663
github.com/bakito/semver
77-
## toolbox - end
64+
## toolbox - end

pkg/makefile/.toolbox.mk.tpl

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ $(TB_LOCALBIN):
1111
## Go Version
1212
TB_GO_VERSION ?= $(shell grep -E '^go [0-9]+\.[0-9]+' go.mod | awk '{print $$2}')
1313
{{- end }}
14+
{{- if $.WithVersionArgs }}
15+
16+
# Helper functions
17+
STRIP_V = $(patsubst v%,%,$(1))
18+
{{- end }}
1419

1520
## Tool Binaries
1621
{{- range .Tools }}
@@ -25,28 +30,31 @@ TB_{{.UpperName}} ?= $(TB_LOCALBIN)/{{.Name}}
2530
# renovate: packageName={{.RepoURL}}
2631
{{- end }}
2732
TB_{{.UpperName}}_VERSION ?= {{.Version}}
33+
{{- if .VersionArg }}
34+
TB_{{.UpperName}}_VERSION_NUM ?= $(call STRIP_V,$(TB_{{.UpperName}}_VERSION))
35+
{{- end }}
2836
{{- end }}
2937
{{- end }}
3038
{{- end }}
3139

3240
## Tool Installer
3341
{{- range .Tools }}
3442
.PHONY: tb.{{.Name}}
35-
tb.{{.Name}}: $(TB_{{.UpperName}}) ## Download {{.Name}} locally if necessary.
36-
$(TB_{{.UpperName}}): $(TB_LOCALBIN)
37-
test -s $(TB_LOCALBIN)/{{.Name}} || GOBIN=$(TB_LOCALBIN) {{ if $.Toolchain }}GOTOOLCHAIN=go$(TB_GO_VERSION) {{ end }}go install {{.ToolName}}{{- if .Version }}@$(TB_{{.UpperName}}_VERSION){{- end }}
43+
tb.{{.Name}}: ## Download {{.Name}} locally if necessary.
44+
@test -s $(TB_{{.UpperName}}) {{ if .VersionArg }}&& $(TB_{{.UpperName}}) {{ .VersionArg }} | grep -q $(TB_{{.UpperName}}_VERSION_NUM) {{ end }}|| \
45+
GOBIN=$(TB_LOCALBIN) {{ if $.Toolchain }}GOTOOLCHAIN=go$(TB_GO_VERSION) {{ end }}go install {{.ToolName}}{{- if .Version }}@$(TB_{{.UpperName}}_VERSION){{- end }}
3846
{{- end }}
3947

4048
## Reset Tools
4149
.PHONY: tb.reset
4250
tb.reset:
4351
@rm -f{{- range .Tools }} \
44-
$(TB_LOCALBIN)/{{.Name}}
52+
$(TB_{{.UpperName}})
4553
{{- end }}
4654

4755
## Update Tools
4856
.PHONY: tb.update
4957
tb.update: tb.reset
5058
toolbox makefile {{ if $.Renovate }}--renovate {{ end }}{{ if $.Toolchain }}--toolchain {{ end }}-f $(TB_LOCALDIR)/Makefile{{- range .Tools }}{{- if not .FromToolsGo }} \
51-
{{.Tool}}{{- end }}
59+
{{.Tool}}{{ if .VersionArg }}?{{ .VersionArg }}{{ end }}{{- end }}
5260
{{- end }}

pkg/makefile/consts.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ const (
1414
var (
1515
//go:embed .toolbox.mk.tpl
1616
tpl string
17-
makefileTemplate = fmt.Sprintf("%s\n%s%s", markerStart, tpl, markerEnd)
17+
makefileTemplate = fmt.Sprintf("%s\n%s%s\n", markerStart, tpl, markerEnd)
1818
)

pkg/makefile/make.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,24 @@ func generateForTools(
4848
})
4949

5050
withVersions := false
51+
withVersionArgs := false
5152
for _, td := range toolData {
5253
if !withVersions && td.Version != "" {
5354
withVersions = true
5455
}
56+
if !withVersionArgs && td.VersionArg != "" {
57+
withVersionArgs = true
58+
}
5559
}
5660

5761
out := &bytes.Buffer{}
5862
t := template.Must(template.New("toolbox.mk").Parse(makefileTemplate))
5963
if err := t.Execute(out, map[string]any{
60-
"Tools": toolData,
61-
"WithVersions": withVersions,
62-
"Renovate": renovate,
63-
"Toolchain": toolchain,
64+
"Tools": toolData,
65+
"WithVersions": withVersions,
66+
"WithVersionArgs": withVersionArgs,
67+
"Renovate": renovate,
68+
"Toolchain": toolchain,
6469
}); err != nil {
6570
return err
6671
}
@@ -131,11 +136,18 @@ func dataForArg(client *resty.Client, tool string) (toolData, error) {
131136
}
132137

133138
func dataForTool(fromToolsGo bool, toolName string, fullTool ...string) toolData {
134-
parts := strings.Split(toolName, "/")
135139
var td toolData
136140
td.ToolName = toolName
141+
142+
if sp := strings.Split(td.ToolName, "?"); len(sp) > 1 {
143+
td.ToolName = sp[0]
144+
td.VersionArg = sp[1]
145+
}
146+
147+
parts := strings.Split(td.ToolName, "/")
148+
137149
if len(fullTool) == 1 {
138-
td.Tool = fullTool[0]
150+
td.Tool = strings.Split(fullTool[0], "?")[0]
139151
} else {
140152
td.Tool = toolName
141153
}
@@ -144,12 +156,13 @@ func dataForTool(fromToolsGo bool, toolName string, fullTool ...string) toolData
144156
} else {
145157
td.Name = parts[len(parts)-1]
146158
}
159+
147160
td.UpperName = strings.ReplaceAll(strings.ToUpper(td.Name), "-", "_")
148161
td.FromToolsGo = fromToolsGo
149162
td.GoModule = extractModulePath(td.ToolName)
150163
td.RepoURL = td.GoModule
151-
if strings.Contains(td.Tool, "@") {
152-
td.RepoURL = strings.Split(td.Tool, "@")[1]
164+
if sp := strings.Split(td.Tool, "@"); len(sp) > 1 {
165+
td.RepoURL = sp[1]
153166
}
154167
return td
155168
}
@@ -180,6 +193,7 @@ type toolData struct {
180193
Tool string `json:"Tool"`
181194
ToolName string `json:"ToolName"`
182195
FromToolsGo bool `json:"FromToolsGo"`
196+
VersionArg string `json:"VersionArg"`
183197
}
184198

185199
func mergeWithToolsGo(fileName string, inTools []string) ([]string, []toolData) {

pkg/makefile/make_test.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ var _ = Describe("Make", func() {
4848
)
4949
Ω(err).ShouldNot(HaveOccurred())
5050

51-
Ω(readFile(makeFilePath)).Should(Equal(readFile(testDataDir, "Makefile.content.expected")))
52-
Ω(readFile(includeFilePath) + "\n").Should(Equal(readFile(testDataDir, ".toolbox.mk.content.expected")))
51+
Ω(makeFilePath).Should(EqualFileDiff(testDataDir, "Makefile.content.expected"))
52+
Ω(includeFilePath).Should(EqualFileDiff(testDataDir, ".toolbox.mk.content.expected"))
5353
})
5454
It("should migrate to include correct output", func() {
5555
makeFilePath = copyFile("Makefile.content.migrate", tempDir)
@@ -61,8 +61,8 @@ var _ = Describe("Make", func() {
6161
)
6262
Ω(err).ShouldNot(HaveOccurred())
6363

64-
Ω(readFile(makeFilePath)).Should(Equal(readFile(testDataDir, "Makefile.content.expected")))
65-
Ω(readFile(includeFilePath) + "\n").Should(Equal(readFile(testDataDir, ".toolbox.mk.content.expected")))
64+
Ω(makeFilePath).Should(EqualFileDiff(testDataDir, "Makefile.content.expected"))
65+
Ω(includeFilePath).Should(EqualFileDiff(testDataDir, ".toolbox.mk.content.expected"))
6666
})
6767
It("should generateForTools a correct output with hybrid tools", func() {
6868
err := Generate(resty.New(), makeFilePath, false, false,
@@ -71,8 +71,8 @@ var _ = Describe("Make", func() {
7171
"github.com/bakito/toolbox",
7272
)
7373
Ω(err).ShouldNot(HaveOccurred())
74-
Ω(readFile(makeFilePath)).Should(Equal(readFile(testDataDir, "Makefile.content.expected")))
75-
Ω(readFile(includeFilePath) + "\n").Should(Equal(readFile(testDataDir, ".toolbox.mk.hybrid.expected")))
74+
Ω(makeFilePath).Should(EqualFileDiff(testDataDir, "Makefile.content.expected"))
75+
Ω(includeFilePath).Should(EqualFileDiff(testDataDir, ".toolbox.mk.hybrid.expected"))
7676
})
7777
It("should generateForTools a correct output with renovate enabled", func() {
7878
err := Generate(resty.New(), makeFilePath, true, false, "",
@@ -82,8 +82,8 @@ var _ = Describe("Make", func() {
8282
"github.com/bakito/toolbox",
8383
)
8484
Ω(err).ShouldNot(HaveOccurred())
85-
Ω(readFile(makeFilePath)).Should(Equal(readFile(testDataDir, "Makefile.content.expected")))
86-
Ω(readFile(includeFilePath) + "\n").Should(Equal(readFile(testDataDir, ".toolbox.mk.renovate.expected")))
85+
Ω(makeFilePath).Should(EqualFileDiff(testDataDir, "Makefile.content.expected"))
86+
Ω(includeFilePath).Should(EqualFileDiff(testDataDir, ".toolbox.mk.renovate.expected"))
8787
})
8888

8989
It("should generateForTools a correct output with toolchain enabled", func() {
@@ -95,8 +95,20 @@ var _ = Describe("Make", func() {
9595
)
9696
Ω(err).ShouldNot(HaveOccurred())
9797

98-
Ω(readFile(makeFilePath)).Should(Equal(readFile(testDataDir, "Makefile.content.expected")))
99-
Ω(readFile(includeFilePath) + "\n").Should(Equal(readFile(testDataDir, ".toolbox.mk.toolchain.expected")))
98+
Ω(makeFilePath).Should(EqualFileDiff(testDataDir, "Makefile.content.expected"))
99+
Ω(includeFilePath).Should(EqualFileDiff(testDataDir, ".toolbox.mk.toolchain.expected"))
100+
})
101+
It("should generateForTools a correct output with versioned tool", func() {
102+
err := Generate(resty.New(), makeFilePath, false, false, "",
103+
"sigs.k8s.io/controller-tools/cmd/controller-gen@github.com/kubernetes-sigs/controller-tools",
104+
"github.com/golangci/golangci-lint/v2/cmd/golangci-lint?--version",
105+
"github.com/bakito/semver",
106+
"github.com/bakito/toolbox",
107+
)
108+
Ω(err).ShouldNot(HaveOccurred())
109+
110+
Ω(makeFilePath).Should(EqualFileDiff(testDataDir, "Makefile.content.expected"))
111+
Ω(includeFilePath).Should(EqualFileDiff(testDataDir, ".toolbox.mk.version.expected"))
100112
})
101113
})
102114

@@ -109,8 +121,8 @@ var _ = Describe("Make", func() {
109121
}
110122
err := generateForTools(resty.New(), makeFilePath, false, false, nil, td)
111123
Ω(err).ShouldNot(HaveOccurred())
112-
Ω(readFile(makeFilePath)).Should(Equal(readFile(testDataDir, "Makefile.content.expected")))
113-
Ω(readFile(includeFilePath) + "\n").Should(Equal(readFile(testDataDir, ".toolbox.mk.tools.go.expected")))
124+
Ω(makeFilePath).Should(EqualFileDiff(testDataDir, "Makefile.content.expected"))
125+
Ω(includeFilePath).Should(EqualFileDiff(testDataDir, ".toolbox.mk.tools.go.expected"))
114126
})
115127
})
116128
Context("updateRenovateConfInternal", func() {
@@ -149,12 +161,6 @@ var _ = Describe("Make", func() {
149161
})
150162
})
151163

152-
func readFile(path ...string) string {
153-
b, err := os.ReadFile(filepath.Join(path...))
154-
Ω(err).ShouldNot(HaveOccurred())
155-
return string(b)
156-
}
157-
158164
func copyFile(name, targetDir string) string {
159165
bytesRead, err := os.ReadFile(filepath.Join(testDataDir, name))
160166

0 commit comments

Comments
 (0)