From 2e70e2aa0c6d87c81ec6865f054117beb7adcba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E5=8F=AF?= Date: Fri, 6 Dec 2024 13:58:52 +0800 Subject: [PATCH] feat: codegen version check (#259) --- Taskfile.yml | 1 + cmd/kod/internal/generate_generator.go | 34 +++++++++++++++++++---- examples/helloworld/kod_gen.go | 19 +++++++++++++ internal/version/version.go | 38 ++++++++++++++++++++++++++ tests/case1/kod_gen.go | 19 +++++++++++++ tests/case2/kod_gen.go | 19 +++++++++++++ tests/case3/kod_gen.go | 19 +++++++++++++ tests/case4/kod_gen.go | 19 +++++++++++++ tests/case5/kod_gen.go | 19 +++++++++++++ tests/graphcase/kod_gen.go | 19 +++++++++++++ version.go | 14 ++++++++++ 11 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 internal/version/version.go create mode 100644 version.go diff --git a/Taskfile.yml b/Taskfile.yml index 2b32526..804231c 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -40,6 +40,7 @@ tasks: -covermode=atomic ./... ./tests/... \ -coverpkg .,./cmd/...,./internal/...,./interceptor/... git checkout tests/case1/kod_gen_mock.go + git checkout tests/graphcase/kod_gen.go sources: - "**/**.go" generates: diff --git a/cmd/kod/internal/generate_generator.go b/cmd/kod/internal/generate_generator.go index f74d39e..0069678 100644 --- a/cmd/kod/internal/generate_generator.go +++ b/cmd/kod/internal/generate_generator.go @@ -22,6 +22,7 @@ import ( "golang.org/x/tools/go/packages" "github.com/go-kod/kod/internal/callgraph" + "github.com/go-kod/kod/internal/version" ) const ( @@ -562,19 +563,14 @@ func (g *generator) generate() error { return nil } - // // Process components in deterministic order. - // sort.Slice(g.components, func(i, j int) bool { - // return g.components[i].intfName() < g.components[j].intfName() - // }) - // Generate the file body. var body bytes.Buffer { fn := func(format string, args ...interface{}) { fmt.Fprintln(&body, fmt.Sprintf(format, args...)) } - // g.generateVersionCheck(fn) g.generateRegisteredComponents(fn) + g.generateVersionCheck(fn) g.generateInstanceChecks(fn) g.generateLocalStubs(fn) @@ -678,6 +674,32 @@ func (g *generator) generateFullMethodNames(p printFn) { p(`)`) } +func (g *generator) generateVersionCheck(p printFn) { + selfVersion := version.SelfVersion() + + p(``) + p(`// CodeGen version check.`) + p("var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[%d][%d]struct{}](%s)", + version.CodeGenMajor, version.CodeGenMinor, + fmt.Sprintf("`"+` +ERROR: You generated this file with 'kod generate' %s (codegen +version %s). The generated code is incompatible with the version of the +github.com/go-kod/kod module that you're using. The kod module +version can be found in your go.mod file or by running the following command. + + go list -m github.com/go-kod/kod + +We recommend updating the kod module and the 'kod generate' command by +running the following. + + go get github.com/go-kod/kod@latest + go install github.com/go-kod/kod/cmd/kod@latest + +Then, re-run 'kod generate' and re-build your code. If the problem persists, +please file an issue at https://github.com/go-kod/kod/issues. +`+"`", selfVersion, version.CodeGenSemVersion)) +} + // generateInstanceChecks generates code that checks that every component // implementation type implements kod.InstanceOf[T] for the appropriate T. func (g *generator) generateInstanceChecks(p printFn) { diff --git a/examples/helloworld/kod_gen.go b/examples/helloworld/kod_gen.go index 5f68ed7..4dc8266 100644 --- a/examples/helloworld/kod_gen.go +++ b/examples/helloworld/kod_gen.go @@ -68,6 +68,25 @@ func init() { }) } +// CodeGen version check. +var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` +ERROR: You generated this file with 'kod generate' (devel) (codegen +version v0.1.0). The generated code is incompatible with the version of the +github.com/go-kod/kod module that you're using. The kod module +version can be found in your go.mod file or by running the following command. + + go list -m github.com/go-kod/kod + +We recommend updating the kod module and the 'kod generate' command by +running the following. + + go get github.com/go-kod/kod@latest + go install github.com/go-kod/kod/cmd/kod@latest + +Then, re-run 'kod generate' and re-build your code. If the problem persists, +please file an issue at https://github.com/go-kod/kod/issues. +`) + // kod.InstanceOf checks. var _ kod.InstanceOf[kod.Main] = (*App)(nil) var _ kod.InstanceOf[HelloWorld] = (*helloWorld)(nil) diff --git a/internal/version/version.go b/internal/version/version.go new file mode 100644 index 0000000..146cdbe --- /dev/null +++ b/internal/version/version.go @@ -0,0 +1,38 @@ +package version + +import ( + "fmt" + "runtime/debug" + + "github.com/samber/lo" +) + +const ( + // CodeGenMajor is the major version of the generated code. + CodeGenMajor = 0 + // CodeGenMinor is the minor version of the generated code. + CodeGenMinor = 1 + // codeGenPatch is the patch version of the generated code. + codeGenPatch = 0 +) + +// CodeGenSemVersion is the version of the generated code. +var CodeGenSemVersion = SemVer{Major: CodeGenMajor, Minor: CodeGenMinor, Patch: codeGenPatch} + +// SemVer represents a semantic version. +type SemVer struct { + Major int + Minor int + Patch int +} + +// String returns the string representation of the semantic version. +func (v SemVer) String() string { + return fmt.Sprintf("v%d.%d.%d", v.Major, v.Minor, v.Patch) +} + +// SelfVersion returns the version of the running tool binary. +func SelfVersion() string { + info := lo.Must(debug.ReadBuildInfo()) + return info.Main.Version +} diff --git a/tests/case1/kod_gen.go b/tests/case1/kod_gen.go index 8d1070a..2b549eb 100644 --- a/tests/case1/kod_gen.go +++ b/tests/case1/kod_gen.go @@ -239,6 +239,25 @@ func init() { }) } +// CodeGen version check. +var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` +ERROR: You generated this file with 'kod generate' (devel) (codegen +version v0.1.0). The generated code is incompatible with the version of the +github.com/go-kod/kod module that you're using. The kod module +version can be found in your go.mod file or by running the following command. + + go list -m github.com/go-kod/kod + +We recommend updating the kod module and the 'kod generate' command by +running the following. + + go get github.com/go-kod/kod@latest + go install github.com/go-kod/kod/cmd/kod@latest + +Then, re-run 'kod generate' and re-build your code. If the problem persists, +please file an issue at https://github.com/go-kod/kod/issues. +`) + // kod.InstanceOf checks. var _ kod.InstanceOf[test1Controller] = (*test1ControllerImpl)(nil) var _ kod.InstanceOf[testService] = (*serviceImpl)(nil) diff --git a/tests/case2/kod_gen.go b/tests/case2/kod_gen.go index 3ed8ff3..0d05a03 100644 --- a/tests/case2/kod_gen.go +++ b/tests/case2/kod_gen.go @@ -52,6 +52,25 @@ func init() { }) } +// CodeGen version check. +var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` +ERROR: You generated this file with 'kod generate' (devel) (codegen +version v0.1.0). The generated code is incompatible with the version of the +github.com/go-kod/kod module that you're using. The kod module +version can be found in your go.mod file or by running the following command. + + go list -m github.com/go-kod/kod + +We recommend updating the kod module and the 'kod generate' command by +running the following. + + go get github.com/go-kod/kod@latest + go install github.com/go-kod/kod/cmd/kod@latest + +Then, re-run 'kod generate' and re-build your code. If the problem persists, +please file an issue at https://github.com/go-kod/kod/issues. +`) + // kod.InstanceOf checks. var _ kod.InstanceOf[Test1Component] = (*test1Component)(nil) var _ kod.InstanceOf[Test2Component] = (*test2Component)(nil) diff --git a/tests/case3/kod_gen.go b/tests/case3/kod_gen.go index 5c273f1..f0fa75f 100644 --- a/tests/case3/kod_gen.go +++ b/tests/case3/kod_gen.go @@ -67,6 +67,25 @@ func init() { }) } +// CodeGen version check. +var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` +ERROR: You generated this file with 'kod generate' (devel) (codegen +version v0.1.0). The generated code is incompatible with the version of the +github.com/go-kod/kod module that you're using. The kod module +version can be found in your go.mod file or by running the following command. + + go list -m github.com/go-kod/kod + +We recommend updating the kod module and the 'kod generate' command by +running the following. + + go get github.com/go-kod/kod@latest + go install github.com/go-kod/kod/cmd/kod@latest + +Then, re-run 'kod generate' and re-build your code. If the problem persists, +please file an issue at https://github.com/go-kod/kod/issues. +`) + // kod.InstanceOf checks. var _ kod.InstanceOf[Test1Component] = (*test1Component)(nil) var _ kod.InstanceOf[Test2Component] = (*test2Component)(nil) diff --git a/tests/case4/kod_gen.go b/tests/case4/kod_gen.go index 3ee9261..54dcb5f 100644 --- a/tests/case4/kod_gen.go +++ b/tests/case4/kod_gen.go @@ -67,6 +67,25 @@ func init() { }) } +// CodeGen version check. +var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` +ERROR: You generated this file with 'kod generate' (devel) (codegen +version v0.1.0). The generated code is incompatible with the version of the +github.com/go-kod/kod module that you're using. The kod module +version can be found in your go.mod file or by running the following command. + + go list -m github.com/go-kod/kod + +We recommend updating the kod module and the 'kod generate' command by +running the following. + + go get github.com/go-kod/kod@latest + go install github.com/go-kod/kod/cmd/kod@latest + +Then, re-run 'kod generate' and re-build your code. If the problem persists, +please file an issue at https://github.com/go-kod/kod/issues. +`) + // kod.InstanceOf checks. var _ kod.InstanceOf[Test1Component] = (*test1Component)(nil) var _ kod.InstanceOf[Test2Component] = (*test2Component)(nil) diff --git a/tests/case5/kod_gen.go b/tests/case5/kod_gen.go index 3de95c5..65b09b2 100644 --- a/tests/case5/kod_gen.go +++ b/tests/case5/kod_gen.go @@ -35,6 +35,25 @@ func init() { }) } +// CodeGen version check. +var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` +ERROR: You generated this file with 'kod generate' (devel) (codegen +version v0.1.0). The generated code is incompatible with the version of the +github.com/go-kod/kod module that you're using. The kod module +version can be found in your go.mod file or by running the following command. + + go list -m github.com/go-kod/kod + +We recommend updating the kod module and the 'kod generate' command by +running the following. + + go get github.com/go-kod/kod@latest + go install github.com/go-kod/kod/cmd/kod@latest + +Then, re-run 'kod generate' and re-build your code. If the problem persists, +please file an issue at https://github.com/go-kod/kod/issues. +`) + // kod.InstanceOf checks. var _ kod.InstanceOf[kod.Main] = (*refStructImpl)(nil) var _ kod.InstanceOf[TestRefStruct1] = (*testRefStruct1)(nil) diff --git a/tests/graphcase/kod_gen.go b/tests/graphcase/kod_gen.go index 1928c7c..3f87f7a 100644 --- a/tests/graphcase/kod_gen.go +++ b/tests/graphcase/kod_gen.go @@ -94,6 +94,25 @@ func init() { }) } +// CodeGen version check. +var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` +ERROR: You generated this file with 'kod generate' (devel) (codegen +version v0.1.0). The generated code is incompatible with the version of the +github.com/go-kod/kod module that you're using. The kod module +version can be found in your go.mod file or by running the following command. + + go list -m github.com/go-kod/kod + +We recommend updating the kod module and the 'kod generate' command by +running the following. + + go get github.com/go-kod/kod@latest + go install github.com/go-kod/kod/cmd/kod@latest + +Then, re-run 'kod generate' and re-build your code. If the problem persists, +please file an issue at https://github.com/go-kod/kod/issues. +`) + // kod.InstanceOf checks. var _ kod.InstanceOf[test1Controller] = (*test1ControllerImpl)(nil) var _ kod.InstanceOf[HTTPController] = (*httpControllerImpl)(nil) diff --git a/version.go b/version.go new file mode 100644 index 0000000..0f39716 --- /dev/null +++ b/version.go @@ -0,0 +1,14 @@ +package kod + +import ( + "github.com/go-kod/kod/internal/version" +) + +// The following types are used to check, at compile time, that every +// kod_gen.go file uses the codegen API version that is linked into the binary. +type ( + // CodeGenVersion is the version of the codegen API. + CodeGenVersion[_ any] string + // CodeGenLatestVersion is the latest version of the codegen API. + CodeGenLatestVersion = CodeGenVersion[[version.CodeGenMajor][version.CodeGenMinor]struct{}] +)