changelog

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Changelog Generator

更新日志生成器

This skill generates and maintains changelogs following the Keep a Changelog format, integrated with Conventional Commits and Semantic Versioning.
本技能遵循Keep a Changelog格式生成和维护更新日志,集成了Conventional Commits与Semantic Versioning规范。

Quick Start

快速开始

When invoked, analyze git history and generate/update the changelog:
bash
undefined
调用时将分析git历史并生成/更新更新日志:
bash
undefined

Get commits since last tag

Get commits since last tag

git log $(git describe --tags --abbrev=0 2>/dev/null || echo "")..HEAD --pretty=format:"%h %s" --no-merges
git log $(git describe --tags --abbrev=0 2>/dev/null || echo "")..HEAD --pretty=format:"%h %s" --no-merges

Get all tags for reference

Get all tags for reference

git tag --sort=-version:refname | head -10
undefined
git tag --sort=-version:refname | head -10
undefined

Changelog Format (Keep a Changelog)

更新日志格式(Keep a Changelog)

markdown
undefined
markdown
undefined

Changelog

Changelog

All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

[Unreleased]

Added

Added

  • New features
  • New features

Changed

Changed

  • Changes in existing functionality
  • Changes in existing functionality

Deprecated

Deprecated

  • Soon-to-be removed features
  • Soon-to-be removed features

Removed

Removed

  • Removed features
  • Removed features

Fixed

Fixed

  • Bug fixes
  • Bug fixes

Security

Security

  • Vulnerability fixes
  • Vulnerability fixes

[1.1.0] - 2024-01-26

[1.1.0] - 2024-01-26

Added

Added

  • New
    zustand-state
    skill for state management
  • New
    form-validation
    skill with Zod + Conform integration
  • New
    security-hardening
    skill for Shopify apps
  • New
    zustand-state
    skill for state management
  • New
    form-validation
    skill with Zod + Conform integration
  • New
    security-hardening
    skill for Shopify apps

Changed

Changed

  • Updated
    shopify-developer
    agent with new skills
  • Updated
    tech-lead
    agent with security-hardening skill
  • Updated
    shopify-developer
    agent with new skills
  • Updated
    tech-lead
    agent with security-hardening skill

[1.0.4] - 2024-01-20

[1.0.4] - 2024-01-20

Fixed

Fixed

  • Initial stable release
undefined
  • Initial stable release
undefined

Conventional Commits Mapping

Conventional Commits映射

Map commit prefixes to changelog categories:
Commit PrefixChangelog Category
feat:
Added
fix:
Fixed
docs:
Changed (Documentation)
style:
Changed (Formatting)
refactor:
Changed
perf:
Changed (Performance)
test:
(Usually omitted)
build:
Changed (Build system)
ci:
(Usually omitted)
chore:
(Usually omitted)
revert:
Removed or Fixed
security:
/
vuln:
Security
deprecate:
Deprecated
remove:
/
breaking:
Removed
将提交前缀映射到更新日志分类:
提交前缀更新日志分类
feat:
Added
fix:
Fixed
docs:
Changed (文档)
style:
Changed (格式)
refactor:
Changed
perf:
Changed (性能)
test:
(通常省略)
build:
Changed (构建系统)
ci:
(通常省略)
chore:
(通常省略)
revert:
RemovedFixed
security:
/
vuln:
Security
deprecate:
Deprecated
remove:
/
breaking:
Removed

Generation Process

生成流程

Step 1: Analyze Git History

步骤1:分析Git历史

bash
undefined
bash
undefined

Get commits since last release

Get commits since last release

git log v1.0.4..HEAD --pretty=format:"%H|%s|%an|%ad" --date=short
git log v1.0.4..HEAD --pretty=format:"%H|%s|%an|%ad" --date=short

Or since a specific date

Or since a specific date

git log --since="2024-01-01" --pretty=format:"%H|%s|%an|%ad" --date=short
undefined
git log --since="2024-01-01" --pretty=format:"%H|%s|%an|%ad" --date=short
undefined

Step 2: Categorize Changes

步骤2:变更分类

Parse each commit message and categorize:
typescript
interface ChangeEntry {
  category: 'Added' | 'Changed' | 'Deprecated' | 'Removed' | 'Fixed' | 'Security';
  description: string;
  commit: string;
  scope?: string;
  breaking?: boolean;
}

function categorizeCommit(message: string): ChangeEntry | null {
  const conventionalRegex = /^(\w+)(?:\(([^)]+)\))?(!)?:\s*(.+)$/;
  const match = message.match(conventionalRegex);

  if (!match) return null;

  const [, type, scope, breaking, description] = match;

  const categoryMap: Record<string, ChangeEntry['category']> = {
    feat: 'Added',
    fix: 'Fixed',
    docs: 'Changed',
    style: 'Changed',
    refactor: 'Changed',
    perf: 'Changed',
    security: 'Security',
    deprecate: 'Deprecated',
    remove: 'Removed',
  };

  return {
    category: categoryMap[type] || 'Changed',
    description,
    scope,
    breaking: !!breaking,
  };
}
解析每条提交信息并分类:
typescript
interface ChangeEntry {
  category: 'Added' | 'Changed' | 'Deprecated' | 'Removed' | 'Fixed' | 'Security';
  description: string;
  commit: string;
  scope?: string;
  breaking?: boolean;
}

function categorizeCommit(message: string): ChangeEntry | null {
  const conventionalRegex = /^(\w+)(?:\(([^)]+)\))?(!)?:\s*(.+)$/;
  const match = message.match(conventionalRegex);

  if (!match) return null;

  const [, type, scope, breaking, description] = match;

  const categoryMap: Record<string, ChangeEntry['category']> = {
    feat: 'Added',
    fix: 'Fixed',
    docs: 'Changed',
    style: 'Changed',
    refactor: 'Changed',
    perf: 'Changed',
    security: 'Security',
    deprecate: 'Deprecated',
    remove: 'Removed',
  };

  return {
    category: categoryMap[type] || 'Changed',
    description,
    scope,
    breaking: !!breaking,
  };
}

Step 3: Generate Markdown

步骤3:生成Markdown

typescript
function generateChangelog(entries: ChangeEntry[], version: string, date: string): string {
  const grouped = groupBy(entries, 'category');
  const order = ['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security'];

  let output = `## [${version}] - ${date}\n\n`;

  for (const category of order) {
    if (grouped[category]?.length) {
      output += `### ${category}\n`;
      for (const entry of grouped[category]) {
        const scope = entry.scope ? `**${entry.scope}:** ` : '';
        const breaking = entry.breaking ? '⚠️ BREAKING: ' : '';
        output += `- ${breaking}${scope}${entry.description}\n`;
      }
      output += '\n';
    }
  }

  return output;
}
typescript
function generateChangelog(entries: ChangeEntry[], version: string, date: string): string {
  const grouped = groupBy(entries, 'category');
  const order = ['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security'];

  let output = `## [${version}] - ${date}\n\n`;

  for (const category of order) {
    if (grouped[category]?.length) {
      output += `### ${category}\n`;
      for (const entry of grouped[category]) {
        const scope = entry.scope ? `**${entry.scope}:** ` : '';
        const breaking = entry.breaking ? '⚠️ BREAKING: ' : '';
        output += `- ${breaking}${scope}${entry.description}\n`;
      }
      output += '\n';
    }
  }

  return output;
}

Version Determination

版本判定

Based on changes, suggest version bump:
Change TypeVersion BumpExample
Breaking changes (
!
)
MAJOR1.0.0 → 2.0.0
New features (
feat
)
MINOR1.0.0 → 1.1.0
Bug fixes (
fix
)
PATCH1.0.0 → 1.0.1
Other changesPATCH1.0.0 → 1.0.1
typescript
function suggestVersionBump(entries: ChangeEntry[], currentVersion: string): string {
  const [major, minor, patch] = currentVersion.split('.').map(Number);

  if (entries.some(e => e.breaking)) {
    return `${major + 1}.0.0`;
  }
  if (entries.some(e => e.category === 'Added')) {
    return `${major}.${minor + 1}.0`;
  }
  return `${major}.${minor}.${patch + 1}`;
}
根据变更内容建议版本号升级规则:
变更类型版本升级幅度示例
破坏性变更 (
!
)
主版本(MAJOR)1.0.0 → 2.0.0
新功能 (
feat
)
次版本(MINOR)1.0.0 → 1.1.0
漏洞修复 (
fix
)
补丁版本(PATCH)1.0.0 → 1.0.1
其他变更补丁版本(PATCH)1.0.0 → 1.0.1
typescript
function suggestVersionBump(entries: ChangeEntry[], currentVersion: string): string {
  const [major, minor, patch] = currentVersion.split('.').map(Number);

  if (entries.some(e => e.breaking)) {
    return `${major + 1}.0.0`;
  }
  if (entries.some(e => e.category === 'Added')) {
    return `${major}.${minor + 1}.0`;
  }
  return `${major}.${minor}.${patch + 1}`;
}

Workflow Integration

工作流集成

Pre-release Workflow

预发布工作流

bash
undefined
bash
undefined

1. Generate changelog for unreleased changes

1. Generate changelog for unreleased changes

git log $(git describe --tags --abbrev=0)..HEAD --oneline
git log $(git describe --tags --abbrev=0)..HEAD --oneline

2. Update CHANGELOG.md with new version section

2. Update CHANGELOG.md with new version section

3. Commit changelog

3. Commit changelog

git add CHANGELOG.md git commit -m "docs: update changelog for v1.2.0"
git add CHANGELOG.md git commit -m "docs: update changelog for v1.2.0"

4. Create version tag

4. Create version tag

git tag -a v1.2.0 -m "Release v1.2.0"
git tag -a v1.2.0 -m "Release v1.2.0"

5. Push with tags

5. Push with tags

git push --follow-tags
undefined
git push --follow-tags
undefined

GitHub Release Integration

GitHub发布集成

Generate release notes for GitHub:
bash
undefined
为GitHub生成发布说明:
bash
undefined

Extract latest version section from CHANGELOG.md

Extract latest version section from CHANGELOG.md

sed -n '/^## [1.2.0]/,/^## [/p' CHANGELOG.md | head -n -1
sed -n '/^## [1.2.0]/,/^## [/p' CHANGELOG.md | head -n -1

Create GitHub release

Create GitHub release

gh release create v1.2.0 --title "v1.2.0" --notes-file release-notes.md
undefined
gh release create v1.2.0 --title "v1.2.0" --notes-file release-notes.md
undefined

Output Formats

输出格式

Markdown (Default)

Markdown(默认)

Standard Keep a Changelog format as shown above.
上文展示的标准Keep a Changelog格式。

JSON

JSON

json
{
  "version": "1.1.0",
  "date": "2024-01-26",
  "changes": {
    "added": [
      "New `zustand-state` skill for state management",
      "New `form-validation` skill with Zod + Conform integration"
    ],
    "changed": [
      "Updated `shopify-developer` agent with new skills"
    ],
    "fixed": [],
    "security": []
  }
}
json
{
  "version": "1.1.0",
  "date": "2024-01-26",
  "changes": {
    "added": [
      "New `zustand-state` skill for state management",
      "New `form-validation` skill with Zod + Conform integration"
    ],
    "changed": [
      "Updated `shopify-developer` agent with new skills"
    ],
    "fixed": [],
    "security": []
  }
}

Release Notes (Simplified)

简化版发布说明

markdown
undefined
markdown
undefined

Release v1.1.0

Release v1.1.0

Highlights

Highlights

  • 🎉 3 new skills added for better Shopify development
  • 🎉 3 new skills added for better Shopify development

What's New

What's New

  • zustand-state: State management with Zustand
  • form-validation: Form validation with Zod + Conform
  • security-hardening: Security best practices
  • zustand-state: State management with Zustand
  • form-validation: Form validation with Zod + Conform
  • security-hardening: Security best practices

Improvements

Improvements

  • Updated agents with new skill integrations

undefined
  • Updated agents with new skill integrations

undefined

Best Practices

最佳实践

DO

推荐做法

  • ✅ Write changelogs for humans, not machines
  • ✅ Use present tense ("Add feature" not "Added feature")
  • ✅ Group changes by type (Added, Changed, Fixed, etc.)
  • ✅ Include links to issues/PRs when relevant
  • ✅ Highlight breaking changes prominently
  • ✅ Keep entries concise but descriptive
  • ✅ 面向人类而非机器编写更新日志
  • ✅ 使用现在时(如"Add feature"而非"Added feature")
  • ✅ 按类型分组变更(新增、变更、修复等)
  • ✅ 相关场景下添加issue/PR链接
  • ✅ 突出展示破坏性变更
  • ✅ 保持条目简洁且描述清晰

DON'T

禁止做法

  • ❌ Include every single commit (filter noise)
  • ❌ Use technical jargon without explanation
  • ❌ Forget to update [Unreleased] section
  • ❌ Mix different versions in one section
  • ❌ Skip security-related changes
  • ❌ 包含所有提交记录(过滤无效信息)
  • ❌ 使用未解释的技术术语
  • ❌ 忘记更新[Unreleased]部分
  • ❌ 在同一个章节混合不同版本的内容
  • ❌ 遗漏安全相关变更

Commands Reference

命令参考

bash
undefined
bash
undefined

View commits since last tag

View commits since last tag

git log $(git describe --tags --abbrev=0)..HEAD --oneline
git log $(git describe --tags --abbrev=0)..HEAD --oneline

View commits between two tags

View commits between two tags

git log v1.0.0..v1.1.0 --oneline
git log v1.0.0..v1.1.0 --oneline

Get commit count by type

Get commit count by type

git log --oneline | grep -E "^[a-f0-9]+ (feat|fix|docs):" | wc -l
git log --oneline | grep -E "^[a-f0-9]+ (feat|fix|docs):" | wc -l

List all contributors since last release

List all contributors since last release

git log $(git describe --tags --abbrev=0)..HEAD --format="%an" | sort -u
git log $(git describe --tags --abbrev=0)..HEAD --format="%an" | sort -u

Generate commit list with dates

Generate commit list with dates

git log --since="2024-01-01" --pretty=format:"- %s (%ad)" --date=short
undefined
git log --since="2024-01-01" --pretty=format:"- %s (%ad)" --date=short
undefined

Example Invocations

调用示例

/changelog                    # Generate for unreleased changes
/changelog 1.2.0              # Generate for specific version
/changelog --since=v1.0.0     # Changes since specific tag
/changelog --format=json      # Output as JSON
/changelog                    # 生成未发布变更的更新日志
/changelog 1.2.0              # 生成指定版本的更新日志
/changelog --since=v1.0.0     # 生成指定标签之后的变更日志
/changelog --format=json      # 输出JSON格式的结果