aqi cli 2.0.1

This commit is contained in:
ideaa
2026-04-14 09:15:31 +08:00
parent 1a3f979c31
commit a4fdb505d8
8 changed files with 162 additions and 46 deletions
+1 -2
View File
@@ -216,7 +216,7 @@ LDFLAGS = "-X '$(FLAGS_PKG).BuildDate=$(BUILD_DATE)' \
-X '$(FLAGS_PKG).Branch=$(GIT_BRANCH)' \
-X '$(FLAGS_PKG).CommitVersion=$(GIT_COMMIT)' \
-X '$(FLAGS_PKG).Revision=$(GIT_REVISION)' \
-extldflags '-static -s -w'"
-s -w"
```
### API Documentation
@@ -236,4 +236,3 @@ This creates a `docs/` directory with:
Options: `-r` router dir (default `./internal/router`), `-f` format (`json` or `markdown`), `-p` package name.
+1 -2
View File
@@ -216,7 +216,7 @@ LDFLAGS = "-X '$(FLAGS_PKG).BuildDate=$(BUILD_DATE)' \
-X '$(FLAGS_PKG).Branch=$(GIT_BRANCH)' \
-X '$(FLAGS_PKG).CommitVersion=$(GIT_COMMIT)' \
-X '$(FLAGS_PKG).Revision=$(GIT_REVISION)' \
-extldflags '-static -s -w'"
-s -w"
```
### API 文档生成
@@ -236,4 +236,3 @@ aqi docgen init
可选参数:`-r` 路由目录(默认 `./internal/router`)、`-f` 输出格式(`json``markdown`)、`-p` 包名。
+8 -3
View File
@@ -8,10 +8,15 @@ BUILD_PATH := ./dist
BUILD_DATE = $(shell date +'%F %T')
# git versions
GIT_BRANCH = -
GIT_COMMIT = -
GIT_REVISION = -
ifneq ($(wildcard .git),)
GIT_BRANCH = $(shell git rev-parse --abbrev-ref HEAD)
GIT_COMMIT = $(shell git rev-list --count HEAD)
GIT_REVISION = $(shell git rev-parse --short HEAD)
GIT_COMMITAT = $(shell git --no-pager log -1 --format="%at")
endif
# flags
FLAGS_PKG = github.com/wonli/aqi
@@ -19,7 +24,7 @@ LDFLAGS = "-X '$(FLAGS_PKG).BuildDate=$(BUILD_DATE)' \
-X '$(FLAGS_PKG).Branch=$(GIT_BRANCH)' \
-X '$(FLAGS_PKG).CommitVersion=$(GIT_COMMIT)' \
-X '$(FLAGS_PKG).Revision=$(GIT_REVISION)' \
-extldflags '-static -s -w'"
-s -w"
# params
GO_FLAGS = -ldflags $(LDFLAGS) -trimpath -tags netgo
@@ -43,4 +48,4 @@ windows:
$(call go/build,windows,amd64,.exe)
linux64:
$(call go/build,linux,amd64)
$(call go/build,linux,amd64)
+49 -26
View File
@@ -5,7 +5,9 @@ import (
"html/template"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"github.com/spf13/cobra"
)
@@ -18,14 +20,15 @@ var newCmd = &cobra.Command{
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
projectName := args[0]
projectDir := projectDirName(projectName)
packageName := projectName
if packageNameFlag != "" {
packageName = packageNameFlag
}
createDir(projectName)
createProject(projectName, packageName)
createDir(projectDir)
createProject(projectDir, packageName)
},
}
@@ -34,7 +37,13 @@ func init() {
rootCmd.AddCommand(newCmd)
}
func createDir(projectName string) {
func projectDirName(projectName string) string {
projectName = strings.TrimRight(projectName, `/\`)
projectName = strings.ReplaceAll(projectName, `\`, "/")
return path.Base(projectName)
}
func createDir(projectDir string) {
// 检查目录是否存在
dirs := []struct {
dirName string
@@ -48,7 +57,7 @@ func createDir(projectName string) {
}
for _, d := range dirs {
dirPath := filepath.Join(projectName, d.dirName)
dirPath := filepath.Join(projectDir, d.dirName)
if err := os.MkdirAll(dirPath, 0755); err != nil {
fmt.Printf("Error creating directory: %v\n", err)
os.Exit(1)
@@ -58,23 +67,7 @@ func createDir(projectName string) {
func createProject(name, packageName string) {
// 复制模板文件
templates := []struct {
templatePath string
outputPath string
}{
{"templates/default/main.go.tmpl", "main.go"},
{"templates/default/go.mod.tmpl", "go.mod"},
{"templates/default/makefile.tmpl", "Makefile"},
{"templates/default/cmd/api.go.tmpl", "cmd/api.go"},
{"templates/default/cmd/dal.go.tmpl", "cmd/dal.go"},
{"templates/default/cmd/boot.go.tmpl", "cmd/boot.go"},
{"templates/default/dbc/dbc.go.tmpl", "internal/dbc/dbc.go"},
{"templates/default/middlewares/app.go.tmpl", "internal/middlewares/app.go"},
{"templates/default/middlewares/recovery.go.tmpl", "internal/middlewares/recovery.go"},
{"templates/default/middlewares/cors.go.tmpl", "internal/middlewares/cors.go"},
{"templates/default/router/action.go.tmpl", "internal/router/action.go"},
{"templates/default/router/api.go.tmpl", "internal/router/api.go"},
}
templates := projectTemplates()
for _, t := range templates {
// 从嵌入的文件系统读取模板
@@ -97,11 +90,7 @@ func createProject(name, packageName string) {
os.Exit(1)
}
data := struct {
PackageName string
}{
PackageName: packageName,
}
data := newProjectTemplateData(name, packageName)
if err := tmpl.Execute(outputFile, data); err != nil {
fmt.Printf("Error executing template: %v\n", err)
@@ -119,6 +108,40 @@ func createProject(name, packageName string) {
fmt.Printf("Successfully created project: %s\n", name)
}
func newProjectTemplateData(name, packageName string) any {
return struct {
PackageName string
AppName string
}{
PackageName: packageName,
AppName: filepath.Base(name),
}
}
func projectTemplates() []struct {
templatePath string
outputPath string
} {
return []struct {
templatePath string
outputPath string
}{
{"templates/default/gitignore.tmpl", ".gitignore"},
{"templates/default/main.go.tmpl", "main.go"},
{"templates/default/go.mod.tmpl", "go.mod"},
{"templates/default/makefile.tmpl", "Makefile"},
{"templates/default/cmd/api.go.tmpl", "cmd/api.go"},
{"templates/default/cmd/dal.go.tmpl", "cmd/dal.go"},
{"templates/default/cmd/boot.go.tmpl", "cmd/boot.go"},
{"templates/default/dbc/dbc.go.tmpl", "internal/dbc/dbc.go"},
{"templates/default/middlewares/app.go.tmpl", "internal/middlewares/app.go"},
{"templates/default/middlewares/recovery.go.tmpl", "internal/middlewares/recovery.go"},
{"templates/default/middlewares/cors.go.tmpl", "internal/middlewares/cors.go"},
{"templates/default/router/action.go.tmpl", "internal/router/action.go"},
{"templates/default/router/api.go.tmpl", "internal/router/api.go"},
}
}
// runGoModTidy 在指定目录先更新依赖然后执行
func runGoModTidy(projectDir string) error {
getCmd := exec.Command("go", "get", "-u", ".")
+76
View File
@@ -0,0 +1,76 @@
package cli
import (
"bytes"
"os"
"path/filepath"
"strings"
"testing"
"text/template"
)
func TestProjectDirName(t *testing.T) {
tests := []struct {
input string
want string
}{
{input: "myapp", want: "myapp"},
{input: "github.com/a/b", want: "b"},
{input: "github.com/a/b/", want: "b"},
{input: `github.com\a\b`, want: "b"},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
if got := projectDirName(tt.input); got != tt.want {
t.Fatalf("projectDirName(%q) = %q, want %q", tt.input, got, tt.want)
}
})
}
}
func TestCreateProjectUsesAppNameInMakefile(t *testing.T) {
tmplContent, err := os.ReadFile(filepath.Join("templates", "default", "makefile.tmpl"))
if err != nil {
t.Fatalf("read makefile template: %v", err)
}
tmpl, err := template.New("Makefile").Parse(string(tmplContent))
if err != nil {
t.Fatalf("parse makefile template: %v", err)
}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, newProjectTemplateData("b", "github.com/a/b")); err != nil {
t.Fatalf("execute makefile template: %v", err)
}
if !strings.Contains(buf.String(), "APP_NAME = b") {
t.Fatalf("Makefile APP_NAME mismatch:\n%s", buf.String())
}
}
func TestCreateProjectIncludesGitignoreTemplate(t *testing.T) {
tmplContent, err := os.ReadFile(filepath.Join("templates", "default", "gitignore.tmpl"))
if err != nil {
t.Fatalf("read gitignore template: %v", err)
}
content := string(tmplContent)
for _, want := range []string{".idea/", ".vscode/", ".fleet/", ".zed/"} {
if !strings.Contains(content, want) {
t.Fatalf("gitignore template missing %q:\n%s", want, content)
}
}
found := false
for _, tmpl := range projectTemplates() {
if tmpl.outputPath == ".gitignore" && tmpl.templatePath == "templates/default/gitignore.tmpl" {
found = true
break
}
}
if !found {
t.Fatal("project templates do not include .gitignore output")
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ var verCmd = &cobra.Command{
Use: "version",
Short: "Version of this CLI",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Version: 2.0")
fmt.Println("Version: 2.0.1")
},
}
@@ -0,0 +1,18 @@
.idea/
.vscode/
.fleet/
.zed/
.history/
data/
dist/
trashDir/
.DS_Store
Thumbs.db
*.swp
*.swo
*~
config-devel.yaml
go.work*
+8 -12
View File
@@ -1,4 +1,4 @@
APP_NAME = {{.PackageName}}
APP_NAME = {{.AppName}}
APP_PATH = .
# 编译路径
@@ -7,18 +7,14 @@ BUILD_PATH := ./dist
# 编译时间
BUILD_DATE = $(shell date +'%F %T')
ifeq ($(shell test -d .git && echo yes),yes)
# git已初始化,可以安全执行git命令
GIT_BRANCH = $(shell git rev-parse --abbrev-ref HEAD)
GIT_COMMIT = $(shell git rev-list --count HEAD)
GIT_REVISION = $(shell git rev-parse --short HEAD)
GIT_COMMITAT = $(shell git --no-pager log -1 --format="%at")
else
# git未初始化,相关变量设为默认值
GIT_BRANCH = -
GIT_COMMIT = -
GIT_REVISION = -
GIT_COMMITAT = -
ifneq ($(wildcard .git),)
GIT_BRANCH = $(shell git rev-parse --abbrev-ref HEAD)
GIT_COMMIT = $(shell git rev-list --count HEAD)
GIT_REVISION = $(shell git rev-parse --short HEAD)
endif
# support包名称
@@ -27,7 +23,7 @@ LDFLAGS = "-X '$(FLAGS_PKG).BuildDate=$(BUILD_DATE)' \
-X '$(FLAGS_PKG).Branch=$(GIT_BRANCH)' \
-X '$(FLAGS_PKG).CommitVersion=$(GIT_COMMIT)' \
-X '$(FLAGS_PKG).Revision=$(GIT_REVISION)' \
-extldflags '-static -s -w'"
-s -w"
# 编译参数
GO_FLAGS = -ldflags $(LDFLAGS) -trimpath -tags netgo
@@ -48,4 +44,4 @@ linux:
$(call go/build,linux,amd64)
windows:
$(call go/build,windows,amd64,.exe)
$(call go/build,windows,amd64,.exe)