Merge pull request #953 from go-admin-team/fix/check-file-create-errors

fix🐛: report failures from app and migrate -g file generation
This commit is contained in:
wenjianzhang
2026-09-27 14:07:56 +08:00
committed by GitHub
11 changed files with 96 additions and 29 deletions
+5 -4
View File
@@ -554,10 +554,11 @@ func renderAll(data any, tpls ...*template.Template) ([][]byte, error) {
return out, nil
}
// writeGenerated writes one generated file, creating its directory first.
// It stands in for pkg.FileCreate, which returns no error at all and, when
// the file cannot be created, closes a nil file and ends the process with
// log.Fatalln - one unwritable path took the whole server down with it.
// writeGenerated writes one generated file, creating its directory first,
// which pkg.FileCreate does not do. It replaced pkg.FileCreate here while
// that returned no error and, when the file could not be created, ended the
// process with log.Fatalln - one unwritable path took the whole server down
// with it. go-admin-core v2.11.0 made pkg.FileCreate return the error.
func writeGenerated(path string, content []byte) error {
if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
return err
+3 -3
View File
@@ -134,9 +134,9 @@ func TestNOActionsGenWritesNothingWhenATemplateFails(t *testing.T) {
}
}
// pkg.FileCreate, which this used to write through, ends the process with
// log.Fatalln when it cannot create the file. Reaching the assertions at all
// is half of this test.
// pkg.FileCreate, which this used to write through, ended the process with
// log.Fatalln when it could not create the file, until go-admin-core v2.11.0.
// Reaching the assertions at all is half of this test.
func TestNOActionsGenReportsAFileItCannotWrite(t *testing.T) {
dir := genWorkspace(t)
blocker := filepath.Join(dir, "app", "admin", "models")
+18 -6
View File
@@ -7,6 +7,7 @@ import (
"github.com/go-admin-team/go-admin-core/v2/sdk/pkg"
"github.com/go-admin-team/go-admin-core/v2/sdk/pkg/utils"
"github.com/spf13/cobra"
"os"
"text/template"
)
@@ -33,7 +34,10 @@ func run() {
//1. 读取配置
fmt.Println(`generate migration file`)
_ = genFile()
if err := genFile(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
@@ -80,11 +84,19 @@ func genFile() error {
m := map[string]string{}
m["appName"] = appName
var b1 bytes.Buffer
err = t1.Execute(&b1, m)
pkg.FileCreate(b1, "./cmd/api/"+appName+".go")
if err = t1.Execute(&b1, m); err != nil {
return err
}
t2, err := template.ParseFiles("template/router.template")
if err != nil {
return err
}
var b2 bytes.Buffer
err = t2.Execute(&b2, nil)
pkg.FileCreate(b2, appPath+"/router/router.go")
return nil
if err = t2.Execute(&b2, nil); err != nil {
return err
}
if err = pkg.FileCreate(b1, "./cmd/api/"+appName+".go"); err != nil {
return err
}
return pkg.FileCreate(b2, appPath+"/router/router.go")
}
+54
View File
@@ -0,0 +1,54 @@
package migrate
import (
"os"
"path/filepath"
"testing"
)
// chdirWithTemplates runs the test from an empty directory that has the
// repository's template/ directory in it, which is what genFile reads from
// the working directory.
func chdirWithTemplates(t *testing.T) string {
t.Helper()
tmpl, err := filepath.Abs(filepath.Join("..", "..", "template"))
if err != nil {
t.Fatal(err)
}
dir := t.TempDir()
if err := os.Symlink(tmpl, filepath.Join(dir, "template")); err != nil {
t.Fatal(err)
}
t.Chdir(dir)
return dir
}
func TestGenFileWritesTheMigration(t *testing.T) {
dir := chdirWithTemplates(t)
out := filepath.Join(dir, "cmd", "migrate", "migration", "version-local")
if err := os.MkdirAll(out, 0o755); err != nil {
t.Fatal(err)
}
if err := genFile(); err != nil {
t.Fatalf("genFile: %v", err)
}
files, err := filepath.Glob(filepath.Join(out, "*_migrate.go"))
if err != nil {
t.Fatal(err)
}
if len(files) != 1 {
t.Fatalf("generated files = %v, want one", files)
}
}
// Run from a directory without cmd/migrate/migration, writing the file fails.
// The failure used to end the process from inside pkg.FileCreate and, before
// that, was dropped by genFile's caller; it now reaches the caller.
func TestGenFileReportsAFileItCannotWrite(t *testing.T) {
chdirWithTemplates(t)
if err := genFile(); err == nil {
t.Fatal("genFile returned nil with no directory to write into")
}
}
+7 -7
View File
@@ -106,7 +106,7 @@ func run() {
)
} else {
fmt.Println(`generate migration file`)
_ = genFile()
exitOnError(os.Stderr, genFile())
}
}
@@ -360,11 +360,11 @@ func genFile() error {
m["Package"] = "version"
}
var b1 bytes.Buffer
err = t1.Execute(&b1, m)
if goAdmin {
pkg.FileCreate(b1, "./cmd/migrate/migration/version/"+m["GenerateTime"]+"_migrate.go")
} else {
pkg.FileCreate(b1, "./cmd/migrate/migration/version-local/"+m["GenerateTime"]+"_migrate.go")
if err = t1.Execute(&b1, m); err != nil {
return err
}
return nil
if goAdmin {
return pkg.FileCreate(b1, "./cmd/migrate/migration/version/"+m["GenerateTime"]+"_migrate.go")
}
return pkg.FileCreate(b1, "./cmd/migrate/migration/version-local/"+m["GenerateTime"]+"_migrate.go")
}
+1 -1
View File
@@ -5,7 +5,7 @@ go 1.27.1
require (
github.com/gin-gonic/gin v1.12.0
github.com/glebarez/sqlite v1.11.0
github.com/go-admin-team/go-admin-core/v2 v2.10.0
github.com/go-admin-team/go-admin-core/v2 v2.11.0
gorm.io/gorm v1.31.2
)
+2 -2
View File
@@ -58,8 +58,8 @@ github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-admin-team/go-admin-core/v2 v2.10.0 h1:MM1wl9s2iW3M4GFsT8SyaUWaj2Q8m1NSuundXc6DWzI=
github.com/go-admin-team/go-admin-core/v2 v2.10.0/go.mod h1:Q0FfO+8pfPNkPqk9fcRpe2sSOHfir82cjZO8Nol/8SI=
github.com/go-admin-team/go-admin-core/v2 v2.11.0 h1:kAiGaQWPHHiEnoa+UeKQqTmIQAptDPjEbdu6s4jBZ7A=
github.com/go-admin-team/go-admin-core/v2 v2.11.0/go.mod h1:Q0FfO+8pfPNkPqk9fcRpe2sSOHfir82cjZO8Nol/8SI=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+1 -1
View File
@@ -11,7 +11,7 @@ require (
github.com/casbin/casbin/v3 v3.8.1
github.com/gin-gonic/gin v1.12.0
github.com/glebarez/sqlite v1.11.0
github.com/go-admin-team/go-admin-core/v2 v2.10.0
github.com/go-admin-team/go-admin-core/v2 v2.11.0
github.com/google/uuid v1.6.0
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.26.6+incompatible
github.com/mssola/user_agent v0.6.0
+2 -2
View File
@@ -145,8 +145,8 @@ github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-admin-team/go-admin-core/v2 v2.10.0 h1:MM1wl9s2iW3M4GFsT8SyaUWaj2Q8m1NSuundXc6DWzI=
github.com/go-admin-team/go-admin-core/v2 v2.10.0/go.mod h1:Q0FfO+8pfPNkPqk9fcRpe2sSOHfir82cjZO8Nol/8SI=
github.com/go-admin-team/go-admin-core/v2 v2.11.0 h1:kAiGaQWPHHiEnoa+UeKQqTmIQAptDPjEbdu6s4jBZ7A=
github.com/go-admin-team/go-admin-core/v2 v2.11.0/go.mod h1:Q0FfO+8pfPNkPqk9fcRpe2sSOHfir82cjZO8Nol/8SI=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
+1 -1
View File
@@ -40,7 +40,7 @@ require (
github.com/gin-contrib/sse v1.1.1 // indirect
github.com/gin-gonic/gin v1.12.0 // indirect
github.com/glebarez/sqlite v1.11.0 // indirect
github.com/go-admin-team/go-admin-core/v2 v2.10.0 // indirect
github.com/go-admin-team/go-admin-core/v2 v2.11.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/jsonpointer v1.0.0 // indirect
github.com/go-openapi/jsonreference v1.0.0 // indirect
+2 -2
View File
@@ -145,8 +145,8 @@ github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-admin-team/go-admin-core/v2 v2.10.0 h1:MM1wl9s2iW3M4GFsT8SyaUWaj2Q8m1NSuundXc6DWzI=
github.com/go-admin-team/go-admin-core/v2 v2.10.0/go.mod h1:Q0FfO+8pfPNkPqk9fcRpe2sSOHfir82cjZO8Nol/8SI=
github.com/go-admin-team/go-admin-core/v2 v2.11.0 h1:kAiGaQWPHHiEnoa+UeKQqTmIQAptDPjEbdu6s4jBZ7A=
github.com/go-admin-team/go-admin-core/v2 v2.11.0/go.mod h1:Q0FfO+8pfPNkPqk9fcRpe2sSOHfir82cjZO8Nol/8SI=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=