Skip to content

Commit ce11adb

Browse files
authored
feat: add code generation headers in safe to edit files (#5136)
1 parent 894e8b1 commit ce11adb

19 files changed

+228
-1
lines changed

tools/goctl/api/gogen/config.tpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Code scaffolded by goctl. Safe to edit.
2+
// goctl {{.version}}
3+
14
package config
25

36
import {{.authImport}}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
package gogen
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"strings"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
12+
)
13+
14+
// TestGenerationComments verifies that all generated files have appropriate generation comments
15+
func TestGenerationComments(t *testing.T) {
16+
// Create a temporary directory for our test
17+
tempDir, err := os.MkdirTemp("", "goctl_test_")
18+
require.NoError(t, err)
19+
defer os.RemoveAll(tempDir)
20+
21+
// Create a simple API spec for testing
22+
apiContent := `
23+
syntax = "v1"
24+
25+
type HelloRequest {
26+
Name string ` + "`json:\"name\"`" + `
27+
}
28+
29+
type HelloResponse {
30+
Message string ` + "`json:\"message\"`" + `
31+
}
32+
33+
service hello-api {
34+
@handler helloHandler
35+
post /hello (HelloRequest) returns (HelloResponse)
36+
}`
37+
38+
// Write the API spec to a temporary file
39+
apiFile := filepath.Join(tempDir, "test.api")
40+
err = os.WriteFile(apiFile, []byte(apiContent), 0644)
41+
require.NoError(t, err)
42+
43+
// Parse and generate the API files using the correct function signature
44+
err = DoGenProject(apiFile, tempDir, "gozero", false)
45+
require.NoError(t, err)
46+
47+
// Define expected files and their comment types
48+
expectedFiles := map[string]string{
49+
// Files that should have "DO NOT EDIT" comments (regenerated files)
50+
"internal/types/types.go": "DO NOT EDIT",
51+
52+
// Files that should have "Safe to edit" comments (scaffolded files)
53+
"internal/handler/hellohandler.go": "Safe to edit",
54+
"internal/config/config.go": "Safe to edit",
55+
"hello.go": "Safe to edit", // main file
56+
"internal/svc/servicecontext.go": "Safe to edit",
57+
"internal/logic/hellologic.go": "Safe to edit",
58+
}
59+
60+
// Check each file for the correct generation comment
61+
for filePath, expectedCommentType := range expectedFiles {
62+
fullPath := filepath.Join(tempDir, filePath)
63+
64+
// Skip if file doesn't exist (some files might not be generated in all cases)
65+
if _, err := os.Stat(fullPath); os.IsNotExist(err) {
66+
t.Logf("File %s does not exist, skipping", filePath)
67+
continue
68+
}
69+
70+
content, err := os.ReadFile(fullPath)
71+
require.NoError(t, err, "Failed to read file: %s", filePath)
72+
73+
contentStr := string(content)
74+
lines := strings.Split(contentStr, "\n")
75+
76+
// Check that the file starts with proper generation comments
77+
require.GreaterOrEqual(t, len(lines), 2, "File %s should have at least 2 lines", filePath)
78+
79+
if expectedCommentType == "DO NOT EDIT" {
80+
assert.Contains(t, lines[0], "// Code generated by goctl. DO NOT EDIT.",
81+
"File %s should have 'DO NOT EDIT' comment as first line", filePath)
82+
} else if expectedCommentType == "Safe to edit" {
83+
assert.Contains(t, lines[0], "// Code scaffolded by goctl. Safe to edit.",
84+
"File %s should have 'Safe to edit' comment as first line", filePath)
85+
}
86+
87+
// Check that the second line contains the version
88+
assert.Contains(t, lines[1], "// goctl",
89+
"File %s should have version comment as second line", filePath)
90+
assert.Contains(t, lines[1], version.BuildVersion,
91+
"File %s should contain version %s in second line", filePath, version.BuildVersion)
92+
}
93+
}
94+
95+
// TestRoutesGenerationComment verifies routes files have "DO NOT EDIT" comment
96+
func TestRoutesGenerationComment(t *testing.T) {
97+
// Create a temporary directory for our test
98+
tempDir, err := os.MkdirTemp("", "goctl_routes_test_")
99+
require.NoError(t, err)
100+
defer os.RemoveAll(tempDir)
101+
102+
// Create an API spec with multiple handlers to ensure routes file is generated
103+
apiContent := `
104+
syntax = "v1"
105+
106+
type HelloRequest {
107+
Name string ` + "`json:\"name\"`" + `
108+
}
109+
110+
type HelloResponse {
111+
Message string ` + "`json:\"message\"`" + `
112+
}
113+
114+
service hello-api {
115+
@handler helloHandler
116+
post /hello (HelloRequest) returns (HelloResponse)
117+
118+
@handler worldHandler
119+
get /world returns (HelloResponse)
120+
}`
121+
122+
// Write the API spec to a temporary file
123+
apiFile := filepath.Join(tempDir, "test.api")
124+
err = os.WriteFile(apiFile, []byte(apiContent), 0644)
125+
require.NoError(t, err)
126+
127+
// Generate the API files using the correct function signature
128+
err = DoGenProject(apiFile, tempDir, "gozero", false)
129+
require.NoError(t, err)
130+
131+
// Check the routes file specifically
132+
routesFile := filepath.Join(tempDir, "internal/handler/routes.go")
133+
if _, err := os.Stat(routesFile); os.IsNotExist(err) {
134+
t.Skip("Routes file not generated, skipping test")
135+
return
136+
}
137+
138+
content, err := os.ReadFile(routesFile)
139+
require.NoError(t, err, "Failed to read routes.go")
140+
141+
contentStr := string(content)
142+
lines := strings.Split(contentStr, "\n")
143+
144+
// Check that routes.go has "DO NOT EDIT" comment
145+
require.GreaterOrEqual(t, len(lines), 2, "Routes file should have at least 2 lines")
146+
assert.Contains(t, lines[0], "// Code generated by goctl. DO NOT EDIT.",
147+
"Routes file should have 'DO NOT EDIT' comment")
148+
assert.Contains(t, lines[1], "// goctl",
149+
"Routes file should have version comment")
150+
assert.Contains(t, lines[1], version.BuildVersion,
151+
"Routes file should contain version %s", version.BuildVersion)
152+
}
153+
154+
// TestVersionInTemplateData verifies that version is correctly passed to templates
155+
func TestVersionInTemplateData(t *testing.T) {
156+
// Test that BuildVersion is available
157+
assert.NotEmpty(t, version.BuildVersion, "BuildVersion should not be empty")
158+
}
159+
160+
// TestCommentsFollowGoStandards verifies our comments follow Go community standards
161+
func TestCommentsFollowGoStandards(t *testing.T) {
162+
// Test the format of our generation comments
163+
doNotEditComment := "// Code generated by goctl. DO NOT EDIT."
164+
safeToEditComment := "// Code scaffolded by goctl. Safe to edit."
165+
166+
// Both should be valid Go comments
167+
assert.True(t, strings.HasPrefix(doNotEditComment, "//"),
168+
"DO NOT EDIT comment should start with //")
169+
assert.True(t, strings.HasPrefix(safeToEditComment, "//"),
170+
"Safe to edit comment should start with //")
171+
172+
// Should contain key information
173+
assert.Contains(t, doNotEditComment, "goctl",
174+
"DO NOT EDIT comment should mention goctl")
175+
assert.Contains(t, safeToEditComment, "goctl",
176+
"Safe to edit comment should mention goctl")
177+
assert.Contains(t, doNotEditComment, "DO NOT EDIT",
178+
"Should clearly state DO NOT EDIT")
179+
assert.Contains(t, safeToEditComment, "Safe to edit",
180+
"Should clearly state Safe to edit")
181+
}

tools/goctl/api/gogen/genconfig.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
99
"github.com/zeromicro/go-zero/tools/goctl/config"
10+
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
1011
"github.com/zeromicro/go-zero/tools/goctl/util/format"
1112
"github.com/zeromicro/go-zero/tools/goctl/vars"
1213
)
@@ -61,6 +62,7 @@ func genConfig(dir, projectPkg string, cfg *config.Config, api *spec.ApiSpec) er
6162
"auth": strings.Join(auths, "\n"),
6263
"jwtTrans": strings.Join(jwtTransList, "\n"),
6364
"projectPkg": projectPkg,
65+
"version": version.BuildVersion,
6466
},
6567
})
6668
}

tools/goctl/api/gogen/genhandlers.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
1010
"github.com/zeromicro/go-zero/tools/goctl/config"
11+
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
1112
"github.com/zeromicro/go-zero/tools/goctl/util"
1213
"github.com/zeromicro/go-zero/tools/goctl/util/format"
1314
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
@@ -64,6 +65,7 @@ func genHandler(dir, rootPkg, projectPkg string, cfg *config.Config, group spec.
6465
"HasDoc": len(route.JoinedDoc()) > 0,
6566
"Doc": getDoc(route.JoinedDoc()),
6667
"projectPkg": projectPkg,
68+
"version": version.BuildVersion,
6769
},
6870
})
6971
}

tools/goctl/api/gogen/genhandlerstest.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
99
"github.com/zeromicro/go-zero/tools/goctl/config"
10+
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
1011
"github.com/zeromicro/go-zero/tools/goctl/util"
1112
"github.com/zeromicro/go-zero/tools/goctl/util/format"
1213
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
@@ -51,6 +52,7 @@ func genHandlerTest(dir, rootPkg, projectPkg string, cfg *config.Config, group s
5152
"HasDoc": len(route.JoinedDoc()) > 0,
5253
"Doc": getDoc(route.JoinedDoc()),
5354
"projectPkg": projectPkg,
55+
"version": version.BuildVersion,
5456
},
5557
})
5658
}

tools/goctl/api/gogen/genlogic.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
1111
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
1212
"github.com/zeromicro/go-zero/tools/goctl/config"
13+
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
1314
"github.com/zeromicro/go-zero/tools/goctl/util/format"
1415
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
1516
"github.com/zeromicro/go-zero/tools/goctl/vars"
@@ -92,6 +93,7 @@ func genLogicByRoute(dir, rootPkg, projectPkg string, cfg *config.Config, group
9293
"hasDoc": len(route.JoinedDoc()) > 0,
9394
"doc": getDoc(route.JoinedDoc()),
9495
"projectPkg": projectPkg,
96+
"version": version.BuildVersion,
9597
},
9698
})
9799
}

tools/goctl/api/gogen/genlogictest.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
99
"github.com/zeromicro/go-zero/tools/goctl/config"
10+
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
1011
"github.com/zeromicro/go-zero/tools/goctl/util/format"
1112
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
1213
)
@@ -74,6 +75,7 @@ func genLogicTestByRoute(dir, rootPkg, projectPkg string, cfg *config.Config, gr
7475
"hasDoc": len(route.JoinedDoc()) > 0,
7576
"doc": getDoc(route.JoinedDoc()),
7677
"projectPkg": projectPkg,
78+
"version": version.BuildVersion,
7779
},
7880
})
7981
}

tools/goctl/api/gogen/genmain.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
99
"github.com/zeromicro/go-zero/tools/goctl/config"
10+
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
1011
"github.com/zeromicro/go-zero/tools/goctl/util/format"
1112
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
1213
"github.com/zeromicro/go-zero/tools/goctl/vars"
@@ -39,6 +40,7 @@ func genMain(dir, rootPkg, projectPkg string, cfg *config.Config, api *spec.ApiS
3940
"importPackages": genMainImports(rootPkg),
4041
"serviceName": configName,
4142
"projectPkg": projectPkg,
43+
"version": version.BuildVersion,
4244
},
4345
})
4446
}

tools/goctl/api/gogen/genmiddleware.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
88
"github.com/zeromicro/go-zero/tools/goctl/config"
9+
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
910
"github.com/zeromicro/go-zero/tools/goctl/util/format"
1011
)
1112

@@ -31,7 +32,8 @@ func genMiddleware(dir string, cfg *config.Config, api *spec.ApiSpec) error {
3132
templateFile: middlewareImplementCodeFile,
3233
builtinTemplate: middlewareImplementCode,
3334
data: map[string]string{
34-
"name": strings.Title(name),
35+
"name": strings.Title(name),
36+
"version": version.BuildVersion,
3537
},
3638
})
3739
if err != nil {

tools/goctl/api/gogen/gensvc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
99
"github.com/zeromicro/go-zero/tools/goctl/config"
10+
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
1011
"github.com/zeromicro/go-zero/tools/goctl/util/format"
1112
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
1213
"github.com/zeromicro/go-zero/tools/goctl/vars"
@@ -54,6 +55,7 @@ func genServiceContext(dir, rootPkg, projectPkg string, cfg *config.Config, api
5455
"middleware": middlewareStr,
5556
"middlewareAssignment": middlewareAssignment,
5657
"projectPkg": projectPkg,
58+
"version": version.BuildVersion,
5759
},
5860
})
5961
}

0 commit comments

Comments
 (0)