feat: 初始化shop-crm-agent项目,实现基础CLI与CRM操作能力
本提交初始化完整的shop-crm-agent项目: 1. 创建基础项目结构与配置文件(.gitignore、go.mod/go.sum) 2. 添加项目许可协议与文档(README.md、AGENTS.md、SKILL.md) 3. 实现核心CLI入口与命令框架 4. 封装Protobuf API客户端与完整的命令实现 5. 添加单元测试覆盖核心功能与边界情况 6. 提供构建脚本与版本管理能力
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
//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)
|
||||
}
|
||||
Reference in New Issue
Block a user