This commit is contained in:
zyj
2026-03-03 18:20:18 +08:00
commit a9f9330744
25 changed files with 5004 additions and 0 deletions

898
docs/API.md Normal file
View File

@@ -0,0 +1,898 @@
# DevPack API 设计文档
> 版本v1.0.0-draft
> 更新日期2026-03-03
> 作者DevPack Team
---
## 1. CLI 命令参考
### 1.1 命令总览
```
devpack [command] [subcommand] [flags]
Available Commands:
init 初始化 DevPack 配置
scan 扫描当前开发环境
capture 捕获环境并生成 Pack
restore 从 Pack 还原开发环境
diff 对比两个环境的差异
export 导出 Pack 为文件
import 导入 Pack 文件
list 列出 Pack 和 Profile
profile 管理配置文件
verify 验证 Pack 文件完整性
version 显示版本信息
help 帮助信息
Global Flags:
-v, --verbose 详细输出
-q, --quiet 静默模式
--log-level 日志级别 (trace|debug|info|warn|error)
--log-file 日志文件路径
--no-color 禁用彩色输出
--config 配置文件路径(默认 ~/.devpack/config.yaml
-h, --help 帮助信息
```
---
### 1.2 devpack init
初始化 DevPack创建配置目录和默认配置文件。
```
devpack init [flags]
Flags:
--profile <name> 创建并使用指定名称的 Profile
--template <tpl> 使用预设模板 (minimal|standard|full)
--force 覆盖已有配置
```
**示例:**
```bash
# 默认初始化
devpack init
# 使用模板初始化
devpack init --template standard
# 创建指定 Profile
devpack init --profile golang-dev
```
**行为:**
1. 创建 `~/.devpack/` 目录
2. 生成 `~/.devpack/config.yaml` 默认配置
3. 创建 `~/.devpack/profiles/` 目录
4. 创建 `~/.devpack/packs/` 目录
5. 创建 `~/.devpack/logs/` 目录
**输出示例:**
```
✓ Created ~/.devpack/config.yaml
✓ Created ~/.devpack/profiles/default.yaml
✓ DevPack initialized successfully!
Run 'devpack scan' to scan your current environment.
```
---
### 1.3 devpack scan
扫描当前系统的开发环境。
```
devpack scan [flags]
Flags:
-c, --collectors <list> 指定采集器(逗号分隔)
--category <cat> 按分类扫描 (runtime|package|editor|shell|git|env)
--profile <name> 使用指定 Profile 的扫描配置
-o, --output <format> 输出格式 (table|json|yaml) [默认: table]
--save <path> 保存扫描结果到文件
--detailed 显示详细信息
```
**示例:**
```bash
# 扫描所有
devpack scan
# 只扫描运行时
devpack scan --category runtime
# 扫描特定采集器
devpack scan -c go,node,vscode
# JSON 格式输出
devpack scan -o json
# 保存结果
devpack scan --save scan-result.json
```
**输出示例:**
```
🔍 Scanning development environment...
╔══════════════╤════════════════════╤═══════════╤═══════════════════╗
║ Category │ Name │ Version │ Details ║
╠══════════════╪════════════════════╪═══════════╪═══════════════════╣
║ Runtime │ Go │ 1.22.1 │ GOPATH: ~/go ║
║ Runtime │ Node.js │ 20.11.0 │ npm: 10.2.4 ║
║ Runtime │ Python │ 3.12.2 │ pip: 24.0 ║
║ Runtime │ Rust │ 1.76.0 │ rustup: 1.27.0 ║
╠══════════════╪════════════════════╪═══════════╪═══════════════════╣
║ Package Mgr │ Scoop │ - │ 42 packages ║
║ Package Mgr │ Winget │ - │ 15 packages ║
╠══════════════╪════════════════════╪═══════════╪═══════════════════╣
║ Editor │ VS Code │ 1.87.0 │ 35 extensions ║
║ Editor │ Neovim │ 0.9.5 │ 18 plugins ║
╠══════════════╪════════════════════╪═══════════╪═══════════════════╣
║ Shell │ PowerShell │ 7.4.1 │ 5 modules ║
║ Shell │ Windows Terminal │ 1.19 │ 3 profiles ║
╠══════════════╪════════════════════╪═══════════╪═══════════════════╣
║ Git │ Git │ 2.43.0 │ 12 aliases ║
╠══════════════╪════════════════════╪═══════════╪═══════════════════╣
║ Environment │ Environment Vars │ - │ 8 dev-related ║
╚══════════════╧════════════════════╧═══════════╧═══════════════════╝
Found 12 items across 6 categories.
Estimated pack size: ~12 MB
```
---
### 1.4 devpack capture
捕获当前环境并创建 Pack。
```
devpack capture [flags]
Flags:
-n, --name <name> Pack 名称(必需)
-d, --description <desc> Pack 描述
-p, --profile <name> 使用指定 Profile
-c, --collectors <list> 指定采集器(逗号分隔)
--filter <expr> 过滤表达式
--all 捕获所有可用采集器
--encrypt 加密敏感数据
--password <pwd> 加密密码(不建议命令行传入)
--exclude <patterns> 排除模式(逗号分隔)
--tag <tags> 标签(逗号分隔)
-y, --yes 跳过确认提示
```
**示例:**
```bash
# 使用默认 Profile 捕获
devpack capture --name "my-env-2026"
# 捕获所有内容
devpack capture --name "full-env" --all
# 使用指定 Profile
devpack capture --name "golang-env" --profile golang-dev
# 选择性捕获
devpack capture --name "vscode-only" -c vscode
# 加密捕获
devpack capture --name "secure-env" --all --encrypt
# 带过滤器
devpack capture --name "web-dev" \
-c go,node,vscode \
--filter "runtime:go,runtime:node,editor:vscode"
```
**输出示例:**
```
📦 Capturing environment "my-env-2026"...
Collecting:
✓ Go Runtime (1.22.1, 3 tools) [2.1 MB]
✓ Node.js Runtime (20.11.0, 12 global pkgs) [1.5 MB]
✓ VS Code (35 extensions, settings) [4.2 MB]
✓ PowerShell (profile, 5 modules) [0.3 MB]
✓ Scoop (42 packages) [0.1 MB]
✓ Git (config, 12 aliases) [0.01 MB]
✓ Environment Variables (8 variables) [0.001 MB]
⚠ SSH Keys skipped (use --encrypt)
Pack created: my-env-2026
Items: 7 collectors, 115 items
Size: 8.2 MB (compressed)
Pack ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890
Run 'devpack export my-env-2026 -o my-env-2026.devpack' to export.
```
---
### 1.5 devpack restore
从 Pack 还原开发环境。
```
devpack restore <pack-name> [flags]
Flags:
--dry-run 预览更改(不实际执行)
--conflict <strategy> 冲突处理策略 (skip|overwrite|merge|prompt|newest)
--no-rollback 不创建还原点
-c, --collectors <list> 只还原指定采集器
--exclude <list> 排除指定采集器
--password <pwd> 解密密码
--parallel <n> 并行还原数(默认: 4
-y, --yes 跳过确认提示
--force 强制还原(忽略平台不匹配)
```
**示例:**
```bash
# 干运行预览
devpack restore my-env-2026 --dry-run
# 正常还原
devpack restore my-env-2026
# 跳过冲突
devpack restore my-env-2026 --conflict skip
# 只还原编辑器配置
devpack restore my-env-2026 -c vscode
# 还原加密 Pack
devpack restore secure-env --password
```
**干运行输出示例:**
```
🔍 Dry Run — Restore Plan for "my-env-2026"
Source: DESKTOP-ABC123 (Windows 11, amd64)
Target: LAPTOP-XYZ789 (Windows 11, amd64) ✓ Compatible
Plan:
┌────────────────────┬────────────┬──────────────────────────────┐
│ Item │ Action │ Details │
├────────────────────┼────────────┼──────────────────────────────┤
│ Go 1.22.1 │ INSTALL │ Download from golang.org │
│ Node.js 20.11.0 │ SKIP │ Already installed (20.11.0) │
│ Python 3.12.2 │ UPGRADE │ Current: 3.11.7 → 3.12.2 │
│ VS Code Extensions │ INSTALL 12 │ 23 already present │
│ VS Code Settings │ MERGE │ Conflict in 3 settings │
│ PowerShell Profile │ OVERWRITE │ Backup: profile.bak │
│ Scoop Packages │ INSTALL 8 │ 34 already present │
│ Git Config │ MERGE │ Add 5 aliases │
│ Env Variables │ SET 3 │ GOPATH, GOROOT, NODE_HOME │
└────────────────────┴────────────┴──────────────────────────────┘
Install: 3 items | Upgrade: 1 | Merge: 2 | Skip: 1 | Overwrite: 1
⚠ This is a dry run. No changes were made.
Run without --dry-run to apply these changes.
```
---
### 1.6 devpack diff
对比两个环境的差异。
```
devpack diff <pack-name> [flags]
Flags:
--current 与当前环境对比
--with <pack-name> 与另一个 Pack 对比
-c, --collectors <list> 只对比指定采集器
-o, --output <format> 输出格式 (table|json|yaml)
```
**示例:**
```bash
# 与当前环境对比
devpack diff my-env-2026 --current
# 两个 Pack 对比
devpack diff env-v1 --with env-v2
```
---
### 1.7 devpack export / import
导出和导入 Pack 文件。
```
# 导出
devpack export <pack-name> [flags]
Flags:
-o, --output <path> 输出文件路径(默认: <pack-name>.devpack
# 导入
devpack import <file-path> [flags]
Flags:
-n, --name <name> 导入后的名称(默认使用 Pack 原名)
--verify 导入前验证文件完整性
```
---
### 1.8 devpack list
列出本地的 Pack 和 Profile。
```
devpack list [subcommand] [flags]
Subcommands:
packs 列出所有 Pack
profiles 列出所有 Profile
collectors 列出所有可用采集器
Flags:
-o, --output <format> 输出格式 (table|json|yaml)
--detailed 显示详细信息
```
---
### 1.9 devpack profile
管理 Profile 配置文件。
```
devpack profile [subcommand] [flags]
Subcommands:
create <name> 创建新 Profile
edit <name> 编辑 Profile
delete <name> 删除 Profile
show <name> 显示 Profile 内容
list 列出所有 Profile
use <name> 设置默认 Profile
```
---
### 1.10 devpack verify
验证 Pack 文件的完整性。
```
devpack verify <pack-name-or-file> [flags]
Flags:
--checksum 验证校验和
--structure 验证目录结构
--deep 深度验证(检查所有采集器数据)
```
---
## 2. 内部 API
### 2.1 Collector 接口
```go
package collector
import (
"context"
"time"
)
// Collector 所有采集器的统一接口
type Collector interface {
// 基本信息
Name() string
DisplayName() string
Description() string
Category() Category
// 可用性检查
IsAvailable(ctx context.Context) bool
// 核心操作
Scan(ctx context.Context, opts ScanOptions) (*ScanResult, error)
Capture(ctx context.Context, targetDir string, opts CaptureOptions) error
Restore(ctx context.Context, sourceDir string, opts RestoreOptions) error
Verify(ctx context.Context) (*VerifyResult, error)
}
// ScanOptions 扫描选项
type ScanOptions struct {
Detailed bool // 是否返回详细信息
Filters map[string]string // 过滤条件
Timeout time.Duration // 超时时间
}
// CaptureOptions 捕获选项
type CaptureOptions struct {
IncludePatterns []string // 包含模式
ExcludePatterns []string // 排除模式
Encrypt bool // 是否加密
}
// RestoreOptions 还原选项
type RestoreOptions struct {
ConflictStrategy ConflictStrategy // 冲突策略
DryRun bool // 干运行
Force bool // 强制
}
// 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"`
Errors []string `json:"errors,omitempty"`
}
// ScanItem 扫描项
type ScanItem struct {
Name string `json:"name"`
Version string `json:"version,omitempty"`
Path string `json:"path,omitempty"`
Type string `json:"type,omitempty"` // binary, config, package
Properties map[string]string `json:"properties,omitempty"`
Size int64 `json:"size,omitempty"`
Sensitive bool `json:"sensitive,omitempty"` // 是否包含敏感数据
Children []ScanItem `json:"children,omitempty"`
}
// VerifyResult 验证结果
type VerifyResult struct {
Success bool `json:"success"`
Items []VerifyItem `json:"items"`
}
type VerifyItem struct {
Name string `json:"name"`
Status string `json:"status"` // ok, missing, version_mismatch, error
Message string `json:"message,omitempty"`
}
```
### 2.2 Pack Engine API
```go
package pack
import (
"context"
"io"
"github.com/user/devpack/pkg/manifest"
)
// Packer 打包器
type Packer struct {
// ...
}
// NewPacker 创建打包器
func NewPacker(opts PackerOptions) *Packer
// PackerOptions 打包器选项
type PackerOptions struct {
Name string
Description string
Author string
Compression CompressionType // gzip, zstd, none
Encryption bool
Password string
}
// Pack 执行打包
func (p *Packer) Pack(ctx context.Context, sourceDir string, output io.Writer) (*manifest.Manifest, error)
// Unpacker 解包器
type Unpacker struct {
// ...
}
// NewUnpacker 创建解包器
func NewUnpacker() *Unpacker
// Unpack 执行解包
func (u *Unpacker) Unpack(ctx context.Context, input io.Reader, targetDir string) (*manifest.Manifest, error)
// Verify 验证 Pack 文件
func (u *Unpacker) Verify(ctx context.Context, input io.Reader) (*VerifyResult, error)
```
### 2.3 Restore Engine API
```go
package restore
import (
"context"
"github.com/user/devpack/internal/collector"
"github.com/user/devpack/pkg/manifest"
)
// Engine 还原引擎
type Engine struct {
registry *collector.Registry
platform platform.Platform
// ...
}
// NewEngine 创建还原引擎
func NewEngine(registry *collector.Registry, platform platform.Platform) *Engine
// Plan 生成还原计划
func (e *Engine) Plan(ctx context.Context, m *manifest.Manifest, opts PlanOptions) (*RestorePlan, error)
// Execute 执行还原计划
func (e *Engine) Execute(ctx context.Context, plan *RestorePlan) (*RestoreReport, error)
// Rollback 回滚还原
func (e *Engine) Rollback(ctx context.Context, restorePointID string) error
// RestorePlan 还原计划
type RestorePlan struct {
PackName string `json:"pack_name"`
Items []RestorePlanItem `json:"items"`
Conflicts []ConflictItem `json:"conflicts"`
TotalSteps int `json:"total_steps"`
}
// RestorePlanItem 还原计划项
type RestorePlanItem struct {
Collector string `json:"collector"`
ItemName string `json:"item_name"`
Action RestoreAction `json:"action"` // install, upgrade, merge, skip, overwrite
Current string `json:"current,omitempty"`
Target string `json:"target"`
Details string `json:"details,omitempty"`
Order int `json:"order"` // 执行顺序
}
// RestoreAction 还原动作
type RestoreAction string
const (
ActionInstall RestoreAction = "install"
ActionUpgrade RestoreAction = "upgrade"
ActionMerge RestoreAction = "merge"
ActionSkip RestoreAction = "skip"
ActionOverwrite RestoreAction = "overwrite"
)
// RestoreReport 还原报告
type RestoreReport struct {
Success int `json:"success"`
Failed int `json:"failed"`
Skipped int `json:"skipped"`
Items []ReportItem `json:"items"`
Duration time.Duration `json:"duration"`
RestorePointID string `json:"restore_point_id,omitempty"`
}
```
---
## 3. Pack 文件格式规范
### 3.1 文件结构
```
<name>.devpack # tar.gz 归档
├── manifest.json # Pack 清单(必需)
├── checksum.sha256 # 校验和文件(必需)
├── collectors/ # 采集器数据目录
│ ├── <category>/ # 分类目录
│ │ └── <collector-name>/ # 采集器目录
│ │ ├── metadata.json # 采集器元数据
│ │ └── data/ # 采集器数据
│ │ └── ... # 具体数据文件
│ └── ...
└── encrypted/ # 加密数据目录(可选)
└── <collector-name>/
└── data.enc # 加密数据
```
### 3.2 manifest.json 完整规范
```json
{
"version": "0.1.0",
"format_ver": "1",
"pack_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "my-dev-env",
"description": "My full development environment",
"author": "developer@example.com",
"created_at": "2026-03-03T10:30:00Z",
"tags": ["golang", "fullstack"],
"source": {
"hostname": "DESKTOP-ABC123",
"os": "windows",
"os_version": "10.0.22631",
"arch": "amd64",
"username": "developer",
"devpack_version": "0.1.0"
},
"collectors": [
{
"name": "go",
"category": "runtime",
"display_name": "Go Runtime",
"item_count": 4,
"data_path": "collectors/runtime/go",
"data_size": 2148576,
"checksum": "sha256:abc123..."
},
{
"name": "vscode",
"category": "editor",
"display_name": "Visual Studio Code",
"item_count": 36,
"data_path": "collectors/editor/vscode",
"data_size": 4412928,
"checksum": "sha256:def456..."
}
],
"encryption": {
"algorithm": "AES-256-GCM",
"kdf": "argon2id",
"kdf_params": {
"time": 1,
"memory": 65536,
"threads": 4
},
"encrypted_collectors": ["ssh"]
},
"checksum": "sha256:789abc..."
}
```
### 3.3 metadata.json 规范
每个采集器目录下的元数据文件:
```json
{
"collector": "go",
"category": "runtime",
"captured_at": "2026-03-03T10:30:00Z",
"platform": {
"os": "windows",
"arch": "amd64"
},
"items": [
{
"name": "go",
"version": "1.22.1",
"type": "binary",
"install_method": "direct",
"install_url": "https://go.dev/dl/go1.22.1.windows-amd64.msi",
"properties": {
"GOPATH": "C:\\Users\\dev\\go",
"GOROOT": "C:\\Program Files\\Go",
"GOPROXY": "https://goproxy.cn,direct"
}
},
{
"name": "gopls",
"version": "0.15.1",
"type": "tool",
"install_method": "go_install",
"install_command": "go install golang.org/x/tools/gopls@v0.15.1"
},
{
"name": "golangci-lint",
"version": "1.56.2",
"type": "tool",
"install_method": "go_install",
"install_command": "go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.2"
}
],
"files": [
{
"source": "data/go-env.json",
"description": "Go environment variables"
}
]
}
```
---
## 4. 配置文件规范
### 4.1 全局配置 (~/.devpack/config.yaml)
```yaml
# DevPack 全局配置
version: "1"
# 存储设置
storage:
packs_dir: "~/.devpack/packs" # Pack 存储目录
profiles_dir: "~/.devpack/profiles" # Profile 目录
logs_dir: "~/.devpack/logs" # 日志目录
temp_dir: "" # 临时目录(空则使用系统默认)
# 默认行为
defaults:
profile: "default" # 默认 Profile
compression: "gzip" # 压缩方式 (gzip|zstd|none)
conflict_strategy: "prompt" # 冲突策略
create_restore_point: true # 还原前创建还原点
parallel_restore: 4 # 并行还原数
# 日志设置
logging:
level: "info" # 日志级别
format: "text" # 日志格式 (text|json)
file: "~/.devpack/logs/devpack.log" # 日志文件
# 网络设置(用于下载安装器)
network:
timeout: 300 # 下载超时(秒)
proxy: "" # HTTP 代理
retries: 3 # 重试次数
# UI 设置
ui:
color: true # 彩色输出
progress_bar: true # 进度条
interactive: true # 交互式提示
# 安全设置
security:
default_encrypt: false # 默认是否加密
scan_for_secrets: true # 扫描敏感数据并警告
exclude_patterns: # 全局排除模式
- "*_KEY"
- "*_SECRET"
- "*_TOKEN"
- "*_PASSWORD"
```
### 4.2 Profile 配置文件规范
```yaml
# Profile 配置文件
name: "default"
description: "Default development environment profile"
version: "1"
collectors:
# 运行时采集器配置
runtime:
enabled: true
include: [] # 空列表 = 全部,非空 = 只包含列出的
exclude: [] # 排除列表
options: {} # 采集器特定选项
# 包管理器采集器配置
package:
enabled: true
include: []
exclude: []
options:
scoop:
include_buckets: true
exclude_packages: []
chocolatey:
exclude_packages: []
# 编辑器采集器配置
editor:
enabled: true
include: ["vscode"]
options:
vscode:
capture_extensions: true
capture_settings: true
capture_keybindings: true
capture_snippets: true
exclude_extensions: []
# Shell 采集器配置
shell:
enabled: true
include: []
options: {}
# Git 采集器配置
git:
enabled: true
options:
capture_config: true
capture_aliases: true
capture_hooks: false
# 环境变量采集器配置
env:
enabled: true
options:
include_patterns: []
exclude_patterns:
- "*_KEY"
- "*_SECRET"
# SSH/GPG 采集器配置
ssh:
enabled: false # 默认禁用
options:
encrypt: true # 必须加密
# 字体采集器配置
font:
enabled: false
options:
include_fonts: [] # 空 = 自动检测开发字体
# 还原选项
restore:
conflict_strategy: "prompt"
create_restore_point: true
dry_run_first: false
# 自定义钩子(高级)
hooks:
pre_capture: "" # 捕获前执行的命令
post_capture: "" # 捕获后执行的命令
pre_restore: "" # 还原前执行的命令
post_restore: "" # 还原后执行的命令
```
---
## 5. 退出码
| 退出码 | 含义 |
|--------|------|
| 0 | 成功 |
| 1 | 一般性错误 |
| 2 | 命令行参数错误 |
| 3 | 配置错误 |
| 10 | Pack 文件损坏或无效 |
| 11 | 平台不兼容 |
| 12 | 版本不兼容 |
| 20 | 还原失败 |
| 21 | 还原部分成功 |
| 22 | 冲突(需要用户介入) |
| 30 | 权限不足 |
| 40 | 网络错误 |
| 50 | 加密/解密错误 |
---
## 6. 环境变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `DEVPACK_HOME` | DevPack 主目录 | `~/.devpack` |
| `DEVPACK_LOG_LEVEL` | 日志级别 | `info` |
| `DEVPACK_LOG_FILE` | 日志文件路径 | `~/.devpack/logs/devpack.log` |
| `DEVPACK_CONFIG` | 配置文件路径 | `~/.devpack/config.yaml` |
| `DEVPACK_NO_COLOR` | 禁用彩色输出 | `false` |
| `DEVPACK_PROFILE` | 默认 Profile | `default` |
| `DEVPACK_HTTP_PROXY` | HTTP 代理 | - |

751
docs/ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,751 @@
# 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 框架用于隔离外部依赖(如包管理器)

196
docs/CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,196 @@
# DevPack 贡献指南
> 感谢你对 DevPack 的兴趣!我们欢迎各种形式的贡献。
---
## 如何贡献
### 🐛 报告 Bug
1. 搜索 [已有的 Issues](https://github.com/user/devpack/issues),确认没有重复
2. 创建新 Issue包含以下信息
- DevPack 版本(`devpack version`
- 操作系统和版本
- 复现步骤
- 期望行为 vs 实际行为
- 日志信息(`--log-level debug`
### 💡 功能建议
1. 搜索已有 Issues确认没有类似建议
2. 创建 Feature Request Issue
3. 描述使用场景和期望行为
4. 解释为什么这个功能对用户有价值
### 🔧 提交代码
#### 环境准备
```bash
# 1. Fork 项目
# 2. Clone 你的 Fork
git clone https://github.com/YOUR_USERNAME/devpack.git
cd devpack
# 3. 添加上游仓库
git remote add upstream https://github.com/user/devpack.git
# 4. 安装依赖
go mod download
# 5. 安装开发工具
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
# 6. 验证环境
make test
make lint
```
#### 开发流程
```bash
# 1. 同步上游
git fetch upstream
git checkout develop
git merge upstream/develop
# 2. 创建分支
git checkout -b feature/your-feature
# 3. 编码
# ... 编写代码和测试
# 4. 运行检查
make fmt # 格式化代码
make lint # 代码检查
make test # 运行测试
# 5. 提交
git add .
git commit -m "feat(scope): description"
# 6. 推送
git push origin feature/your-feature
# 7. 创建 Pull Request
```
#### Pull Request 规范
- **标题:** 遵循 Conventional Commits 格式
- **描述:** 说明改了什么、为什么改、怎么测试的
- **关联 Issue** 如果有对应的 Issue请关联
- **测试:** 确保新代码有对应的测试
- **文档:** 如果改变了用户可见行为,更新对应文档
#### PR 模板
```markdown
## 描述
简述这个 PR 做了什么。
## 改动类型
- [ ] Bug fix
- [ ] New feature
- [ ] Refactoring
- [ ] Documentation
- [ ] Test
## 关联 Issue
Fixes #123
## 测试
描述如何测试这个改动。
## 检查清单
- [ ] 代码通过 `make lint`
- [ ] 添加了对应的单元测试
- [ ] 所有测试通过 `make test`
- [ ] 更新了相关文档
```
---
## 编码规范
### Go 代码规范
- 遵循 [Effective Go](https://golang.org/doc/effective_go)
- 使用 `gofmt` 格式化代码
- 通过 `golangci-lint` 检查
- 公开 API 必须有文档注释
- 错误必须包含上下文信息
### 提交规范
使用 [Conventional Commits](https://www.conventionalcommits.org/)
```
feat(collector): add Docker runtime collector
fix(restore): handle version conflict correctly
docs(readme): update installation instructions
test(pack): add pack/unpack round-trip test
refactor(platform): simplify Windows adapter
chore(ci): add macOS build matrix
```
### 测试规范
- 所有新功能必须有单元测试
- 测试文件与源码在同一包下
- 使用 `testify` 断言库
- 平台特定逻辑需要条件跳过:
```go
func TestWindowsSpecific(t *testing.T) {
if runtime.GOOS != "windows" {
t.Skip("Windows-only test")
}
// ...
}
```
---
## 添加新采集器
如果你想为 DevPack 添加一个新的采集器,请参考以下步骤:
1.`internal/collector/` 下创建新的包
2. 实现 `Collector` 接口的所有方法
3.`registry.go` 中注册
4. 编写单元测试
5. 更新文档PRD.md 和 USER-GUIDE.md
详细指南请参考 [开发指南 - 添加新采集器](DEVELOPMENT.md#5-添加新采集器指南)。
---
## 社区准则
- 友善和尊重
- 建设性的讨论
- 接受不同意见
- 关注事实和技术
---
## 获取帮助
- 📖 [用户手册](USER-GUIDE.md)
- 🏗️ [架构设计](ARCHITECTURE.md)
- 💻 [开发指南](DEVELOPMENT.md)
- ❓ [GitHub Discussions](https://github.com/user/devpack/discussions)
---
## 许可证
贡献的代码将按照项目的 [MIT License](../LICENSE) 发布。

638
docs/DEVELOPMENT.md Normal file
View File

@@ -0,0 +1,638 @@
# DevPack 开发指南
> 版本v1.0.0-draft
> 更新日期2026-03-03
> 作者DevPack Team
---
## 1. 开发环境搭建
### 1.1 前置要求
| 工具 | 最低版本 | 安装方式 |
|------|---------|---------|
| Go | 1.22+ | [golang.org](https://golang.org/dl/) |
| Git | 2.30+ | [git-scm.com](https://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 获取代码
```bash
git clone https://github.com/user/devpack.git
cd devpack
```
### 1.3 安装依赖
```bash
go mod download
```
### 1.4 验证环境
```bash
# 运行测试
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 Go](https://golang.org/doc/effective_go) 和 [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)。
#### 命名规范
```go
// ✅ 包名:小写单词,不用下划线
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")
```
#### 错误处理
```go
// ✅ 使用 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 使用
```go
// ✅ 第一个参数传递 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](https://www.conventionalcommits.org/)
```
<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 命令
```makefile
# 构建
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: 创建采集器文件
```go
// 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: 注册采集器
```go
// 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: 编写测试
```go
// 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 日志级别
```bash
# 设置日志级别
DEVPACK_LOG_LEVEL=debug devpack scan
# 或通过命令行参数
devpack scan --log-level debug
```
| 级别 | 用途 |
|------|------|
| `trace` | 非常详细的调试信息 |
| `debug` | 调试信息 |
| `info` | 正常操作信息(默认) |
| `warn` | 警告 |
| `error` | 错误 |
| `fatal` | 致命错误 |
### 6.2 VS Code 调试配置
```json
// .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](https://semver.org/lang/zh-CN/)
```
MAJOR.MINOR.PATCH[-PRERELEASE]
- MAJOR: 不兼容的 API 变更
- MINOR: 向下兼容的功能新增
- PATCH: 向下兼容的 Bug 修复
```
### 7.2 发布步骤
```bash
# 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 配置
```yaml
# .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:'
```

288
docs/PRD.md Normal file
View File

@@ -0,0 +1,288 @@
# DevPack 产品需求文档 (PRD)
> 版本v1.0.0-draft
> 更新日期2026-03-03
> 作者DevPack Team
---
## 1. 产品概述
### 1.1 产品定位
DevPack 是一款面向开发者的**开发环境打包迁移工具**。它能够将一台电脑上的完整开发环境运行时、工具链、IDE 配置、Shell 设置等)扫描、捕获并打包成一个可移植的文件,在另一台同操作系统的电脑上快速还原,大幅减少环境搭建时间。
### 1.2 产品愿景
> **让开发环境像 U 盘一样即插即用。**
### 1.3 目标用户
| 用户画像 | 描述 | 核心诉求 |
|---------|------|---------|
| 🧑‍💻 个人开发者 | 拥有多台电脑或定期更换设备 | 快速在新设备上恢复工作环境 |
| 👥 团队 Leader | 负责团队开发规范和环境标准化 | 统一团队成员开发环境 |
| 🏢 企业 IT 管理员 | 需要批量部署开发工位 | 标准化开发环境快速部署 |
| 🎓 培训讲师 | 需要为学员提供一致的学习环境 | 一键分发教学开发环境 |
| 🔄 DevOps 工程师 | 管理多个项目的不同环境需求 | 快速切换不同项目环境配置 |
### 1.4 核心价值主张
1. **节省时间** — 将环境搭建从数小时/天缩短至分钟级别
2. **避免遗漏** — 自动扫描确保不遗漏任何配置
3. **可复现** — 确保环境的精确复现
4. **安全可靠** — 敏感数据加密,还原可回滚
---
## 2. 用户场景 (User Stories)
### 2.1 核心场景
#### US-001: 换电脑迁移开发环境
> **作为** 一名全栈开发者
> **我希望** 在换新电脑时能一键迁移我的所有开发环境
> **以便** 我可以在新电脑上立即开始工作,而不用花一整天重新配置
**验收标准:**
- [ ] 能在旧电脑上扫描并打包完整开发环境
- [ ] 生成的 `.devpack` 文件可通过 U 盘或网络传输
- [ ] 在新电脑上能一键还原所有工具和配置
- [ ] 还原后的环境与原始环境功能一致
#### US-002: 团队环境标准化
> **作为** 一名技术团队 Leader
> **我希望** 能导出一个标准开发环境包分发给团队成员
> **以便** 所有人使用一致的开发工具和配置
**验收标准:**
- [ ] 能创建一个"标准环境"配置文件
- [ ] 团队成员可导入并一键应用标准环境
- [ ] 可指定哪些配置是强制的,哪些是可选的
- [ ] 支持环境包版本更新推送
#### US-003: 选择性环境打包
> **作为** 一名开发者
> **我希望** 只打包特定的工具链(如只打包 Go + VS Code
> **以便** 我可以为不同项目准备精简的环境包
**验收标准:**
- [ ] 扫描时能分类展示各类工具/配置
- [ ] 用户可选择只打包特定分类
- [ ] 支持通过过滤器精确指定打包内容
- [ ] 支持保存过滤器为命名配置
#### US-004: 环境差异对比
> **作为** 一名开发者
> **我希望** 对比两台电脑的开发环境差异
> **以便** 我能定位"为什么在你电脑上能跑在我这里不行"的问题
**验收标准:**
- [ ] 能导入另一台电脑的环境快照
- [ ] 以清晰的格式展示两个环境的差异
- [ ] 差异按分类(运行时版本、配置差异、缺失工具等)组织
- [ ] 可选择性地将差异应用到当前环境
#### US-005: 环境备份与恢复
> **作为** 一名开发者
> **我希望** 定期备份我的开发环境配置
> **以便** 系统崩溃或重装后能快速恢复
**验收标准:**
- [ ] 支持增量备份(只记录变化部分)
- [ ] 支持查看历史版本
- [ ] 能从指定版本恢复
- [ ] 备份文件占用空间合理
### 2.2 扩展场景
#### US-006: 干运行模式
> **作为** 一名谨慎的开发者
> **我希望** 在还原前能预览将要做的所有更改
> **以便** 确认不会破坏我现有的环境
#### US-007: 还原回滚
> **作为** 一名开发者
> **我希望** 还原失败或不满意时能撤销所有更改
> **以便** 我的电脑不会因为错误的还原变得更糟
#### US-008: 敏感数据保护
> **作为** 一名注重安全的开发者
> **我希望** SSH 密钥和 Token 等敏感数据在打包时被加密
> **以便** 即使 .devpack 文件泄露也不会暴露我的密钥
---
## 3. 功能需求
### 3.1 功能矩阵
| 功能模块 | 功能项 | 优先级 | MVP | 说明 |
|---------|--------|--------|-----|------|
| **环境扫描** | 运行时检测 | P0 | ✅ | Go, Node, Python, Java, Rust, .NET |
| | 包管理器检测 | P0 | ✅ | Scoop, Choco, Winget, Brew, APT |
| | 编辑器/IDE 配置 | P0 | ✅ | VS Code (扩展+设置), JetBrains |
| | Shell 配置 | P0 | ✅ | PowerShell Profile, .bashrc, .zshrc |
| | 环境变量 | P0 | ✅ | 用户级环境变量 |
| | Git 配置 | P1 | ✅ | .gitconfig, aliases |
| | SSH/GPG 密钥 | P1 | ❌ | 加密处理 |
| | 字体 | P2 | ❌ | 开发用等宽字体 |
| | 自定义脚本 | P2 | ❌ | 用户指定的脚本/工具 |
| **打包引擎** | Pack 文件生成 | P0 | ✅ | .devpack 格式 |
| | 选择性打包 | P0 | ✅ | 按采集器/过滤器 |
| | 增量打包 | P1 | ❌ | 基于上一次快照的差异包 |
| | 数据加密 | P1 | ❌ | AES-256-GCM 加密敏感数据 |
| | 压缩优化 | P1 | ✅ | 多种压缩算法可选 |
| **还原引擎** | 自动安装 | P0 | ✅ | 按依赖顺序安装 |
| | 配置还原 | P0 | ✅ | 还原配置文件 |
| | 冲突处理 | P0 | ✅ | 检测并处理版本冲突 |
| | 干运行模式 | P0 | ✅ | 预览更改不实际执行 |
| | 回滚机制 | P1 | ❌ | 还原前创建还原点 |
| **环境管理** | Profile 管理 | P0 | ✅ | 创建/编辑/删除配置 |
| | 环境对比 | P1 | ❌ | diff 两个环境 |
| | 版本历史 | P2 | ❌ | 环境快照版本管理 |
| **插件系统** | 内置采集器 | P0 | ✅ | 核心采集器 |
| | 自定义插件 | P2 | ❌ | 外部插件加载 |
| **注册中心** | 本地存储 | P0 | ✅ | 本地 Pack 管理 |
| | 远程注册中心 | P2 | ❌ | 类似 Docker Hub |
### 3.2 采集器详细需求
#### 3.2.1 运行时采集器 (Runtime Collector)
**扫描内容:**
| 语言/工具 | 检测项 | 还原方式 |
|-----------|--------|---------|
| Go | 版本、GOPATH、GOROOT、go env 全部配置 | 下载安装对应版本 |
| Node.js | 版本、npm/yarn/pnpm 全局包 | 通过 nvm/fnm 或直接安装 |
| Python | 版本、pip 全局包、virtualenv/conda | 安装器或 pyenv |
| Java | 版本、JAVA_HOME、Maven/Gradle 配置 | 通过 SDKMAN 或直接安装 |
| Rust | 版本、rustup 工具链、cargo 全局安装 | 通过 rustup |
| .NET | 版本、SDK 版本列表 | 通过官方安装器 |
| Ruby | 版本、gem 全局包 | 通过 rbenv/rvm |
| PHP | 版本、Composer 全局包 | 通过安装器 |
#### 3.2.2 包管理器采集器 (Package Collector)
| 平台 | 包管理器 | 采集内容 |
|------|---------|---------|
| Windows | Scoop | bucket 列表、已安装包列表 |
| Windows | Chocolatey | 已安装包列表及版本 |
| Windows | Winget | 已安装包列表 |
| macOS | Homebrew | tap 列表、formulae、casks |
| Linux (Debian) | APT | 手动安装的包列表 |
| Linux (RHEL) | DNF/YUM | 手动安装的包列表 |
| Linux (Arch) | Pacman/Yay | 显式安装的包列表 |
#### 3.2.3 编辑器采集器 (Editor Collector)
| 编辑器 | 采集内容 |
|--------|---------|
| VS Code | 扩展列表、settings.json、keybindings.json、代码片段 |
| VS Code Insiders | 同上 |
| JetBrains IDEs | 设置仓库导出、插件列表 |
| Vim/Neovim | .vimrc / init.vim / init.lua、插件列表 |
| Sublime Text | 包列表、配置文件 |
| Emacs | .emacs / init.el 配置 |
#### 3.2.4 Shell 采集器 (Shell Collector)
| Shell | 采集内容 |
|-------|---------|
| PowerShell | Profile 脚本、已安装模块 |
| Bash | .bashrc, .bash_profile, .bash_aliases |
| Zsh | .zshrc, oh-my-zsh 配置/主题/插件 |
| Fish | config.fish, 自定义函数 |
| Windows Terminal | settings.json |
| iTerm2 (macOS) | 配置文件 |
---
## 4. 非功能需求
### 4.1 性能要求
| 指标 | 要求 | 说明 |
|------|------|------|
| 扫描速度 | < 30 秒 | 完整环境扫描 |
| 打包速度 | < 2 分钟 | 典型开发环境(不含大文件) |
| 还原速度 | 取决于网络 | 下载安装器受网速限制 |
| Pack 文件大小 | < 50 MB | 典型环境(不含二进制文件) |
| 内存占用 | < 200 MB | 运行时峰值 |
### 4.2 安全要求
- 敏感数据SSH 密钥、Token、密码必须使用 AES-256-GCM 加密
- 加密密钥由用户密码通过 Argon2id 派生
- Pack 文件支持完整性校验SHA-256
- 还原前必须校验 Pack 文件签名
- 不采集浏览器密码、系统密码等隐私数据
### 4.3 兼容性要求
- 同操作系统类型之间迁移Windows → Windows, macOS → macOS, Linux → Linux
- 不支持跨操作系统迁移(设计决策:不同 OS 的工具链差异太大)
- 支持同一 OS 不同版本之间迁移(尽力兼容,不保证 100%
- Pack 文件格式向后兼容(新版本能读取旧版本生成的 Pack
### 4.4 可靠性要求
- 还原过程中断后可恢复(断点续装)
- 还原失败自动回滚
- 详细的操作日志记录
- 错误信息清晰可操作
---
## 5. 约束与假设
### 5.1 技术约束
- 使用 Go 语言开发,编译为单一静态二进制文件
- 不依赖运行时环境(不需要预装 Go、Python 等)
- 跨平台编译支持 Windows/macOS/Linux
- CLI 优先,暂不开发 GUI
### 5.2 假设
- 用户具备基本的命令行使用能力
- 目标电脑有网络连接(用于下载安装器)
- 用户有对应平台的管理员/sudo 权限
- 源电脑和目标电脑使用相同的操作系统类型
---
## 6. 成功指标
| 指标 | 目标 | 衡量方式 |
|------|------|---------|
| 环境恢复时间 | 缩短 80%+ | 对比手动配置时间 |
| 环境完整度 | > 95% 配置项正确恢复 | 还原后验证 |
| 用户满意度 | > 4.0/5.0 | 用户调查 |
| GitHub Stars | 1000+ (首年) | GitHub |
| 活跃用户 | 500+ MAU (首年) | 遥测数据 |
---
## 7. 风险评估
| 风险 | 可能性 | 影响 | 缓解措施 |
|------|--------|------|---------|
| 不同版本 OS 兼容性问题 | 高 | 中 | 充分测试,兼容性矩阵 |
| 安全敏感数据泄露 | 低 | 高 | 强加密,安全审计 |
| 包管理器 API 变更 | 中 | 中 | 插件化设计,快速适配 |
| 还原过程破坏现有环境 | 中 | 高 | 回滚机制,干运行模式 |
| Pack 文件过大 | 中 | 低 | 选择性打包,增量打包 |
---
## 附录 A: 术语表
| 术语 | 定义 |
|------|------|
| Pack | DevPack 生成的打包文件(.devpack 格式) |
| Profile | 命名的环境配置方案,定义打包范围和规则 |
| Collector | 采集器,负责扫描和收集特定类别的环境信息 |
| Manifest | Pack 内的清单文件,描述 Pack 的完整内容和元数据 |
| Restore Point | 还原点,还原前创建的当前环境快照,用于回滚 |
| Dry Run | 干运行,模拟执行并展示将要做的更改,不实际操作 |

232
docs/ROADMAP.md Normal file
View File

@@ -0,0 +1,232 @@
# DevPack 开发路线图
> 更新日期2026-03-03
> 作者DevPack Team
---
## 版本规划概览
```
v0.1.0 (MVP) v0.2.0 v0.3.0 v1.0.0
──────────────── → ──────────────── → ──────────────── → ────────────────
核心框架 + 基础 扩展采集器 + 加密 + 增量 + 稳定发布 +
采集器 + 打包还原 环境对比 + 回滚 远程注册中心 性能优化
2026 Q2 2026 Q3 2026 Q4 2027 Q1
```
---
## v0.1.0 — MVP (最小可行产品)
> **目标:** 核心打包还原流程跑通,支持最常用的开发工具
> **预计时间:** 2026 Q2约 3 个月)
### 里程碑
#### M1: 项目基础架构2 周)
- [ ] 项目脚手架搭建Go Module、目录结构、Makefile
- [ ] CLI 框架搭建Cobra + Viper
- [ ] 日志系统搭建zerolog
- [ ] 平台检测与适配层基础实现
- [ ] Collector 接口定义与注册中心实现
- [ ] 基础配置系统config.yaml
- [ ] `devpack version` 命令
#### M2: 核心采集器3 周)
- [ ] Go 运行时采集器
- [ ] Node.js 运行时采集器
- [ ] Python 运行时采集器
- [ ] VS Code 编辑器采集器(扩展 + 设置)
- [ ] PowerShell Shell 采集器
- [ ] Scoop 包管理器采集器Windows
- [ ] Git 配置采集器
- [ ] 环境变量采集器
- [ ] `devpack scan` 命令
#### M3: 打包引擎2 周)
- [ ] Pack 文件格式实现
- [ ] Manifest 生成与解析
- [ ] tar.gz 打包/解包
- [ ] 校验和计算与验证
- [ ] `devpack capture` 命令
- [ ] `devpack export` / `devpack import` 命令
#### M4: 还原引擎3 周)
- [ ] 还原计划生成器
- [ ] 基础冲突检测(版本对比)
- [ ] 各采集器的还原逻辑实现
- [ ] 干运行模式
- [ ] 还原报告生成
- [ ] `devpack restore` 命令
#### M5: 配置与打磨2 周)
- [ ] Profile 系统实现
- [ ] `devpack init` 命令
- [ ] `devpack list` 命令
- [ ] `devpack profile` 命令
- [ ] 终端 UI 优化(进度条、表格、颜色)
- [ ] 错误信息优化
- [ ] 单元测试覆盖率 > 60%
- [ ] README 和基础文档完善
- [ ] GitHub Actions CI 配置
- [ ] 首次内测发布
### MVP 交付标准
- ✅ 能在 Windows 上扫描 Go、Node、Python、VS Code、PowerShell 配置
- ✅ 能打包生成 `.devpack` 文件
- ✅ 能在另一台 Windows 上还原
- ✅ 干运行模式可用
- ✅ 基本的冲突处理
- ✅ CLI 交互友好
---
## v0.2.0 — 功能扩展
> **目标:** 更多采集器、环境对比、回滚、macOS 支持
> **预计时间:** 2026 Q3
### 新增功能
#### 更多采集器
- [ ] Java/Kotlin 运行时采集器JDK + Maven/Gradle
- [ ] Rust 运行时采集器rustup + cargo
- [ ] .NET 运行时采集器
- [ ] JetBrains IDE 采集器
- [ ] Vim/Neovim 采集器
- [ ] Bash/Zsh Shell 采集器
- [ ] Homebrew 包管理器采集器macOS
- [ ] Chocolatey 包管理器采集器Windows
- [ ] Winget 包管理器采集器Windows
- [ ] Windows Terminal 配置采集器
#### 环境对比
- [ ] `devpack diff` 命令实现
- [ ] Pack vs 当前环境对比
- [ ] Pack vs Pack 对比
- [ ] 差异可视化输出
#### 回滚机制
- [ ] 还原点创建
- [ ] 还原点管理(列出、删除)
- [ ] 从还原点回滚
- [ ] `devpack rollback` 命令
#### 平台扩展
- [ ] macOS 平台完整支持
- [ ] macOS 采集器适配
- [ ] 跨平台 CI 测试矩阵
#### 改进
- [ ] 还原进度条改进
- [ ] 并行扫描/还原
- [ ] 更好的错误消息和排障指南
- [ ] 测试覆盖率 > 75%
---
## v0.3.0 — 安全与高级功能
> **目标:** 加密支持、增量打包、Linux 支持、远程注册中心
> **预计时间:** 2026 Q4
### 新增功能
#### 安全
- [ ] AES-256-GCM 数据加密
- [ ] Argon2id 密钥派生
- [ ] SSH/GPG 密钥采集器(加密存储)
- [ ] 敏感数据自动检测与警告
- [ ] Pack 文件签名
#### 增量打包
- [ ] 基于上一次快照的差异计算
- [ ] 增量 Pack 生成
- [ ] 增量还原
#### Linux 支持
- [ ] Linux 平台适配
- [ ] APT 包管理器采集器
- [ ] DNF/YUM 包管理器采集器
- [ ] Linux 特定配置采集
#### 远程注册中心(实验性)
- [ ] 注册中心 API 设计
- [ ] Pack 上传/下载
- [ ] 版本管理
- [ ] `devpack registry` 命令
- [ ] 团队共享支持
#### 字体采集器
- [ ] 开发字体检测
- [ ] 字体文件采集
- [ ] 字体安装还原
---
## v1.0.0 — 稳定发布
> **目标:** 生产就绪、性能优化、完善文档
> **预计时间:** 2027 Q1
### 重点
#### 稳定性
- [ ] 全面端到端测试
- [ ] 多 OS 版本兼容性测试
- [ ] 压力测试
- [ ] 边界情况处理
- [ ] 测试覆盖率 > 85%
#### 性能优化
- [ ] 扫描性能优化(缓存、并行)
- [ ] 打包性能优化zstd 压缩可选)
- [ ] 还原性能优化(并行安装)
- [ ] 大文件处理优化
#### 文档完善
- [ ] 完整用户手册
- [ ] API 参考文档
- [ ] 插件开发指南
- [ ] 故障排除指南
- [ ] 视频教程
#### 发布
- [ ] GoReleaser 多平台构建
- [ ] Homebrew Formula
- [ ] Scoop Manifest
- [ ] Docker 镜像(用于 CI
- [ ] 官方网站
---
## 远期规划 (v1.x+)
### 可能的功能方向
| 功能 | 描述 | 优先级 |
|------|------|--------|
| 🔌 插件系统 | 支持第三方采集器插件 | 高 |
| 🌐 Web UI | 基于 Web 的管理界面 | 中 |
| 📱 GUI 客户端 | 桌面 GUI 客户端 | 中 |
| ☁️ 云同步 | 通过云端同步 Pack | 中 |
| 🔄 自动更新 | 定时检查环境变更并自动备份 | 中 |
| 🤝 团队管理 | 团队 Pack 管理和权限控制 | 低 |
| 📊 环境报告 | 生成环境配置报告 | 低 |
| 🐳 Docker 集成 | 从 Dockerfile 提取环境信息 | 低 |
| 🧪 沙盒预览 | 在沙盒中预览还原效果 | 低 |
| 📋 配方系统 | 预设的"开发环境配方"共享 | 低 |
---
## 贡献
路线图中的功能优先级可能根据社区反馈调整。如果你对某个功能特别期待,欢迎:
1. 在 [Issues](https://github.com/user/devpack/issues) 中提出功能请求
2. 为你期待的 Issue 点赞 👍
3. 提交 Pull Request 实现功能
我们优先实现社区呼声最高的功能。

558
docs/USER-GUIDE.md Normal file
View File

@@ -0,0 +1,558 @@
# DevPack 用户手册
> 版本v0.1.0
> 更新日期2026-03-03
---
## 目录
1. [简介](#1-简介)
2. [安装](#2-安装)
3. [快速入门](#3-快速入门)
4. [核心概念](#4-核心概念)
5. [命令详解](#5-命令详解)
6. [使用场景](#6-使用场景)
7. [配置文件](#7-配置文件)
8. [常见问题](#8-常见问题)
9. [故障排除](#9-故障排除)
---
## 1. 简介
DevPack 是一个开发环境打包迁移工具。它可以:
- 🔍 **扫描** 你当前电脑上安装的开发工具、配置、环境变量等
- 📦 **打包** 成一个可移植的 `.devpack` 文件
- 🚀 **还原** 在另一台电脑上一键恢复完整开发环境
### 支持的内容
| 类别 | 支持的项目 |
|------|-----------|
| 编程语言 | Go, Node.js, Python, Java, Rust, .NET, Ruby, PHP |
| 包管理器 | Scoop, Chocolatey, Winget, Homebrew, APT |
| 编辑器 | VS Code (扩展+设置), JetBrains IDEs, Vim/Neovim |
| Shell | PowerShell, Bash, Zsh, Fish, Windows Terminal |
| 其他 | Git 配置, 环境变量, SSH 密钥, 字体 |
---
## 2. 安装
### 2.1 通过 Go 安装
```bash
go install github.com/user/devpack@latest
```
### 2.2 通过包管理器安装
**Windows (Scoop):**
```powershell
scoop bucket add devpack https://github.com/user/devpack-bucket
scoop install devpack
```
**Windows (Chocolatey):**
```powershell
choco install devpack
```
**macOS (Homebrew):**
```bash
brew tap user/devpack
brew install devpack
```
### 2.3 下载二进制文件
1. 前往 [GitHub Releases](https://github.com/user/devpack/releases)
2. 下载对应你系统的压缩包
3. 解压到一个目录(如 `C:\Tools\devpack\`
4. 将该目录添加到系统 PATH
### 2.4 验证安装
```bash
devpack version
```
输出示例:
```
DevPack v0.1.0 (commit: abc1234, built: 2026-03-03)
OS: windows/amd64
```
---
## 3. 快速入门
### 3.1 五分钟上手
```bash
# 第一步:初始化
devpack init
# 第二步:扫描你的环境
devpack scan
# 第三步:打包
devpack capture --name "my-env"
# 第四步:导出为文件(可以拷贝到 U 盘)
devpack export my-env -o my-env.devpack
```
拿到 `.devpack` 文件后,在新电脑上:
```bash
# 第五步:安装 DevPack 后,导入文件
devpack import my-env.devpack
# 第六步:预览将要做的更改
devpack restore my-env --dry-run
# 第七步:正式还原
devpack restore my-env
```
### 3.2 推荐工作流
```
旧电脑 新电脑
────── ──────
devpack init (安装 DevPack)
│ │
devpack scan │
│ │
devpack capture --name env │
│ │
devpack export env │
│ │
└── my-env.devpack ──(U盘)──▶ │
devpack import my-env.devpack
devpack restore env --dry-run
devpack restore env
✅ 环境就绪!
```
---
## 4. 核心概念
### 4.1 Pack环境包
Pack 是 DevPack 生成的打包文件(`.devpack` 格式)。它包含:
- **Manifest** — 描述包内容的清单
- **采集器数据** — 各个采集器收集的环境数据
- **校验信息** — 确保文件完整性
一个 Pack 代表某一时刻你的开发环境的"快照"。
### 4.2 Profile配置方案
Profile 定义了"打包什么"和"怎么打包"。通过 Profile你可以
- 只打包特定的工具链(如只打包 Go + VS Code
- 排除不需要的内容
- 为不同场景准备不同的配置方案
内置 Profile 模板:
| 模板 | 包含内容 |
|------|---------|
| `minimal` | 只有编辑器设置和 Shell 配置 |
| `standard` | 运行时 + 编辑器 + Shell + Git + 环境变量 |
| `full` | 所有可用的采集器 |
### 4.3 Collector采集器
采集器是负责扫描和收集特定类型环境信息的模块。每个采集器独立工作:
| 采集器 | 扫描内容 | 还原方式 |
|--------|---------|---------|
| `go` | Go 版本、go env、GOPATH/bin 工具 | 下载安装器 |
| `node` | Node 版本、npm 全局包 | nvm/直接安装 |
| `python` | Python 版本、pip 全局包 | 安装器/pyenv |
| `vscode` | 扩展列表、settings.json | code --install-extension |
| `powershell` | Profile、已安装模块 | 复制 Profile + Install-Module |
| `scoop` | bucket 列表、已安装包 | scoop install |
| `git` | .gitconfig、aliases | 复制配置 |
| `env` | 用户环境变量 | setx/export |
### 4.4 还原策略
当还原时遇到已存在的配置DevPack 提供多种处理策略:
| 策略 | 行为 |
|------|------|
| `skip` | 跳过,保留现有配置 |
| `overwrite` | 覆盖,使用 Pack 中的配置 |
| `merge` | 合并两者(适用于配置文件) |
| `prompt` | 逐项询问用户(默认) |
| `newest` | 使用较新的版本 |
---
## 5. 命令详解
### 5.1 devpack init
初始化 DevPack 配置。
```bash
# 默认初始化
devpack init
# 使用 standard 模板
devpack init --template standard
# 指定 Profile 名称
devpack init --profile my-profile
```
这会在 `~/.devpack/` 下创建配置目录和默认配置文件。
### 5.2 devpack scan
扫描当前环境,展示检测到的开发工具和配置。
```bash
# 扫描所有
devpack scan
# 详细模式
devpack scan --detailed
# 只扫描运行时
devpack scan --category runtime
# 只扫描特定采集器
devpack scan -c go,node,vscode
# 输出为 JSON
devpack scan -o json
# 保存扫描结果
devpack scan --save my-scan.json
```
### 5.3 devpack capture
捕获环境数据并创建 Pack。
```bash
# 基本用法
devpack capture --name "my-env"
# 使用 Profile
devpack capture --name "go-env" --profile golang-dev
# 捕获所有
devpack capture --name "full-env" --all
# 只捕获特定采集器
devpack capture --name "editor-env" -c vscode,git
# 带描述和标签
devpack capture --name "v1" \
--description "生产环境工具链" \
--tag golang,production
```
### 5.4 devpack restore
从 Pack 还原环境。
```bash
# 先预览
devpack restore my-env --dry-run
# 执行还原
devpack restore my-env
# 跳过冲突项
devpack restore my-env --conflict skip
# 覆盖所有冲突
devpack restore my-env --conflict overwrite
# 只还原特定采集器
devpack restore my-env -c vscode,git
# 跳过确认
devpack restore my-env -y
```
### 5.5 devpack export / import
```bash
# 导出为文件
devpack export my-env -o ~/Desktop/my-env.devpack
# 导入文件
devpack import ~/Desktop/my-env.devpack
# 导入并指定名称
devpack import ~/Desktop/my-env.devpack --name imported-env
# 导入前验证
devpack import ~/Desktop/my-env.devpack --verify
```
### 5.6 devpack diff
对比环境差异。
```bash
# 与当前环境对比
devpack diff my-env --current
# 两个 Pack 对比
devpack diff old-env --with new-env
# 只对比特定采集器
devpack diff my-env --current -c runtime
```
### 5.7 devpack list
```bash
# 列出所有 Pack
devpack list packs
# 列出所有 Profile
devpack list profiles
# 列出所有可用采集器
devpack list collectors
# 详细信息
devpack list packs --detailed
```
### 5.8 devpack profile
```bash
# 创建 Profile
devpack profile create my-profile
# 查看 Profile
devpack profile show my-profile
# 编辑 Profile使用默认编辑器打开
devpack profile edit my-profile
# 设置默认 Profile
devpack profile use my-profile
# 删除 Profile
devpack profile delete my-profile
# 列出所有 Profile
devpack profile list
```
---
## 6. 使用场景
### 6.1 个人换电脑
**场景:** 你买了一台新笔记本电脑,需要迁移开发环境。
**步骤:**
在旧电脑上:
```bash
devpack init
devpack scan --detailed # 确认要迁移的内容
devpack capture --name "laptop-2026" --all
devpack export laptop-2026 -o laptop-2026.devpack
```
`laptop-2026.devpack` 拷贝到 U 盘或通过网络传到新电脑。
在新电脑上:
```bash
# 先安装 DevPack
devpack import laptop-2026.devpack
devpack restore laptop-2026 --dry-run # 预览
devpack restore laptop-2026 # 开始还原
```
### 6.2 团队环境统一
**场景:** 你是 Tech Lead需要为团队准备统一的开发环境。
**步骤:**
1. 创建团队 Profile
```bash
devpack profile create team-standard
devpack profile edit team-standard
```
2. 在 Profile 中定义标准配置(编辑 YAML 文件)
3. 使用 Profile 打包:
```bash
devpack capture --name "team-env-v1" --profile team-standard
devpack export team-env-v1 -o team-env-v1.devpack
```
4. 分发给团队成员
5. 成员还原:
```bash
devpack import team-env-v1.devpack
devpack restore team-env-v1
```
### 6.3 项目环境隔离
**场景:** 你同时参与 Go 和 Python 项目,需要不同的环境配置。
**步骤:**
1. 为每个项目创建 Profile
```bash
devpack profile create golang-project
devpack profile create python-ml
```
2. 分别配置各 Profile 只包含对应工具链
3. 按项目打包:
```bash
devpack capture --name "go-env" --profile golang-project
devpack capture --name "ml-env" --profile python-ml
```
### 6.4 环境排障
**场景:** 同事说"在我电脑上能跑",你需要对比环境差异。
```bash
# 让同事导出环境
# (同事) devpack capture --name "alice-env" && devpack export alice-env
# 你导入并对比
devpack import alice-env.devpack
devpack diff alice-env --current
```
差异输出会清晰展示两个环境的不同之处。
---
## 7. 配置文件
### 7.1 配置文件位置
| 文件 | 路径 | 说明 |
|------|------|------|
| 全局配置 | `~/.devpack/config.yaml` | DevPack 全局设置 |
| Profile | `~/.devpack/profiles/<name>.yaml` | 命名配置方案 |
| 日志 | `~/.devpack/logs/devpack.log` | 运行日志 |
| Pack 存储 | `~/.devpack/packs/` | 本地 Pack 存储 |
### 7.2 自定义配置示例
```yaml
# ~/.devpack/config.yaml
defaults:
profile: "standard"
compression: "gzip"
conflict_strategy: "prompt"
logging:
level: "info"
ui:
color: true
progress_bar: true
security:
scan_for_secrets: true
exclude_patterns:
- "*_KEY"
- "*_SECRET"
- "*_TOKEN"
```
---
## 8. 常见问题
### Q: DevPack 和 Docker 有什么区别?
Docker 用于打包**应用运行环境**应用运行在容器中DevPack 用于打包**开发者的本地开发环境**,直接还原到宿主机。两者是互补关系。
### Q: 支持跨操作系统迁移吗?
不支持。DevPack 只支持同一操作系统之间的迁移Windows → Windows, macOS → macOS。不同操作系统的工具链和配置差异太大无法可靠地自动转换。
### Q: 还原会覆盖我现有的配置吗?
默认不会。DevPack 使用 `prompt` 策略,遇到冲突会询问你如何处理。你也可以先使用 `--dry-run` 预览所有更改。
### Q: Pack 文件大小一般多大?
典型的开发环境 Pack 大小在 5-50 MB 之间。Pack 文件只包含配置信息和元数据,不包含实际的安装程序二进制文件(还原时会从网络下载)。
### Q: 密码和密钥安全吗?
DevPack 默认不采集 SSH 密钥和密码。如果你选择采集 SSH 密钥,它们会使用 AES-256-GCM 加密存储。DevPack 不会采集浏览器密码、系统凭证等隐私数据。
### Q: 还原需要网络连接吗?
是的。还原过程需要从网络下载对应版本的安装程序。Pack 文件只包含"安装什么"的信息,不包含安装程序本身。
### Q: 还原失败了怎么办?
如果开启了还原点功能(默认开启),可以使用 `devpack rollback` 撤销所有更改,回到还原前的状态。
---
## 9. 故障排除
### 9.1 查看详细日志
```bash
# 开启详细输出
devpack scan --verbose
# 开启 debug 日志
devpack scan --log-level debug
# 查看日志文件
# Windows
notepad %USERPROFILE%\.devpack\logs\devpack.log
# macOS/Linux
cat ~/.devpack/logs/devpack.log
```
### 9.2 常见错误
| 错误 | 原因 | 解决方案 |
|------|------|---------|
| `collector not available` | 对应的工具未安装 | 安装对应工具或排除该采集器 |
| `pack file corrupted` | Pack 文件损坏 | 使用 `devpack verify` 检查,重新导出 |
| `platform mismatch` | Pack 的系统与当前不一致 | 只能在相同 OS 之间还原 |
| `permission denied` | 权限不足 | 以管理员身份运行 |
| `network timeout` | 下载超时 | 检查网络,或设置代理 |
### 9.3 报告问题
如果遇到无法解决的问题:
1. 运行 `devpack scan --log-level debug --save debug-info.json`
2. 查看 `~/.devpack/logs/devpack.log`
3. 在 [GitHub Issues](https://github.com/user/devpack/issues) 创建 Issue
4. 附上 debug 日志(注意删除敏感信息)