# DevPack 架构设计文档 > 版本:v1.0.0-draft > 更新日期:2026-03-03 > 作者:DevPack Team --- ## 1. 架构概览 ### 1.1 设计原则 | 原则 | 说明 | |------|------| | **单一二进制** | 编译为无依赖的单一可执行文件 | | **插件化** | 采集器通过接口抽象,支持扩展 | | **安全优先** | 敏感数据加密,操作可回滚 | | **平台适配** | 通过平台适配层处理 OS 差异 | | **幂等性** | 同一 Pack 多次还原结果一致 | | **最小侵入** | 只修改用户级配置,不修改系统级设置(除非明确授权) | ### 1.2 高层架构图 ``` ┌──────────────────────────────────────────────────────────────────┐ │ CLI Layer (Cobra) │ │ ┌──────┐ ┌───────┐ ┌─────────┐ ┌────────┐ ┌──────┐ ┌────────┐ │ │ │ init │ │ scan │ │ capture │ │restore │ │ diff │ │export/ │ │ │ │ │ │ │ │ │ │ │ │ │ │import │ │ │ └──┬───┘ └───┬───┘ └────┬────┘ └───┬────┘ └──┬───┘ └───┬────┘ │ └─────┼─────────┼──────────┼──────────┼─────────┼─────────┼──────┘ │ │ │ │ │ │ ┌─────┴─────────┴──────────┴──────────┴─────────┴─────────┴──────┐ │ Core Engine Layer │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ │ │ Collector │ │ Pack Engine │ │ Restore Engine │ │ │ │ Registry │ │ │ │ │ │ │ └──────┬───────┘ └──────┬───────┘ └────────────┬─────────────┘ │ │ │ │ │ │ │ ┌──────┴───────┐ ┌──────┴───────┐ ┌────────────┴─────────────┐ │ │ │ Profile │ │ Crypto │ │ Dependency Resolver │ │ │ │ Manager │ │ Module │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────────────────┘ │ └─────────────────────────┬───────────────────────────────────────┘ │ ┌─────────────────────────┴───────────────────────────────────────┐ │ Platform Abstraction Layer │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ Windows │ │ macOS │ │ Linux │ │ │ │ Adapter │ │ Adapter │ │ Adapter │ │ │ └────────────┘ └────────────┘ └────────────┘ │ └─────────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────┴───────────────────────────────────────┐ │ Collector Plugins │ │ ┌─────────┐ ┌─────────┐ ┌────────┐ ┌───────┐ ┌─────┐ ┌─────┐ │ │ │ Runtime │ │ Package │ │ Editor │ │ Shell │ │ Git │ │ Env │ │ │ └─────────┘ └─────────┘ └────────┘ └───────┘ └─────┘ └─────┘ │ │ ┌─────────┐ ┌─────────┐ │ │ │ Font │ │ SSH/GPG │ │ │ └─────────┘ └─────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 2. 核心模块设计 ### 2.1 采集器系统 (Collector System) 采集器是 DevPack 的核心,负责扫描和收集环境信息。所有采集器实现统一的接口。 #### 2.1.1 Collector 接口 ```go // Collector 定义了所有采集器必须实现的接口 type Collector interface { // Name 返回采集器名称(唯一标识) Name() string // DisplayName 返回采集器的显示名称 DisplayName() string // Description 返回采集器的描述信息 Description() string // Category 返回采集器所属分类 Category() Category // IsAvailable 检测当前系统是否支持此采集器 IsAvailable(ctx context.Context) bool // Scan 扫描当前环境,返回扫描结果 Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error) // Capture 捕获环境数据,写入到指定目录 Capture(ctx context.Context, targetDir string, opts CaptureOptions) error // Restore 从指定目录还原环境 Restore(ctx context.Context, sourceDir string, opts RestoreOptions) error // Verify 验证还原后的环境是否正确 Verify(ctx context.Context) (*VerifyResult, error) } // Category 采集器分类 type Category string const ( CategoryRuntime Category = "runtime" // 编程语言运行时 CategoryPackage Category = "package" // 包管理器 CategoryEditor Category = "editor" // 编辑器/IDE CategoryShell Category = "shell" // Shell 配置 CategoryGit Category = "git" // Git 配置 CategoryEnv Category = "env" // 环境变量 CategoryFont Category = "font" // 字体 CategorySSH Category = "ssh" // SSH/GPG 密钥 CategoryCustom Category = "custom" // 自定义 ) // ScanResult 扫描结果 type ScanResult struct { Collector string `json:"collector"` Category Category `json:"category"` Items []ScanItem `json:"items"` Timestamp time.Time `json:"timestamp"` Platform PlatformInfo `json:"platform"` } // ScanItem 单个扫描项 type ScanItem struct { Name string `json:"name"` Version string `json:"version,omitempty"` Path string `json:"path,omitempty"` Properties map[string]string `json:"properties,omitempty"` Size int64 `json:"size,omitempty"` Children []ScanItem `json:"children,omitempty"` } ``` #### 2.1.2 采集器注册中心 ```go // Registry 采集器注册中心 type Registry struct { collectors map[string]Collector mu sync.RWMutex } // Register 注册一个采集器 func (r *Registry) Register(c Collector) error // Get 获取指定名称的采集器 func (r *Registry) Get(name string) (Collector, bool) // List 列出所有已注册的采集器 func (r *Registry) List() []Collector // ListByCategory 按分类列出采集器 func (r *Registry) ListByCategory(cat Category) []Collector // ScanAll 使用所有可用的采集器扫描 func (r *Registry) ScanAll(ctx context.Context, opts ScanOptions) ([]*ScanResult, error) ``` #### 2.1.3 内置采集器实现示例 以 Go 运行时采集器为例: ```go type GoCollector struct{} func (c *GoCollector) Name() string { return "go" } func (c *GoCollector) DisplayName() string { return "Go Runtime" } func (c *GoCollector) Category() Category { return CategoryRuntime } func (c *GoCollector) Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error) { result := &ScanResult{ Collector: c.Name(), Category: c.Category(), } // 检测 Go 版本 version, err := exec.CommandContext(ctx, "go", "version").Output() // ... 解析版本信息 // 获取 go env 信息 envJSON, err := exec.CommandContext(ctx, "go", "env", "-json").Output() // ... 解析环境变量 // 获取全局安装的工具 // ... 扫描 GOPATH/bin return result, nil } ``` ### 2.2 打包引擎 (Pack Engine) #### 2.2.1 Pack 文件格式 `.devpack` 文件本质上是一个经过组织的 tar.gz 归档文件: ``` my-env.devpack (tar.gz) ├── manifest.json # Pack 清单(元数据) ├── checksum.sha256 # 文件校验和 ├── collectors/ # 各采集器数据 │ ├── runtime/ │ │ ├── go/ │ │ │ ├── metadata.json # Go 环境元数据 │ │ │ └── data/ # Go 相关数据文件 │ │ ├── node/ │ │ │ ├── metadata.json │ │ │ └── data/ │ │ └── python/ │ │ ├── metadata.json │ │ └── data/ │ ├── editor/ │ │ └── vscode/ │ │ ├── metadata.json │ │ ├── extensions.json # 扩展列表 │ │ └── data/ # 设置文件 │ │ ├── settings.json │ │ ├── keybindings.json │ │ └── snippets/ │ ├── shell/ │ │ ├── powershell/ │ │ │ ├── metadata.json │ │ │ └── data/ │ │ └── bash/ │ │ ├── metadata.json │ │ └── data/ │ ├── package/ │ │ └── scoop/ │ │ ├── metadata.json │ │ └── data/ │ ├── git/ │ │ ├── metadata.json │ │ └── data/ │ └── env/ │ ├── metadata.json │ └── data/ └── encrypted/ # 加密数据(可选) └── ssh/ └── data.enc # 加密的 SSH 密钥 ``` #### 2.2.2 Manifest 结构 ```go // Manifest Pack 清单 type Manifest struct { // 元信息 Version string `json:"version"` // DevPack 版本 FormatVer string `json:"format_ver"` // Pack 格式版本 Name string `json:"name"` // Pack 名称 Description string `json:"description"` // 描述 Author string `json:"author"` // 作者 CreatedAt time.Time `json:"created_at"` // 创建时间 PackID string `json:"pack_id"` // 唯一 ID (UUID) // 源环境信息 Source SourceInfo `json:"source"` // 采集器数据索引 Collectors []CollectorEntry `json:"collectors"` // 加密信息 Encryption *EncryptionInfo `json:"encryption,omitempty"` // 校验信息 Checksum string `json:"checksum"` // 整包校验和 } // SourceInfo 源环境信息 type SourceInfo struct { Hostname string `json:"hostname"` OS string `json:"os"` // windows, darwin, linux OSVersion string `json:"os_version"` Arch string `json:"arch"` // amd64, arm64 Username string `json:"username"` } // CollectorEntry 采集器条目 type CollectorEntry struct { Name string `json:"name"` Category Category `json:"category"` ItemCount int `json:"item_count"` DataPath string `json:"data_path"` DataSize int64 `json:"data_size"` Checksum string `json:"checksum"` } ``` #### 2.2.3 打包流程 ``` 用户执行 capture 命令 │ ▼ ┌─────────────────┐ │ 加载 Profile │ ─── 确定需要运行哪些采集器 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 运行采集器 │ ─── 并行扫描 → 收集数据 → 写入临时目录 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 生成 Manifest │ ─── 创建清单文件、计算校验和 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 加密敏感数据 │ ─── 对标记为敏感的数据进行加密(可选) └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 压缩归档 │ ─── tar.gz 打包 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 输出 .devpack │ ─── 写入最终文件 └─────────────────┘ ``` ### 2.3 还原引擎 (Restore Engine) #### 2.3.1 还原流程 ``` 用户执行 restore 命令 │ ▼ ┌─────────────────┐ │ 校验 Pack 文件 │ ─── 检查完整性、版本兼容性 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 解析 Manifest │ ─── 读取清单,确定还原内容 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 平台兼容检查 │ ─── 确认目标平台与源平台匹配 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 冲突检测 │ ─── 检测与现有环境的冲突 └────────┬────────┘ │ ▼ ┌─────────────────────┐ │ 创建还原点(可选) │ ─── 备份当前环境用于回滚 └────────┬────────────┘ │ ▼ ┌─────────────────┐ │ 依赖排序 │ ─── 按依赖关系排序安装顺序 └────────┬────────┘ │ ▼ ┌─────────────────┐ ┌──────────────┐ │ 执行还原 │ ──▶ │ 逐项安装/配置 │ └────────┬────────┘ └──────────────┘ │ ▼ ┌─────────────────┐ │ 验证还原结果 │ ─── 运行各采集器的验证逻辑 └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 生成还原报告 │ ─── 成功/失败/跳过的项目清单 └─────────────────┘ ``` #### 2.3.2 冲突处理策略 ```go // ConflictStrategy 冲突处理策略 type ConflictStrategy int const ( ConflictSkip ConflictStrategy = iota // 跳过(保留现有) ConflictOverwrite // 覆盖(使用 Pack 中的) ConflictMerge // 合并 ConflictPrompt // 询问用户 ConflictNewest // 使用较新版本 ) // ConflictItem 冲突项 type ConflictItem struct { Collector string ItemName string CurrentVer string PackVer string Type ConflictType // VersionMismatch, AlreadyExists, DependencyConflict } ``` ### 2.4 配置文件管理 (Profile Manager) #### 2.4.1 Profile 格式 使用 YAML 格式定义 Profile: ```yaml # ~/.devpack/profiles/golang-dev.yaml name: golang-dev description: "Go 全栈开发环境" version: "1.0" # 采集器配置 collectors: runtime: enabled: true include: - go - node exclude: [] options: go: capture_gopath_bin: true # 捕获 GOPATH/bin 下的工具 capture_go_env: true # 捕获 go env 配置 editor: enabled: true include: - vscode options: vscode: capture_extensions: true capture_settings: true capture_keybindings: true capture_snippets: true # 排除的扩展 exclude_extensions: - "ms-vsliveshare.vsliveshare" shell: enabled: true include: - powershell - bash package: enabled: true include: - scoop git: enabled: true options: capture_aliases: true capture_hooks: false env: enabled: true options: # 只捕获匹配的环境变量 include_patterns: - "GOPATH" - "GOROOT" - "PATH" - "NODE_*" exclude_patterns: - "*_KEY" - "*_SECRET" - "*_TOKEN" ssh: enabled: false # 还原选项 restore: conflict_strategy: prompt # skip, overwrite, merge, prompt, newest create_restore_point: true dry_run_first: false ``` ### 2.5 平台适配层 (Platform Abstraction Layer) ```go // Platform 平台适配接口 type Platform interface { // OS 返回操作系统标识 OS() string // Arch 返回架构标识 Arch() string // HomeDir 返回用户主目录 HomeDir() string // ConfigDir 返回配置文件目录 ConfigDir() string // DataDir 返回数据目录 DataDir() string // GetEnvVar 获取环境变量 GetEnvVar(key string) string // SetEnvVar 设置用户级环境变量 SetEnvVar(key, value string) error // AddToPath 添加目录到 PATH AddToPath(dir string) error // IsAdmin 是否以管理员身份运行 IsAdmin() bool // PackageManagers 返回可用的包管理器 PackageManagers() []string // DefaultShell 返回默认 Shell DefaultShell() string // InstallFont 安装字体文件 InstallFont(fontPath string) error // RunAsAdmin 以管理员权限运行命令 RunAsAdmin(cmd string, args ...string) error } ``` 各平台实现: ```go // Windows 平台实现 type WindowsPlatform struct{} func (p *WindowsPlatform) OS() string { return "windows" } func (p *WindowsPlatform) HomeDir() string { return os.Getenv("USERPROFILE") } func (p *WindowsPlatform) ConfigDir() string { return os.Getenv("APPDATA") } func (p *WindowsPlatform) DefaultShell() string { return "powershell" } func (p *WindowsPlatform) PackageManagers() []string { var pms []string if _, err := exec.LookPath("scoop"); err == nil { pms = append(pms, "scoop") } if _, err := exec.LookPath("choco"); err == nil { pms = append(pms, "chocolatey") } if _, err := exec.LookPath("winget"); err == nil { pms = append(pms, "winget") } return pms } // macOS 平台实现 type DarwinPlatform struct{} // Linux 平台实现 type LinuxPlatform struct{} ``` ### 2.6 加密模块 (Crypto Module) ```go // Encryptor 加密器接口 type Encryptor interface { // Encrypt 使用密码加密数据 Encrypt(data []byte, password string) ([]byte, error) // Decrypt 使用密码解密数据 Decrypt(encrypted []byte, password string) ([]byte, error) } // AESGCMEncryptor AES-256-GCM 加密实现 type AESGCMEncryptor struct{} // 密钥派生使用 Argon2id func deriveKey(password string, salt []byte) []byte { return argon2.IDKey([]byte(password), salt, 1, 64*1024, 4, 32) } ``` --- ## 3. 数据流 ### 3.1 扫描 → 打包数据流 ``` ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────┐ │ 用户系统 │ ──▶ │ Collectors │ ──▶ │ ScanResult │ ──▶ │ 临时目录 │ │ (实际环境) │ │ (扫描采集) │ │ (结构化数据)│ │ (文件数据)│ └────────────┘ └────────────┘ └────────────┘ └────┬─────┘ │ ┌────────────┐ ┌────────────┐ │ │ .devpack │ ◀── │ Pack 引擎 │ ◀────────┘ │ (归档文件) │ │ (压缩打包) │ └────────────┘ └────────────┘ ``` ### 3.2 导入 → 还原数据流 ``` ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────┐ │ .devpack │ ──▶ │ 解压校验 │ ──▶ │ Manifest │ ──▶ │ 还原计划 │ │ (归档文件) │ │ │ │ 解析 │ │ 生成 │ └────────────┘ └────────────┘ └────────────┘ └────┬─────┘ │ ┌────────────┐ ┌────────────┐ │ │ 目标系统 │ ◀── │ Restore │ ◀────────┘ │ (已还原) │ │ Engine │ └────────────┘ └────────────┘ ``` --- ## 4. 技术选型 ### 4.1 核心依赖 | 依赖 | 用途 | 选型理由 | |------|------|---------| | [cobra](https://github.com/spf13/cobra) | CLI 框架 | Go 生态最流行的 CLI 框架 | | [viper](https://github.com/spf13/viper) | 配置管理 | 支持多种配置格式 | | [zerolog](https://github.com/rs/zerolog) | 日志 | 高性能结构化日志 | | [color](https://github.com/fatih/color) | 终端着色 | 美化 CLI 输出 | | [progressbar](https://github.com/schollz/progressbar) | 进度条 | 长时操作反馈 | | [survey](https://github.com/AlecAivazis/survey) | 交互式提示 | 用户交互 | | [archiver](https://github.com/mholt/archiver) | 压缩归档 | 支持多种归档格式 | | [go-yaml](https://github.com/go-yaml/yaml) | YAML 解析 | Profile 文件解析 | | [uuid](https://github.com/google/uuid) | UUID 生成 | Pack ID 生成 | | [golang.org/x/crypto](https://golang.org/x/crypto) | 加密库 | Argon2, AES | ### 4.2 构建工具 | 工具 | 用途 | |------|------| | Go 1.22+ | 编程语言 | | Make / Task | 构建脚本 | | GoReleaser | 多平台发布 | | golangci-lint | 代码检查 | | GitHub Actions | CI/CD | --- ## 5. 错误处理策略 ### 5.1 错误分级 ```go // ErrorLevel 错误级别 type ErrorLevel int const ( ErrorFatal ErrorLevel = iota // 致命错误,必须终止 ErrorCritical // 严重错误,当前采集器失败 ErrorWarning // 警告,可继续但需告知用户 ErrorInfo // 信息,记录但不影响流程 ) // CollectorError 采集器错误 type CollectorError struct { Collector string Level ErrorLevel Message string Cause error Hint string // 给用户的建议 } ``` ### 5.2 错误处理原则 1. **采集阶段** — 单个采集器失败不影响其他采集器 2. **打包阶段** — 失败的采集器数据不包含在 Pack 中,但 Pack 仍然生成 3. **还原阶段** — 根据策略决定是继续还是终止 4. **所有操作** — 详细日志记录,用户友好的错误信息 --- ## 6. 安全设计 ### 6.1 敏感数据识别 | 数据类型 | 敏感级别 | 处理方式 | |---------|---------|---------| | SSH 私钥 | 高 | AES-256 加密 | | GPG 私钥 | 高 | AES-256 加密 | | API Token | 高 | AES-256 加密或排除 | | 环境变量中的密码 | 高 | 默认排除 | | Git 凭证 | 高 | 默认排除 | | IDE 设置 | 低 | 明文存储 | | Shell 配置 | 中 | 扫描并警告内嵌 Token | ### 6.2 加密流程 ``` 用户密码 ──▶ Argon2id ──▶ 派生密钥 (256-bit) │ ▼ 敏感数据 ──▶ AES-256-GCM 加密 ──▶ 加密数据 + Nonce + Salt │ ▼ 存入 encrypted/ 目录 ``` --- ## 7. 可扩展性设计 ### 7.1 插件系统(远期规划) 未来计划支持外部插件: ```go // Plugin 外部插件接口 type Plugin interface { Collector // PluginInfo 返回插件元信息 PluginInfo() PluginMeta } type PluginMeta struct { Name string `json:"name"` Version string `json:"version"` Author string `json:"author"` MinDevPack string `json:"min_devpack_version"` } ``` 插件发现机制: 1. `~/.devpack/plugins/` 目录下的可执行文件 2. 通过 Go Plugin 机制加载 `.so` / `.dll` 3. 通过 gRPC/JSON-RPC 与外部进程通信(推荐,跨语言) --- ## 8. 测试策略 ### 8.1 测试层级 | 层级 | 范围 | 工具 | |------|------|------| | 单元测试 | 各模块独立逻辑 | Go testing + testify | | 集成测试 | 模块间协作 | Go testing | | 端到端测试 | 完整的 capture → restore 流程 | 脚本 + Docker/VM | | 平台测试 | 各操作系统适配 | GitHub Actions Matrix | ### 8.2 测试环境 - CI 环境使用 GitHub Actions 矩阵构建(Windows/macOS/Linux) - 端到端测试使用虚拟机或容器模拟真实环境 - Mock 框架用于隔离外部依赖(如包管理器)