Skip to content

Commit 2e70e2a

Browse files
authored
feat: codegen version check (#259)
1 parent a053608 commit 2e70e2a

File tree

11 files changed

+214
-6
lines changed

11 files changed

+214
-6
lines changed

Taskfile.yml

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ tasks:
4040
-covermode=atomic ./... ./tests/... \
4141
-coverpkg .,./cmd/...,./internal/...,./interceptor/...
4242
git checkout tests/case1/kod_gen_mock.go
43+
git checkout tests/graphcase/kod_gen.go
4344
sources:
4445
- "**/**.go"
4546
generates:

cmd/kod/internal/generate_generator.go

+28-6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"golang.org/x/tools/go/packages"
2323

2424
"github.com/go-kod/kod/internal/callgraph"
25+
"github.com/go-kod/kod/internal/version"
2526
)
2627

2728
const (
@@ -562,19 +563,14 @@ func (g *generator) generate() error {
562563
return nil
563564
}
564565

565-
// // Process components in deterministic order.
566-
// sort.Slice(g.components, func(i, j int) bool {
567-
// return g.components[i].intfName() < g.components[j].intfName()
568-
// })
569-
570566
// Generate the file body.
571567
var body bytes.Buffer
572568
{
573569
fn := func(format string, args ...interface{}) {
574570
fmt.Fprintln(&body, fmt.Sprintf(format, args...))
575571
}
576-
// g.generateVersionCheck(fn)
577572
g.generateRegisteredComponents(fn)
573+
g.generateVersionCheck(fn)
578574
g.generateInstanceChecks(fn)
579575
g.generateLocalStubs(fn)
580576

@@ -678,6 +674,32 @@ func (g *generator) generateFullMethodNames(p printFn) {
678674
p(`)`)
679675
}
680676

677+
func (g *generator) generateVersionCheck(p printFn) {
678+
selfVersion := version.SelfVersion()
679+
680+
p(``)
681+
p(`// CodeGen version check.`)
682+
p("var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[%d][%d]struct{}](%s)",
683+
version.CodeGenMajor, version.CodeGenMinor,
684+
fmt.Sprintf("`"+`
685+
ERROR: You generated this file with 'kod generate' %s (codegen
686+
version %s). The generated code is incompatible with the version of the
687+
github.com/go-kod/kod module that you're using. The kod module
688+
version can be found in your go.mod file or by running the following command.
689+
690+
go list -m github.com/go-kod/kod
691+
692+
We recommend updating the kod module and the 'kod generate' command by
693+
running the following.
694+
695+
go get github.com/go-kod/kod@latest
696+
go install github.com/go-kod/kod/cmd/kod@latest
697+
698+
Then, re-run 'kod generate' and re-build your code. If the problem persists,
699+
please file an issue at https://github.com/go-kod/kod/issues.
700+
`+"`", selfVersion, version.CodeGenSemVersion))
701+
}
702+
681703
// generateInstanceChecks generates code that checks that every component
682704
// implementation type implements kod.InstanceOf[T] for the appropriate T.
683705
func (g *generator) generateInstanceChecks(p printFn) {

examples/helloworld/kod_gen.go

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/version/version.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package version
2+
3+
import (
4+
"fmt"
5+
"runtime/debug"
6+
7+
"github.com/samber/lo"
8+
)
9+
10+
const (
11+
// CodeGenMajor is the major version of the generated code.
12+
CodeGenMajor = 0
13+
// CodeGenMinor is the minor version of the generated code.
14+
CodeGenMinor = 1
15+
// codeGenPatch is the patch version of the generated code.
16+
codeGenPatch = 0
17+
)
18+
19+
// CodeGenSemVersion is the version of the generated code.
20+
var CodeGenSemVersion = SemVer{Major: CodeGenMajor, Minor: CodeGenMinor, Patch: codeGenPatch}
21+
22+
// SemVer represents a semantic version.
23+
type SemVer struct {
24+
Major int
25+
Minor int
26+
Patch int
27+
}
28+
29+
// String returns the string representation of the semantic version.
30+
func (v SemVer) String() string {
31+
return fmt.Sprintf("v%d.%d.%d", v.Major, v.Minor, v.Patch)
32+
}
33+
34+
// SelfVersion returns the version of the running tool binary.
35+
func SelfVersion() string {
36+
info := lo.Must(debug.ReadBuildInfo())
37+
return info.Main.Version
38+
}

tests/case1/kod_gen.go

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/case2/kod_gen.go

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/case3/kod_gen.go

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/case4/kod_gen.go

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/case5/kod_gen.go

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/graphcase/kod_gen.go

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

version.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package kod
2+
3+
import (
4+
"github.com/go-kod/kod/internal/version"
5+
)
6+
7+
// The following types are used to check, at compile time, that every
8+
// kod_gen.go file uses the codegen API version that is linked into the binary.
9+
type (
10+
// CodeGenVersion is the version of the codegen API.
11+
CodeGenVersion[_ any] string
12+
// CodeGenLatestVersion is the latest version of the codegen API.
13+
CodeGenLatestVersion = CodeGenVersion[[version.CodeGenMajor][version.CodeGenMinor]struct{}]
14+
)

0 commit comments

Comments
 (0)