本提交初始化完整的shop-crm-agent项目: 1. 创建基础项目结构与配置文件(.gitignore、go.mod/go.sum) 2. 添加项目许可协议与文档(README.md、AGENTS.md、SKILL.md) 3. 实现核心CLI入口与命令框架 4. 封装Protobuf API客户端与完整的命令实现 5. 添加单元测试覆盖核心功能与边界情况 6. 提供构建脚本与版本管理能力
130 lines
3.4 KiB
Go
130 lines
3.4 KiB
Go
//go:build ignore
|
|
|
|
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
const modulePath = "code.zhecent.com/open/shop-crm-agent"
|
|
|
|
func main() {
|
|
if err := run(); err != nil {
|
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func run() error {
|
|
repoRoot, err := os.Getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := os.Stat(filepath.Join(repoRoot, "go.mod")); err != nil {
|
|
return errors.New("build.go must run from the shop-crm-agent repository root")
|
|
}
|
|
moduleCommand := exec.Command("go", "list", "-m", "-f", "{{.Path}}")
|
|
moduleCommand.Dir = repoRoot
|
|
moduleOutput, err := moduleCommand.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("read Go module path: %w: %s", err, strings.TrimSpace(string(moduleOutput)))
|
|
}
|
|
if actualModule := strings.TrimSpace(string(moduleOutput)); actualModule != modulePath {
|
|
return fmt.Errorf("unexpected Go module; want %s", modulePath)
|
|
}
|
|
|
|
env := withEnv(os.Environ(), "CGO_ENABLED", "0")
|
|
if err := runCommand(repoRoot, env, "go", "test", "./..."); err != nil {
|
|
return fmt.Errorf("test shop-crm-agent: %w", err)
|
|
}
|
|
|
|
version := gitVersion(repoRoot)
|
|
binaryName := "shop-crm-agent"
|
|
if runtime.GOOS == "windows" {
|
|
binaryName += ".exe"
|
|
}
|
|
binDir := filepath.Join(repoRoot, "bin")
|
|
if err := os.MkdirAll(binDir, 0o755); err != nil {
|
|
return err
|
|
}
|
|
tempFile, err := os.CreateTemp(binDir, "."+binaryName+".tmp-")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tempPath := tempFile.Name()
|
|
if err := tempFile.Close(); err != nil {
|
|
return err
|
|
}
|
|
if err := os.Remove(tempPath); err != nil {
|
|
return err
|
|
}
|
|
defer os.Remove(tempPath)
|
|
|
|
ldflags := "-s -w -X main.version=" + version
|
|
if err := runCommand(repoRoot, env, "go", "build", "-trimpath", "-ldflags", ldflags, "-o", tempPath, "./cmd/shop-crm-agent"); err != nil {
|
|
return fmt.Errorf("build shop-crm-agent: %w", err)
|
|
}
|
|
if runtime.GOOS != "windows" {
|
|
if err := os.Chmod(tempPath, 0o755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
probe := exec.Command(tempPath, "--version")
|
|
probe.Dir = repoRoot
|
|
probeOutput, err := probe.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("probe built binary: %w: %s", err, strings.TrimSpace(string(probeOutput)))
|
|
}
|
|
|
|
targetPath := filepath.Join(binDir, binaryName)
|
|
if err := replaceBinary(tempPath, targetPath); err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("installed: %s\n", filepath.Join("bin", binaryName))
|
|
fmt.Printf("version: %s\n", strings.TrimSpace(string(probeOutput)))
|
|
return nil
|
|
}
|
|
|
|
func gitVersion(repoRoot string) string {
|
|
command := exec.Command("git", "describe", "--tags", "--always", "--dirty")
|
|
command.Dir = repoRoot
|
|
output, err := command.Output()
|
|
if err != nil || strings.TrimSpace(string(output)) == "" {
|
|
return "dev"
|
|
}
|
|
return strings.TrimSpace(string(output))
|
|
}
|
|
|
|
func replaceBinary(source, target string) error {
|
|
if err := os.Rename(source, target); err != nil {
|
|
return fmt.Errorf("install built binary: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func runCommand(dir string, env []string, name string, args ...string) error {
|
|
command := exec.Command(name, args...)
|
|
command.Dir = dir
|
|
command.Env = env
|
|
command.Stdout = os.Stdout
|
|
command.Stderr = os.Stderr
|
|
return command.Run()
|
|
}
|
|
|
|
func withEnv(env []string, key, value string) []string {
|
|
prefix := key + "="
|
|
result := make([]string, 0, len(env)+1)
|
|
for _, entry := range env {
|
|
if !strings.HasPrefix(entry, prefix) {
|
|
result = append(result, entry)
|
|
}
|
|
}
|
|
return append(result, prefix+value)
|
|
}
|