变更日志自动化Skill changelog-automation

此技能用于自动化生成变更日志、发布说明和版本管理,遵循Keep a Changelog格式和Conventional Commits规范。它涉及设置自动化工作流、标准化提交消息格式、生成GitHub/GitLab发布说明、管理语义版本控制等。关键词包括:变更日志自动化、Conventional Commits、语义版本控制、GitHub发布、CI/CD工作流、自动化工具、软件开发流程。

DevOps 0 次安装 0 次浏览 更新于 3/22/2026

name: changelog-automation description: 自动化从提交、PR和发布中生成变更日志,遵循Keep a Changelog格式。用于设置发布工作流、生成发布说明或标准化提交约定。

变更日志自动化

模式和工具用于自动化生成变更日志、发布说明和版本管理,遵循行业标准。

何时使用此技能

  • 设置自动化变更日志生成
  • 实施Conventional Commits
  • 创建发布说明工作流
  • 标准化提交消息格式
  • 生成GitHub/GitLab发布说明
  • 管理语义版本控制

核心概念

1. Keep a Changelog格式

# 变更日志

所有对此项目的显著更改将记录在此文件中。

格式基于[Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
并且此项目遵循[语义版本控制](https://semver.org/spec/v2.0.0.html)。

## [未发布]

### 新增

- 新功能X

## [1.2.0] - 2024-01-15

### 新增

- 用户个人资料头像
- 深色模式支持

### 更改

- 改进加载性能40%

### 弃用

- 旧认证API(使用v2)

### 移除

- 遗留支付网关

### 修复

- 登录超时问题(#123)

### 安全

- 更新依赖项以应对CVE-2024-1234

[未发布]: https://github.com/user/repo/compare/v1.2.0...HEAD
[1.2.0]: https://github.com/user/repo/compare/v1.1.0...v1.2.0

2. Conventional Commits

<类型>[可选范围]: <描述>

[可选正文]

[可选页脚]
类型 描述 变更日志部分
feat 新功能 新增
fix 错误修复 修复
docs 文档 (通常排除)
style 格式化 (通常排除)
refactor 代码重构 更改
perf 性能 更改
test 测试 (通常排除)
chore 维护 (通常排除)
ci CI更改 (通常排除)
build 构建系统 (通常排除)
revert 还原提交 移除

3. 语义版本控制

主版本号.次版本号.修订号

主版本号:破坏性更改 (feat! 或 BREAKING CHANGE)
次版本号:新功能 (feat)
修订号:错误修复 (fix)

实施方法

方法1: Conventional Changelog (Node.js)

# 安装工具
npm install -D @commitlint/cli @commitlint/config-conventional
npm install -D husky
npm install -D standard-version
# 或
npm install -D semantic-release

# 设置commitlint
cat > commitlint.config.js << 'EOF'
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      [
        'feat',
        'fix',
        'docs',
        'style',
        'refactor',
        'perf',
        'test',
        'chore',
        'ci',
        'build',
        'revert',
      ],
    ],
    'subject-case': [2, 'never', ['start-case', 'pascal-case', 'upper-case']],
    'subject-max-length': [2, 'always', 72],
  },
};
EOF

# 设置husky
npx husky init
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg

方法2: standard-version配置

// .versionrc.js
module.exports = {
  types: [
    { type: "feat", section: "功能" },
    { type: "fix", section: "错误修复" },
    { type: "perf", section: "性能改进" },
    { type: "revert", section: "还原" },
    { type: "docs", section: "文档", hidden: true },
    { type: "style", section: "样式", hidden: true },
    { type: "chore", section: "杂项", hidden: true },
    { type: "refactor", section: "代码重构", hidden: true },
    { type: "test", section: "测试", hidden: true },
    { type: "build", section: "构建系统", hidden: true },
    { type: "ci", section: "CI/CD", hidden: true },
  ],
  commitUrlFormat: "{{host}}/{{owner}}/{{repository}}/commit/{{hash}}",
  compareUrlFormat:
    "{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...{{currentTag}}",
  issueUrlFormat: "{{host}}/{{owner}}/{{repository}}/issues/{{id}}",
  userUrlFormat: "{{host}}/{{user}}",
  releaseCommitMessageFormat: "chore(release): {{currentTag}}",
  scripts: {
    prebump: 'echo "运行prebump"',
    postbump: 'echo "运行postbump"',
    prechangelog: 'echo "运行prechangelog"',
    postchangelog: 'echo "运行postchangelog"',
  },
};
// package.json脚本
{
  "scripts": {
    "release": "standard-version",
    "release:minor": "standard-version --release-as minor",
    "release:major": "standard-version --release-as major",
    "release:patch": "standard-version --release-as patch",
    "release:dry": "standard-version --dry-run"
  }
}

方法3: semantic-release (全自动化)

// release.config.js
module.exports = {
  branches: [
    "main",
    { name: "beta", prerelease: true },
    { name: "alpha", prerelease: true },
  ],
  plugins: [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@semantic-release/changelog",
      {
        changelogFile: "CHANGELOG.md",
      },
    ],
    [
      "@semantic-release/npm",
      {
        npmPublish: true,
      },
    ],
    [
      "@semantic-release/github",
      {
        assets: ["dist/**/*.js", "dist/**/*.css"],
      },
    ],
    [
      "@semantic-release/git",
      {
        assets: ["CHANGELOG.md", "package.json"],
        message:
          "chore(release): ${nextRelease.version} [skip ci]

${nextRelease.notes}",
      },
    ],
  ],
};

方法4: GitHub Actions工作流

# .github/workflows/release.yml
name: 发布

on:
  push:
    branches: [main]
  workflow_dispatch:
    inputs:
      release_type:
        description: "发布类型"
        required: true
        default: "patch"
        type: choice
        options:
          - patch
          - minor
          - major

permissions:
  contents: write
  pull-requests: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.GITHUB_TOKEN }}

      - uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"

      - run: npm ci

      - name: 配置Git
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"

      - name: 运行semantic-release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npx semantic-release

  # 替代方法:手动发布使用standard-version
  manual-release:
    if: github.event_name == 'workflow_dispatch'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: "20"

      - run: npm ci

      - name: 配置Git
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"

      - name: 版本提升并生成变更日志
        run: npx standard-version --release-as ${{ inputs.release_type }}

      - name: 推送更改
        run: git push --follow-tags origin main

      - name: 创建GitHub发布
        uses: softprops/action-gh-release@v1
        with:
          tag_name: ${{ steps.version.outputs.tag }}
          body_path: RELEASE_NOTES.md
          generate_release_notes: true

方法5: git-cliff (基于Rust, 快速)

# cliff.toml
[changelog]
header = """
# 变更日志

所有对此项目的显著更改将记录在此文件中。

"""
body = """
{% if version %}\
    ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
    ## [未发布]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
    ### {{ group | upper_first }}
    {% for commit in commits %}
        - {% if commit.scope %}**{{ commit.scope }}:** {% endif %}\
            {{ commit.message | upper_first }}\
            {% if commit.github.pr_number %} ([#{{ commit.github.pr_number }}](https://github.com/owner/repo/pull/{{ commit.github.pr_number }})){% endif %}\
    {% endfor %}
{% endfor %}
"""
footer = """
{% for release in releases -%}
    {% if release.version -%}
        {% if release.previous.version -%}
            [{{ release.version | trim_start_matches(pat="v") }}]: \
                https://github.com/owner/repo/compare/{{ release.previous.version }}...{{ release.version }}
        {% endif -%}
    {% else -%}
        [未发布]: https://github.com/owner/repo/compare/{{ release.previous.version }}...HEAD
    {% endif -%}
{% endfor %}
"""
trim = true

[git]
conventional_commits = true
filter_unconventional = true
split_commits = false
commit_parsers = [
    { message = "^feat", group = "功能" },
    { message = "^fix", group = "错误修复" },
    { message = "^doc", group = "文档" },
    { message = "^perf", group = "性能" },
    { message = "^refactor", group = "重构" },
    { message = "^style", group = "样式" },
    { message = "^test", group = "测试" },
    { message = "^chore\\(release\\)", skip = true },
    { message = "^chore", group = "杂项" },
]
filter_commits = false
tag_pattern = "v[0-9]*"
skip_tags = ""
ignore_tags = ""
topo_order = false
sort_commits = "oldest"

[github]
owner = "owner"
repo = "repo"
# 生成变更日志
git cliff -o CHANGELOG.md

# 为特定范围生成
git cliff v1.0.0..v2.0.0 -o RELEASE_NOTES.md

# 预览不写入
git cliff --unreleased --dry-run

方法6: Python (commitizen)

# pyproject.toml
[tool.commitizen]
name = "cz_conventional_commits"
version = "1.0.0"
version_files = [
    "pyproject.toml:version",
    "src/__init__.py:__version__",
]
tag_format = "v$version"
update_changelog_on_bump = true
changelog_incremental = true
changelog_start_rev = "v0.1.0"

[tool.commitizen.customize]
message_template = "{{change_type}}{% if scope %}({{scope}}){% endif %}: {{message}}"
schema = "<类型>(<范围>): <主题>"
schema_pattern = "^(feat|fix|docs|style|refactor|perf|test|chore)(\\(\\w+\\))?:\\s.*"
bump_pattern = "^(feat|fix|perf|refactor)"
bump_map = {"feat" = "MINOR", "fix" = "PATCH", "perf" = "PATCH", "refactor" = "PATCH"}
# 安装
pip install commitizen

# 交互式创建提交
cz commit

# 提升版本并更新变更日志
cz bump --changelog

# 检查提交
cz check --rev-range HEAD~5..HEAD

发布说明模板

GitHub发布模板

## 有什么变化

### 🚀 功能

{{ range .Features }}

- {{ .Title }} 由 @{{ .Author }} 在 #{{ .PR }}
  {{ end }}

### 🐛 错误修复

{{ range .Fixes }}

- {{ .Title }} 由 @{{ .Author }} 在 #{{ .PR }}
  {{ end }}

### 📚 文档

{{ range .Docs }}

- {{ .Title }} 由 @{{ .Author }} 在 #{{ .PR }}
  {{ end }}

### 🔧 维护

{{ range .Chores }}

- {{ .Title }} 由 @{{ .Author }} 在 #{{ .PR }}
  {{ end }}

## 新贡献者

{{ range .NewContributors }}

- @{{ .Username }} 在 #{{ .PR }} 中首次贡献
  {{ end }}

**完整变更日志**: https://github.com/owner/repo/compare/v{{ .Previous }}...v{{ .Current }}

内部发布说明

# 发布 v2.1.0 - 2024年1月15日

## 总结

此发布引入深色模式支持,并提高结账性能40%。还包括重要的安全更新。

## 亮点

### 🌙 深色模式

用户现在可以从设置切换到深色模式。偏好自动保存并跨设备同步。

### ⚡ 性能

- 结账流程快40%
- 减少捆绑包大小15%

## 破坏性更改

此发布中无破坏性更改。

## 升级指南

无需特殊步骤。标准部署流程适用。

## 已知问题

- 深色模式可能在初始加载时闪烁(计划在v2.1.1中修复)

## 更新依赖项

| 包       | 从       | 到       | 原因                   |
| -------- | -------- | -------- | ---------------------- |
| react    | 18.2.0   | 18.3.0   | 性能改进               |
| lodash   | 4.17.20  | 4.17.21  | 安全补丁               |

提交消息示例

# 带范围的功能
feat(auth): 添加Google登录的OAuth2支持

# 带问题引用的错误修复
fix(checkout): 解决支付处理中的竞争条件

关闭 #123

# 破坏性更改
feat(api)!: 更改用户端点响应格式

破坏性更改:用户端点现在返回`userId`而不是`id`。
迁移指南:更新所有API消费者使用新字段名。

# 多段落
fix(database): 优雅处理连接超时

之前,连接超时会导致整个请求失败而无重试。此更改实施指数退避,最多重试3次再失败。

基于p99延迟分析,超时阈值从5秒增加到10秒。

修复 #456
审核者: @alice

最佳实践

应做事项

  • 遵循Conventional Commits - 启用自动化
  • 写清晰消息 - 未来的你会感谢你
  • 引用问题 - 链接提交到工单
  • 一致使用范围 - 定义团队约定
  • 自动化发布 - 减少手动错误

不应做事项

  • 不混用更改 - 每个提交一个逻辑更改
  • 不跳过验证 - 使用commitlint
  • 不手动编辑 - 仅使用生成的变更日志
  • 不忘记破坏性更改 - 用!或页脚标记
  • 不忽略CI - 在管道中验证提交

资源