Files
DevPack/docs/DEVELOPMENT.md
2026-03-03 18:20:18 +08:00

18 KiB
Raw Blame History

DevPack 开发指南

版本v1.0.0-draft
更新日期2026-03-03
作者DevPack Team


1. 开发环境搭建

1.1 前置要求

工具 最低版本 安装方式
Go 1.22+ golang.org
Git 2.30+ git-scm.com
Make 3.81+ 系统包管理器Windows 推荐用 choco install make
golangci-lint 1.55+ go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

1.2 获取代码

git clone https://github.com/user/devpack.git
cd devpack

1.3 安装依赖

go mod download

1.4 验证环境

# 运行测试
go test ./...

# 构建
go build -o devpack ./cmd/devpack/

# 代码检查
golangci-lint run

2. 项目结构详解

DevPack/
├── cmd/                        # 应用入口
│   └── devpack/
│       ├── main.go             # 主入口
│       └── commands/           # CLI 命令
│           ├── root.go         # 根命令
│           ├── init.go         # devpack init
│           ├── scan.go         # devpack scan
│           ├── capture.go      # devpack capture
│           ├── restore.go      # devpack restore
│           ├── diff.go         # devpack diff
│           ├── export.go       # devpack export
│           ├── import.go       # devpack import
│           ├── list.go         # devpack list
│           ├── profile.go      # devpack profile
│           └── version.go      # devpack version
│
├── internal/                   # 内部包
│   ├── collector/              # 采集器核心
│   │   ├── collector.go        # Collector 接口定义
│   │   ├── registry.go         # 采集器注册中心
│   │   ├── options.go          # 扫描/捕获/还原选项
│   │   ├── result.go           # 结果类型定义
│   │   │
│   │   ├── runtime/            # 运行时采集器
│   │   │   ├── go.go           # Go 采集器
│   │   │   ├── node.go         # Node.js 采集器
│   │   │   ├── python.go       # Python 采集器
│   │   │   ├── java.go         # Java 采集器
│   │   │   ├── rust.go         # Rust 采集器
│   │   │   ├── dotnet.go       # .NET 采集器
│   │   │   └── runtime_test.go # 运行时采集器测试
│   │   │
│   │   ├── editor/             # 编辑器采集器
│   │   │   ├── vscode.go       # VS Code 采集器
│   │   │   ├── jetbrains.go    # JetBrains 采集器
│   │   │   ├── vim.go          # Vim/Neovim 采集器
│   │   │   └── editor_test.go
│   │   │
│   │   ├── shell/              # Shell 采集器
│   │   │   ├── powershell.go   # PowerShell 采集器
│   │   │   ├── bash.go         # Bash 采集器
│   │   │   ├── zsh.go          # Zsh 采集器
│   │   │   ├── fish.go         # Fish 采集器
│   │   │   ├── terminal.go     # 终端模拟器配置Windows Terminal 等)
│   │   │   └── shell_test.go
│   │   │
│   │   ├── pkgmgr/             # 包管理器采集器
│   │   │   ├── scoop.go        # Scoop 采集器
│   │   │   ├── chocolatey.go   # Chocolatey 采集器
│   │   │   ├── winget.go       # Winget 采集器
│   │   │   ├── homebrew.go     # Homebrew 采集器
│   │   │   ├── apt.go          # APT 采集器
│   │   │   └── pkgmgr_test.go
│   │   │
│   │   ├── git/                # Git 配置采集器
│   │   │   ├── gitconfig.go
│   │   │   └── git_test.go
│   │   │
│   │   ├── env/                # 环境变量采集器
│   │   │   ├── envvar.go
│   │   │   └── env_test.go
│   │   │
│   │   ├── font/               # 字体采集器
│   │   │   ├── font.go
│   │   │   └── font_test.go
│   │   │
│   │   └── ssh/                # SSH/GPG 采集器
│   │       ├── ssh.go
│   │       └── ssh_test.go
│   │
│   ├── pack/                   # 打包引擎
│   │   ├── packer.go           # 打包器
│   │   ├── unpacker.go         # 解包器
│   │   ├── format.go           # Pack 格式定义
│   │   └── pack_test.go
│   │
│   ├── restore/                # 还原引擎
│   │   ├── engine.go           # 还原核心逻辑
│   │   ├── planner.go          # 还原计划生成
│   │   ├── conflict.go         # 冲突检测与处理
│   │   ├── rollback.go         # 回滚管理
│   │   ├── verifier.go         # 还原验证
│   │   └── restore_test.go
│   │
│   ├── profile/                # 配置文件管理
│   │   ├── profile.go          # Profile 定义与操作
│   │   ├── parser.go           # YAML 解析
│   │   └── profile_test.go
│   │
│   ├── diff/                   # 差异对比
│   │   ├── differ.go           # 差异计算
│   │   ├── renderer.go         # 差异展示
│   │   └── diff_test.go
│   │
│   ├── crypto/                 # 加密模块
│   │   ├── aesgcm.go           # AES-256-GCM 实现
│   │   ├── argon2.go           # Argon2id 密钥派生
│   │   └── crypto_test.go
│   │
│   ├── platform/               # 平台适配层
│   │   ├── platform.go         # Platform 接口
│   │   ├── detect.go           # 平台检测
│   │   ├── windows.go          # Windows 实现
│   │   ├── darwin.go           # macOS 实现
│   │   ├── linux.go            # Linux 实现
│   │   └── platform_test.go
│   │
│   ├── config/                 # 应用配置
│   │   ├── config.go           # 全局配置
│   │   └── paths.go            # 路径管理
│   │
│   ├── ui/                     # 终端 UI
│   │   ├── printer.go          # 格式化输出
│   │   ├── progress.go         # 进度条
│   │   ├── table.go            # 表格输出
│   │   └── prompt.go           # 用户交互
│   │
│   └── logger/                 # 日志
│       └── logger.go           # 日志初始化
│
├── pkg/                        # 公共包
│   ├── manifest/               # Pack 清单
│   │   ├── manifest.go         # Manifest 结构定义
│   │   └── validate.go         # Manifest 验证
│   └── version/                # 版本信息
│       └── version.go          # 版本号管理
│
├── plugins/                    # 外部插件目录
│   └── README.md               # 插件开发指南
│
├── test/                       # 集成与端到端测试
│   ├── e2e/                    # 端到端测试
│   │   ├── capture_restore_test.go
│   │   └── testdata/           # 测试数据
│   └── fixtures/               # 测试 fixtures
│       └── sample-pack/
│
├── scripts/                    # 脚本
│   ├── build.sh                # 构建脚本
│   ├── install.sh              # 安装脚本
│   └── release.sh              # 发布脚本
│
├── .github/
│   └── workflows/
│       ├── ci.yml              # CI 流水线
│       └── release.yml         # 发布流水线
│
├── .golangci.yml               # Lint 配置
├── .gitignore
├── go.mod
├── go.sum
├── Makefile
├── LICENSE
└── README.md

3. 编码规范

3.1 Go 编码规范

遵循 Effective GoGo Code Review Comments

命名规范

// ✅ 包名:小写单词,不用下划线
package collector
package pkgmgr

// ✅ 接口名:动词或名词,单方法接口用 -er 后缀
type Collector interface { ... }
type Scanner interface { ... }

// ✅ 导出函数/方法:大驼峰
func NewRegistry() *Registry { ... }
func (r *Registry) Register(c Collector) error { ... }

// ✅ 非导出函数/方法:小驼峰
func parseVersion(raw string) (string, error) { ... }

// ✅ 常量:大驼峰(导出)或小驼峰(非导出)
const DefaultTimeout = 30 * time.Second
const maxRetries = 3

// ✅ 错误变量Err 前缀
var ErrCollectorNotFound = errors.New("collector not found")
var ErrPackCorrupted = errors.New("pack file corrupted")

错误处理

// ✅ 使用 fmt.Errorf 包装错误,提供上下文
func (c *GoCollector) Scan(ctx context.Context) (*ScanResult, error) {
    version, err := c.detectVersion(ctx)
    if err != nil {
        return nil, fmt.Errorf("go collector: detect version: %w", err)
    }
    // ...
}

// ✅ 自定义错误类型用于需要类型判断的场景
type CollectorError struct {
    Collector string
    Op        string
    Err       error
}

func (e *CollectorError) Error() string {
    return fmt.Sprintf("%s: %s: %v", e.Collector, e.Op, e.Err)
}

func (e *CollectorError) Unwrap() error {
    return e.Err
}

Context 使用

// ✅ 第一个参数传递 context
func (c *GoCollector) Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error) {
    // 使用 context 控制超时
    ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
    defer cancel()

    cmd := exec.CommandContext(ctx, "go", "version")
    // ...
}

3.2 项目约定

约定 说明
文件命名 小写 + 下划线:go_collector.go, scan_result.go
测试文件 *_test.go 放在同一包下
平台特定 使用 Go build tag//go:build windows
依赖注入 通过接口 + 构造函数实现
配置 使用 Viper支持文件 + 环境变量 + 命令行参数
日志 使用 zerolog结构化日志

3.3 Git 提交规范

使用 Conventional Commits

<type>(<scope>): <description>

[optional body]

[optional footer(s)]

类型 (type)

Type 说明
feat 新功能
fix Bug 修复
docs 文档
style 代码格式
refactor 重构
perf 性能优化
test 测试
chore 构建/工具

Scope 示例: collector, pack, restore, cli, platform, crypto

示例:

feat(collector): add VS Code extension collector

Scan and capture VS Code extensions list and settings.

Closes #42

4. 开发工作流

4.1 分支策略

main (稳定发布)
 │
 ├── develop (开发主干)
 │    │
 │    ├── feature/collector-vscode    (功能分支)
 │    ├── feature/restore-engine      (功能分支)
 │    └── fix/scan-timeout            (修复分支)
 │
 └── release/v0.1.0 (发布分支)

4.2 开发流程

  1. 创建分支: git checkout -b feature/xxx develop
  2. 开发 & 测试: 编写代码 + 单元测试
  3. 代码检查: make lint
  4. 提交: 遵循 Conventional Commits
  5. 推送 & PR 推送分支,创建 Pull Request
  6. Code Review 至少一人 Review 通过
  7. 合并: Squash Merge 到 develop

4.3 常用 Make 命令

# 构建
make build              # 构建当前平台
make build-all          # 构建所有平台
make build-windows      # 构建 Windows 版本
make build-darwin       # 构建 macOS 版本
make build-linux        # 构建 Linux 版本

# 测试
make test               # 运行所有测试
make test-unit          # 运行单元测试
make test-integration   # 运行集成测试
make test-e2e           # 运行端到端测试
make test-coverage      # 生成覆盖率报告

# 代码质量
make lint               # 运行 golangci-lint
make fmt                # 格式化代码
make vet                # go vet 检查

# 开发
make run                # 编译并运行
make dev                # 开发模式(热重载)
make clean              # 清理构建产物

# 发布
make release            # 使用 GoReleaser 发布
make snapshot           # GoReleaser 快照(不发布)

5. 添加新采集器指南

5.1 步骤

以添加 "Docker" 采集器为例:

Step 1: 创建采集器文件

// internal/collector/runtime/docker.go

package runtime

import (
    "context"
    "github.com/user/devpack/internal/collector"
)

// DockerCollector Docker 环境采集器
type DockerCollector struct{}

// 确保实现了 Collector 接口
var _ collector.Collector = (*DockerCollector)(nil)

func NewDockerCollector() *DockerCollector {
    return &DockerCollector{}
}

func (c *DockerCollector) Name() string        { return "docker" }
func (c *DockerCollector) DisplayName() string { return "Docker" }
func (c *DockerCollector) Description() string {
    return "Captures Docker version, images, and configuration"
}
func (c *DockerCollector) Category() collector.Category {
    return collector.CategoryRuntime
}

func (c *DockerCollector) IsAvailable(ctx context.Context) bool {
    _, err := exec.LookPath("docker")
    return err == nil
}

func (c *DockerCollector) Scan(ctx context.Context, opts collector.ScanOptions) (*collector.ScanResult, error) {
    // 实现扫描逻辑
    // 1. 检测 Docker 版本
    // 2. 列出本地镜像
    // 3. 获取 Docker daemon 配置
    return nil, nil
}

func (c *DockerCollector) Capture(ctx context.Context, targetDir string, opts collector.CaptureOptions) error {
    // 实现捕获逻辑
    return nil
}

func (c *DockerCollector) Restore(ctx context.Context, sourceDir string, opts collector.RestoreOptions) error {
    // 实现还原逻辑
    return nil
}

func (c *DockerCollector) Verify(ctx context.Context) (*collector.VerifyResult, error) {
    // 实现验证逻辑
    return nil, nil
}

Step 2: 注册采集器

// internal/collector/registry.go 中添加注册

func NewDefaultRegistry() *Registry {
    r := NewRegistry()

    // Runtime collectors
    r.Register(runtime.NewGoCollector())
    r.Register(runtime.NewNodeCollector())
    r.Register(runtime.NewDockerCollector())  // 新增
    // ...

    return r
}

Step 3: 编写测试

// internal/collector/runtime/docker_test.go

func TestDockerCollector_Scan(t *testing.T) {
    c := NewDockerCollector()

    if !c.IsAvailable(context.Background()) {
        t.Skip("Docker not available")
    }

    result, err := c.Scan(context.Background(), collector.ScanOptions{})
    assert.NoError(t, err)
    assert.NotEmpty(t, result.Items)
}

Step 4: 更新文档

在 README.md 和 PRD.md 中添加 Docker 采集器的说明。


6. 调试指南

6.1 日志级别

# 设置日志级别
DEVPACK_LOG_LEVEL=debug devpack scan

# 或通过命令行参数
devpack scan --log-level debug
级别 用途
trace 非常详细的调试信息
debug 调试信息
info 正常操作信息(默认)
warn 警告
error 错误
fatal 致命错误

6.2 VS Code 调试配置

// .vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug DevPack Scan",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "program": "${workspaceFolder}/cmd/devpack",
            "args": ["scan", "--verbose"],
            "env": {
                "DEVPACK_LOG_LEVEL": "debug"
            }
        },
        {
            "name": "Debug DevPack Capture",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "program": "${workspaceFolder}/cmd/devpack",
            "args": ["capture", "--name", "test-env"],
            "env": {
                "DEVPACK_LOG_LEVEL": "debug"
            }
        }
    ]
}

6.3 常见问题排查

问题 排查方向
采集器找不到工具 检查 PATH 环境变量,确认工具已安装
Pack 文件损坏 使用 devpack verify <pack> 校验
还原权限不足 以管理员身份运行
跨版本不兼容 检查 Manifest 中的 format_ver

7. 发布流程

7.1 版本号规范

遵循 Semantic Versioning

MAJOR.MINOR.PATCH[-PRERELEASE]

- MAJOR: 不兼容的 API 变更
- MINOR: 向下兼容的功能新增
- PATCH: 向下兼容的 Bug 修复

7.2 发布步骤

# 1. 确保所有测试通过
make test

# 2. 更新 CHANGELOG
# 编辑 CHANGELOG.md

# 3. 创建 Release Tag
git tag -a v0.1.0 -m "Release v0.1.0"
git push origin v0.1.0

# 4. GoReleaser 自动构建发布CI 触发)
# 或手动:
make release

7.3 GoReleaser 配置

# .goreleaser.yml
version: 2

builds:
  - main: ./cmd/devpack
    binary: devpack
    env:
      - CGO_ENABLED=0
    goos:
      - windows
      - darwin
      - linux
    goarch:
      - amd64
      - arm64
    ldflags:
      - -s -w
      - -X github.com/user/devpack/pkg/version.Version={{.Version}}
      - -X github.com/user/devpack/pkg/version.Commit={{.Commit}}
      - -X github.com/user/devpack/pkg/version.Date={{.Date}}

archives:
  - format: tar.gz
    format_overrides:
      - goos: windows
        format: zip

checksum:
  name_template: 'checksums.txt'

changelog:
  sort: asc
  filters:
    exclude:
      - '^docs:'
      - '^test:'
      - '^chore:'