nkds

导航

 

MonkeyCode 开源项目的版本管理策略:从语义化版本到发布节奏的完整实践

引言

在开源软件的世界里,版本管理(Version Management) 不仅仅是给代码打标签那么简单——它是项目与用户之间建立信任的契约,是依赖管理的基石,也是团队协作的节拍器。作为一款支持私有化部署的 AI 编程工具,MonkeyCode 在版本管理方面积累了丰富的实践经验。本文将全面分享我们的版本管理策略、工具链配置和最佳实践。

GitHub Issue 邀请:如果您在版本管理、语义化版本规范或发布流程方面有任何问题或建议,欢迎前往 MonkeyCode GitHub 仓库 提交 Issue 或参与讨论!


一、为什么版本管理如此重要?

1.1 版本管理的核心价值

┌─────────────────────────────────────────────────────────────┐
│           📌 版本管理的六大核心价值                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  🔢 可预测性                                                │
│     → 用户知道何时升级安全                                   │
│     → 依赖方可以锁定兼容版本                                 │
│     → 团队成员理解变更范围                                   │
│                                                             │
│  🔗 互操作性                                                │
│     → API 兼容性清晰定义                                     │
│     → 依赖冲突可提前发现                                     │
│     → 集成测试有明确目标                                     │
│                                                             │
│  📊 可追溯性                                                │
│     → Bug 可以关联到具体版本                                 │
│     → 变更历史有据可查                                       │
│     → 回滚决策有数据支撑                                     │
│                                                             │
│  🤝 信任建设                                                │
│     → 承诺的稳定性增强用户信心                               │
│     → 透明的变更日志建立专业形象                             │
│     → 一致的发布节奏培养社区习惯                             │
│                                                             │
│  ⚡ 效率提升                                                │
│     → 自动化流水线减少人工错误                               │
│     → 标准化流程降低沟通成本                                 │
│     → 工具链集成加速开发迭代                                 │
│                                                             │
│  🛡️ 风险控制                                                │
│     → Breaking Changes 有预警机制                            │
│     → 安全补丁快速响应通道                                   │
│     → 灰度发布和回滚能力                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 版本管理不善的代价

问题类型 影响 实际案例
版本号混乱 用户不知道该用哪个版本 某知名库同时存在 v1.0, v1.0.1, v2.0-alpha, v2.0-rc1, v2.0-final
Breaking Change 无预警 依赖方大规模故障 left-pad 事件(2016)
Changelog 缺失 无法评估升级风险 多个 npm 包无更新说明导致升级困难
发布节奏不稳定 用户无法规划升级时间 某框架半年不更新,一周发5个版本

二、MonkeyCode 的版本管理架构

2.1 语义化版本(SemVer)实践

semver_implementation:
  
  format: "MAJOR.MINOR.PATCH[-prerelease][+build]"
  
  rules:
    MAJOR:
      trigger: "不兼容的 API 变更"
      examples:
        - "移除已废弃的 API endpoint"
        - "改变核心配置文件格式"
        - "修改插件接口签名"
      process: "RFC 讨论 → 废弃期(≥2个版本) → 移除"
      
    MINOR:
      trigger: "向后兼容的功能新增"
      examples:
        - "新增 AI 模型提供商支持"
        - "增加新的 CLI 命令"
        - "扩展 API 能力(不影响现有调用)"
        
    PATCH:
      trigger: "向后兼容的问题修复"
      examples:
        - "修复特定场景下的 bug"
        - "更新文档中的错误描述"
        - "改进错误提示信息"
        
    prerelease:
      formats:
        - "alpha.{n}": "内部测试阶段,API 可能变化"
        - "beta.{n}": "公开测试,功能冻结但可能有 bug"
        - "rc.{n}": "候选发布版,仅修复 critical bug"

2.2 版本号示例

MonkeyCode 版本演进示例:

v0.1.0-alpha.1   → 初始原型,仅核心功能可用
v0.1.0-beta.1    → 功能基本完成,邀请早期体验者
v0.1.0           → 首个公开版本
v0.2.0           → 新增 GPT-4 支持(功能新增)
v0.2.1           → 修复 GPT-4 超时处理(bug 修复)
v1.0.0-rc.1      → API 稳定,准备正式发布
v1.0.0           → 正式发布!API 兼容性承诺生效
v1.1.0           → 新增 Claude 支持
v1.2.0           → 新增本地模型运行能力
v2.0.0-alpha.1   → 重构插件系统(breaking change)

三、分支管理与发布流程

3.1 Git 分支策略

graph TD A[main<br/>稳定发布版] -->|hotfix| B[hotfix/x.y.z] B -->|merge + tag| A A -->|release branch| C[release/vx.y.z] C -->|bug fixes only| C C -->|tag + merge| A C -->|backport to| D[develop] D[develop<br/>开发集成分支] -->|feature| E[feature/xxx] E -->|PR review| D D -->|ready for release| C style A fill:#2ECC40,color:#fff style D fill:#3498DB,color:#fff style C fill:#F39C12,color:#000 style E fill:#9B59B6,color:#fff style B fill:#E74C3C,color:#fff

3.2 分支命名与保护规则

branch_strategy:

  main:
    name: "main"
    protection:
      required_reviews: 2
      required_status_checks:
        - "CI / Build (ubuntu-latest)"
        - "CI / Test (ubuntu-latest)"
        - "CodeQL Analysis"
        - "Dependabot Security"
      dismiss_stale_reviews: true
      restrict_push: true
      allowed_pushers: ["release-bot", "maintainers-team"]
    commit_message_format: "release(v{version})"
    
  develop:
    name: "develop"
    purpose: "开发集成分支"
    base_for_feature_branches: true
    sync_with_main: "daily via bot"
    
  feature:
    pattern: "feature/{ticket-id}-{short-description}"
    source: "develop"
    target: "develop"
    lifecycle: "delete after merge"
    
  release:
    pattern: "release/v{major}.{minor}"
    source: "develop"
    target: "main + develop"
    lifecycle: "delete after release"
    
  hotfix:
    pattern: "hotfix/v{major}.{minor}.{patch}"
    source: "main"
    target: "main + develop"
    lifecycle: "delete after merge"

3.3 发布流程详解

## 🚀 MonkeyCode 标准发布流程

### Phase 1: 准备阶段

**触发条件**:
- [ ] develop 分支的所有 PR 已合并
- [ ] CI 全绿
- [ ] 测试覆盖率 ≥ 目标阈值
- [ ] Changelog 已更新
- [ ] 文档已同步更新

**操作步骤**:
1. 从 develop 创建 `release/vX.Y.Z` 分支
2. 更新版本号(所有涉及位置)
3. 运行完整的 Release CI 流水线

### Phase 2: 候选发布(RC)

**RC 发布检查清单**:
- [ ] 所有 Critical/High bug 已修复或接受延期
- [ ] 性能基准测试通过
- [ ] 安全扫描无 High/Critical 发现
- [ ] 向前兼容性验证通过
- [ ] 向后兼容性验证通过
- [ ] 升级路径测试完成(从 N-2 到当前版本)

**RC 发布操作**:
```bash
# 创建 RC tag
git tag -a v1.2.0-rc.1 -m "Release candidate 1 for v1.2.0"
git push origin v1.2.0-rc.1

# GitHub Release(Draft)
gh release create v1.2.0-rc.1 \
  --title "v1.2.0-rc.1 (Release Candidate)" \
  --notes-file CHANGELOG.md \
  --prerelease \
  --draft

Phase 3: 正式发布

最终检查:

发布操作:

# 正式 tag
git tag -a v1.2.0 -m "Release v1.2.0"
git push origin v1.2.0

# 合并到 main
# (由 release-bot 或 maintainer 执行)

# GitHub Release
gh release create v1.2.0 \
  --title "🎉 MonkeyCode v1.2.0" \
  --notes-file RELEASE_NOTES.md \
  --generate-notes

# Publish to package registries
npm publish
# 或其他包管理器的发布命令

---

## 四、自动化工具链

### 4.1 Version Automation 配置

```typescript
// .github/version.ts — MonkeyCode 版本自动管理脚本
import { readFileSync, writeFileSync } from 'fs';
import { execSync } from 'child_process';

interface Version {
  major: number;
  minor: number;
  patch: string;
  prerelease?: string;
}

export function getCurrentVersion(): Version {
  const pkg = JSON.parse(readFileSync('package.json', 'utf-8'));
  return parseVersion(pkg.version);
}

export function parseVersion(versionStr: string): Version {
  const match = versionStr.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
  if (!match) throw new Error(`Invalid version: ${versionStr}`);
  return {
    major: parseInt(match[1]),
    minor: parseInt(match[2]),
    patch: match[3],
    prerelease: match[4],
  };
}

export function bumpVersion(
  current: Version,
  type: 'major' | 'minor''patch' | 'prerelease'
): Version {
  switch (type) {
    case 'major':
      return { ...current, major: current.major + 1, minor: 0, patch: '0', prerelease: undefined };
    case 'minor':
      return { ...current, minor: current.minor + 1, patch: '0', prerelease: undefined };
    case 'patch':
      return { ...current, patch: String(parseInt(current.patch) + 1), prerelease: undefined };
    case 'prerelease': {
      const prerelease = current.prerelease || 'alpha.0';
      const [prefix, num] = prerelease.split('.');
      return { ...current, prerelease: `${prefix}.${parseInt(num) + 1}` };
    }
  }
}

export function updateAllVersionFiles(newVersion: Version): void {
  const versionStr = formatVersion(newVersion);
  
  // Update package.json
  const pkg = JSON.parse(readFileSync('package.json', 'utf-8'));
  pkg.version = versionStr;
  writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
  
  // Update Cargo.toml if exists
  // Update pyproject.toml if exists
  // Update VERSION file
  writeFileSync('VERSION', versionStr + '\n');
  
  console.log(`✅ Updated all version files to ${versionStr}`);
}

function formatVersion(v: Version): string {
  let result = `${v.major}.${v.minor}.${v.patch}`;
  if (v.prerelease) result += `-${v.prerelease}`;
  return result;
}

4.2 GitHub Actions Release Workflow

# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - 'v[0-9]+.[0-9]+.[0-9]+'          # 正式版本
      - 'v[0-9]+.[0-9]+.[0-9]+-*'         # 预发布版本

permissions:
  contents: write
  packages: write

jobs:
  prepare:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
      is_prerelease: ${{ steps.version.outputs.is_prerelease }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - id: version
        name: Extract version info
        run: |
          VERSION=${GITHUB_REF_NAME#v}
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          if [[ "$VERSION" == *-* ]]; then
            echo "is_prerelease=true" >> $GITHUB_OUTPUT
          else
            echo "is_prerelease=false" >> $GITHUB_OUTPUT
          fi

  build:
    needs: prepare
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        include:
          - os: ubuntu-latest
            artifact_name: monkeycode-linux-amd64
            asset_name: monkeycode-${{ needs.prepare.outputs.version }}-linux-amd64.tar.gz
          - os: macos-latest
            artifact_name: monkeycode-darwin-amd64
            asset_name: monkeycode-${{ needs.prepare.outputs.version }}-darwin-amd64.tar.gz
          - os: windows-latest
            artifact_name: monkeycode-windows-amd64.exe
            asset_name: monkeycode-${{ needs.prepare.outputs.version }}-windows-amd64.zip
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      
      - run: npm ci
      - run: npm run build
      - run: npm run package:${{ matrix.os == 'windows-latest' && 'win' || matrix.os == 'macos-latest' && 'mac' || 'linux' }}
      
      - uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.artifact_name }}
          path: dist/

  release:
    needs: [prepare, build]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/download-artifact@v4
        with:
          path: artifacts/
          pattern: monkeycode-*
          merge-multiple: true
      
      - name: Generate changelog
        id: changelog
        run: |
          # 使用 git-chglog 或自定义脚本生成 changelog
          PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
          node .github/scripts/generate-changelog.js > RELEASE_BODY.md
          
      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ github.ref_name }}
          name: Release ${{ needs.prepare.outputs.version }}
          body_path: RELEASE_BODY.md
          draft: false
          prerelease: ${{ needs.prepare.outputs.is_prerelease == 'true' }}
          files: artifacts/*
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  publish-npm:
    needs: [prepare, build]
    runs-on: ubuntu-latest
    if: needs.prepare.outputs.is_prerelease != 'true'
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          registry-url: 'https://registry.npmjs.org'
      
      - run: npm ci
      - run: npm run build
      
      - run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

  docker-push:
    needs: [prepare, build]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            monkeycode/monkeyCode:${{ needs.prepare.outputs.version }}
            ${{ needs.prepare.outputs.is_prerelease != 'true' && 'monkeycode/monkeyCode:latest' || '' }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

4.3 Changelog 自动生成

// .github/scripts/generate-changelog.js
const { execSync } = require('child_process');

const TYPE_EMOJI = {
  feat: '✨',
  fix: '🐛',
  docs: '📝',
  style: '💎',
  refactor: '♻️',
  perf: '⚡',
  test: '✅',
  build: '📦',
  ci: '🔄',
  chore: '🔧',
  revert: '⏪',
};

const TYPE_LABELS = {
  feat: '新功能',
  fix: 'Bug 修复',
  docs: '文档',
  style: '样式',
  refactor: '重构',
  perf: '性能优化',
  test: '测试',
  build: '构建',
  ci: '持续集成',
  chore: '杂项',
  revert: '回退',
};

function getCommitsSinceLastTag() {
  try {
    const lastTag = execSync('git describe --tags --abbrev=0 HEAD^')
      .toString().trim();
    const log = execSync(
      `git log ${lastTag}..HEAD --pretty=format:"%H|%s|%b"`
    ).toString().trim();
    return log.split('\n').map(line => {
      const [hash, subject, body] = line.split('|');
      return { hash, subject, body };
    });
  } catch {
    return [];
  }
}

function parseConventionalCommit(message) {
  const match = message.match(/^(\w+)(?:\(([^)]+)\))?!?:\s+(.+)$/);
  if (!match) return null;
  return {
    type: match[1],
    scope: match[2] || null,
    breaking: message.includes('!'),
    description: match[3].trim(),
  };
}

function generateChangelog() {
  const commits = getCommitsSinceLastTag();
  const grouped = {};
  
  commits.forEach(({ subject }) => {
    const parsed = parseConventionalCommit(subject);
    if (!parsed) return;
    
    const type = parsed.type in TYPE_LABELS ? parsed.type : 'chore';
    if (!grouped[type]) grouped[type] = [];
    
    const entry = `${TYPE_EMOJI[type]} **${parsed.description}`;
    if (parsed.scope) entry += \` (\${parsed.scope})\`;
    if (parsed.breaking) entry += ' **⚠️ BREAKING';
    entry += '**';
    
    grouped[type].push(entry);
  });
  
  let output = '## What\'s Changed\n\n';
  
  Object.entries(grouped).forEach(([type, items]) => {
    output += \`### \${TYPE_LABELS[type]}\n\n\`;
    items.forEach(item => { output += \`- \${item}\n\`; });
    output += '\n';
  });
  
  return output;
}

console.log(generateChangelog());

五、发布节奏与策略

5.1 MonkeyCode 发布日历

release_rhythm:
  
  regular_releases:
    schedule: "每两周一次(周二)"
    version_type: "MINOR or PATCH"
    content: "累积的功能和修复"
    freeze_period: "发布前 3 天代码冻结"
    
  lts_releases:
    schedule: "每季度一次"
    version_type: "LTS (Long Term Support)"
    support_duration: "18 个月"
    criteria: "经过充分验证的稳定版本"
    
  security_patches:
    trigger: "Critical/High 安全漏洞发现"
    response_time: "< 48 小时(Critical)/< 7 天(High)"
    version_type: "PATCH on latest LTS"
    
  emergency_hotfixes:
    trigger: "生产环境阻断性问题"
    approval: "需要 ≥2 maintainers 批准"
    version_type: "PATCH"
    post_release: "必须包含回归测试计划"

5.2 发布窗口管理

MonkeyCode 2026 H2 发布日历:

  7月 ───┬── 8月 ───┬── 9月 ───┬── 10月 ──┬── 11月 ──┬── 12月 ──
         │         │         │         │         │         │
Week 1   │         │         │         │         │         │
Week 2   │ 🔵v1.3.0 │         │ 🔵v1.4.0 │         │ 🔵v1.5.0 │
Week 3   │         │         │         │         │         │
Week 4   │         │ 🟢LTS1.2 │         │         │         │ 🟢LTS1.5

图例:
🔵  定期发布(双周)
🟢  LTS 季度发布
🔴  紧急热修复(按需)

六、版本兼容性与迁移

6.1 兼容性矩阵

-- MonkeyCode 版本兼容性查询视图
CREATE VIEW version_compatibility AS
SELECT 
  v.version,
  v.release_date,
  v.status,
  v.support_until,
  CASE 
    WHEN v.status = 'lts' THEN '18 months from release'
    WHEN v.status = 'stable' THEN '6 months from next minor'
    ELSE '3 months from release'
  END AS support_policy,
  ARRAY(
    SELECT DISTINCT api_version 
    FROM api_changes ac 
    WHERE ac.version_from <= v.version 
    AND ac.version_to >= v.version 
    AND ac.change_type != 'breaking'
  ) AS compatible_api_versions,
  COUNT(CASE WHEN ac.change_type = 'breaking' THEN 1 END) AS breaking_changes_count
FROM versions v
LEFT JOIN api_changes ac ON v.version = ac.version_to
WHERE v.release_date >= CURRENT_DATE - INTERVAL '2 years'
GROUP BY v.version, v.release_date, v.status, v.support_until
ORDER BY v.release_date DESC;

6.2 Deprecation 流程

## 📋 MonkeyCode API 废弃标准流程

### 时间线

T=0 宣布废弃(在 Changelog 和文档中标注 @deprecated)
↓
T+2周 发送废弃通知(GitHub Discussion + Discord 公告)
↓
T+1版本 新版本中标记为 deprecated(编译时警告)
↓
T+2版本 保留功能但默认禁用(需显式启用)
↓
T+3版本 完全移除(Breaking Change,进入下一个 MAJOR 版本)


### 废弃声明模板

```typescript
/**
 * @deprecated Since v1.3.0. Will be removed in v2.0.0.
 * Use `generateCodeWithConfig()` instead.
 * 
 * Migration guide: https://docs.monkeyCode.dev/migration/v1-to-v2
 * Discussion: https://github.com/monkeyCode/discussions/42
 * 
 * @reason The old API doesn't support streaming responses and has 
 *         limited configuration options. The new API provides a 
 *         more flexible and future-proof interface.
 */
export function generateCodeLegacy(prompt: string): Promise<string> {
  console.warn(
    '[MonkeyCode] generateCodeLegacy is deprecated since v1.3.0. ' +
    'Use generateCodeWithConfig instead. ' +
    'See: https://docs.monkeyCode.dev/migration/v1-to-v2'
  );
  // ... legacy implementation
}

---

## 七、多包/多仓库版本协调

### 7.1 Monorepo 版本策略

```json
{
  "name": "monkeyCode",
  "version": "1.3.0",
  "private": true,
  "workspaces": [
    "packages/*",
    "apps/*",
    "tools/*"
  ],
  "packages": {
    "@monkeyCode/core": { "version": "1.3.0", "public": true },
    "@monkeyCode/cli": { "version": "1.3.0", "public": true },
    "@monkeyCode/server": { "version": "1.3.0", "public": true },
    "@monkeyCode/plugin-system": { "version": "1.3.0", "public": true },
    "@monkeyCode/ui": { "version": "1.3.0", "public": true },
    "@monkeyCode/config-types": { "version": "1.3.0", "public": true },
    "monkeyCode-vscode-extension": { "version": "1.3.0", "public": true },
    "@monkeyCode/eslint-config": { "version": "1.3.0", "public": true },
    "@monkeyCode/testing-utils": { "version": "1.3.0", "public": false },
    "@monkeyCode/scripts": { "version": "1.3.0", "public": false }
  }
}

7.2 版本联动规则

monorepo_version_rules:
  
  synchronization:
    mode: "single source of truth"
    source: "root package.json version"
    propagation: "all packages inherit root version"
    tool: "changesets (for independent versioning when needed)"
    
  dependency_updates:
    internal_deps: "auto-bump to same version on release"
    external_deps: "manual review during release prep"
    peer_deps: "must match major version range"
    
  publishing_order:
    order:
      - "@monkeyCode/config-types"       # 无内部依赖
      - "@monkeyCode/core"               # 核心逻辑
      - "@monkeyCode/plugin-system"      # 依赖 core
      - "@monkeyCode/server"             # 依赖 core + plugins
      - "@monkeyCode/cli"                # 依赖 server
      - "@monkeyCode/ui"                 # 独立 UI 组件
      - "monkeyCode-vscode-extension"    # 依赖 cli
      - "@monkeyCode/eslint-config"      # 开发工具
    validation: "integration tests after each publish"

八、监控与度量

8.1 版本健康仪表盘指标

# version_health.py — MonkeyCode 版本健康度计算
from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import List, Optional

@dataclass
class VersionMetrics:
    version: str
    release_date: datetime
    days_since_release: int
    open_issues: int
    critical_bugs: int
    adoption_rate: float  # 0-1
    avg_time_to_upgrade: Optional[int]  # days from previous version
    churn_rate: float  # % of users downgrading
    satisfaction_score: Optional[float]  # 1-5 from surveys
    
    def health_score(self) -> int:
        """计算版本健康分数 (0-100)"""
        score = 100
        
        # Bug penalty
        score -= self.critical_bugs * 15
        score -= min(self.open_issues * 2, 30)
        
        # Age factor (newer is better for recent releases)
        if self.days_since_release < 30:
            score += 10
        elif self.days_since_release > 180:
            score -= 10
            
        # Adoption bonus
        score += int(self.adoption_rate * 20)
        
        # Satisfaction factor
        if self.satisfaction_score:
            score += int((self.satisfaction_score - 3) * 10)
            
        # Churn penalty
        score -= int(self.churn_rate * 30)
        
        return max(0, min(100, score))
    
    def status(self) -> str:
        health = self.health_score()
        if health >= 80: return "🟢 Healthy"
        elif health >= 60: return "🟡 Warning"
        elif health >= 40: return "🟠 At Risk"
        else: return "🔴 Critical"

def generate_version_report(versions: List[VersionMetrics]) -> str:
    """生成版本健康报告"""
    report = "# MonkeyCode Version Health Report\n\n"
    report += f"Generated: {datetime.now().isoformat()}\n\n"
    
    report += "| Version | Age | Issues | Critical | Adoption | Health | Status |\n"
    report += "|---------|-----|--------|----------|----------|--------|--------|\n"
    
    for v in sorted(versions, key=lambda x: x.release_date, reverse=True):
        report += (
            f"| {v.version} "
            f"| {v.days_since_release}d "
            f"| {v.open_issues} "
            f"| {v.critical_bugs} "
            f"| {v.adoption_rate:.0%} "
            f"| {v.health_score()} "
            f"| {v.status()} |\n"
        )
    
    return report

8.2 发布质量门禁

release_quality_gates:
  
  pre_release_gates:
    - name: "Test Coverage"
      threshold: ">= 80%"
      blocking: true
      measurement: "codecov/patch"
      
    - name: "Critical Bugs"
      threshold: "== 0"
      blocking: true
      scope: "current release scope"
      
    - name: "Security Scan"
      threshold: "No HIGH/CRITICAL"
      blocking: true
      tools: ["CodeQL", "Dependabot", "Snyk"]
      
    - name: "Performance Regression"
      threshold: "< 5% degradation"
      blocking: false
      warning_only: true
      
    - name: "Documentation Coverage"
      threshold: ">= 90% APIs documented"
      blocking: false
      
  post_release_monitoring:
    - name: "Error Rate Spike"
      threshold: "< 2x baseline within 24h"
      alert_channel: "#ops-alerts"
      
    - name: "Adoption Rate"
      threshold: "> 10% within 7 days"
      comparison: "vs previous version"
      
    - name: "Support Ticket Volume"
      threshold: "< 1.5x baseline"
      tracking_period: "14 days"

九、常见问题与解决方案

9.1 FAQ

## ❓ 常见问题

### Q1: 什么时候应该发布 Major 版本?
**A**: 当你需要做以下任一操作时:
- 删除或改变现有公共 API 的行为
- 改变配置文件的格式(不可向前兼容)
- 更改 CLI 命令的参数结构
- 移除某个已存在的功能模块

**最佳实践**:使用废弃期(至少 2 个 minor 版本)给用户足够的迁移时间。

### Q2: Hotfix 应该如何处理?
**A**:
1. 从 main 创建 `hotfix/vX.Y.Z` 分支
2. 修复问题并添加测试
3. 合并回 main 并打 tag
4. 同时 cherry-pick 回 develop 分支
5. 发布 Hotfix 版本(PATCH 版本号递增)

### Q3: 如何处理预发布版本的依赖?
**A**:
- 预发布版本应使用 `~` (tilde) 范围锁定
- 例如 `"@monkeyCode/core": "~1.3.0-alpha.1"`
- 正式发布时切换到 `^` (caret) 范围

### Q4: 版本号泄露了怎么办?
**A**:
- 如果是 pre-release:直接删除 tag 和 release,重新发布
- 如果是正式版本且未广泛传播:同上
- 如果已经有人在使用:发布 PATCH 版本修复,并在 Changelog 中说明

### Q5: Monorepo 中如何处理独立版本?
**A**:
- 默认模式:所有包共享根版本号(推荐)
- 特殊情况:使用 changesets 进行独立版本控制
- 内部工具包可以跟随主版本,不需要独立发版

十、总结与行动号召

10.1 核心要点回顾

╔═══════════════════════════════════════════════════════════╗
║                                                           ║
║  📦 MonkeyCode 版本管理七大原则                             ║
║                                                           ║
║  1️⃣ 严格 SemVer — MAJOR/MINOR/PATCH 含义明确               ║
║  2️⃣ 自动化优先 — 手动改版本号是错误之源                     ║
║  3️⃣ Changelog 必要 — 每次发布都有清晰的变更记录             ║
║  4️⃣ 分支保护 — main 分支受严格保护                         ║
║  5️⃣ 发布节奏稳定 — 用户可以预期和规划                       ║
║  6️⃣ 废弃有流程 — 给用户足够的时间迁移                       ║
║  7️⃣ 监控反馈 — 发布后的健康度持续追踪                       ║
║                                                           ║
╚═══════════════════════════════════════════════════════════╝

10.2 如何参与?

  • 💬 讨论版本策略:前往 GitHub Discussions 参与 RFC 讨论
  • 🐛 报告版本相关问题:提交 Issue 时标注 area: versioning 标签
  • 🔧 贡献改进:我们欢迎更好的 changelog 生成器、版本检查工具等贡献
  • 📖 阅读更多:查看 MonkeyCode 贡献指南

现在就访问 MonkeyCode GitHub,查看最新版本,或为下一个版本贡献力量!


本文最后更新于 2026 年 7 月 1 日。版本号不是数字游戏,而是对用户的承诺。

相关文章推荐:


© 2026 MonkeyCode Open Source Project. Licensed under Apache License 2.0.
Discord: https://discord.gg/monkeyCode | Twitter/X: @monkeyCode_dev

posted on 2026-07-01 13:12  MonkeyCode  阅读(71)  评论(0)    收藏  举报