gen-release-notes について
指定したタグ以降の変更から、Keep a Changelog形式のリリースノートを作成するスキルです。変更の分析と分類、バージョン提案、CHANGELOGの更新、比較リンクの検証を案内します。
主な機能
- 01前のタグ以降の変更収集
- 02Keep a Changelogに沿った分類
- 03Semantic Versioningのバージョン提案
- 04CHANGELOG.mdの更新手順
- 05比較リンクのフッター検証
活用シーン
- 01タグ付きリリースのノート作成
- 02ユーザーへの影響に基づく変更整理
- 03リリースバージョンの提案
- 04changelog比較リンクの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ existential-birds/ beagle --skill gen-release-notesインストール後、Claude Code で/gen-release-notesを入力して読み込まれたか確認します。
詳細
リリースノートジェネレーター
Keep a Changelog の標準に従って、プロフェッショナルなリリースノートを生成します。
入力:前のタグ(例:v0.0.1)
$ARGUMENTS
リリースノートを生成する前に、変更内容を十分に分析してください。
ゲート
タグ、PR 番号、リンクを捏造しないでください。各行の条件を満たしてから、それに依存する作業に進んでください。
| タイミング | 合格条件(証拠) | 不合格の場合 |
|---|---|---|
git log/git diff の実行前 | git tag -l "$PREV_TAG" が PREV_TAG と一致する行をちょうど 1 行出力する | 停止し、タグが見つからないことを報告してください。変更履歴のエントリーは書かないでください |
| カテゴリー分けの前 | git rev-parse "$PREV_TAG^{commit}" が終了コード 0 で終了する | 停止し、PREV_TAG またはリポジトリのチェックアウトを修正してください |
gh pr list を使用する場合 | コマンドが終了コード 0 で終了し、JSON が有効である | コミットの件名とマージコミットの URL のみを使用してください。PR 番号を捏造しないでください |
| ステップ 5 のフッター編集後 | ステップ 6 のフッターゲートが終了コード 0 で終了する(ステージされた CHANGELOG.md に対する両方の grep -q チェックが成功する) | ステップ 5 のフッター編集をやり直してから、終了コード 0 で終了するまでステップ 6 を再実行してください |
ステップ 1:変更を収集する
指定されたタグ以降の変更に関する情報を収集するため、次のコマンドを実行してください。
# Store the previous tag
PREV_TAG="$ARGUMENTS"
# Gate: tag must exist (output must be non-empty and match PREV_TAG)
git tag -l "$PREV_TAG"
# If the line above prints nothing, STOP — do not continue below.
# Get the repo URL for PR links
git remote get-url origin
# List commits since last tag
git log ${PREV_TAG}..HEAD --pretty=format:"%h %s" --no-merges
# Get detailed diff stats
git diff ${PREV_TAG}..HEAD --stat
# List changed files by directory
git diff ${PREV_TAG}..HEAD --name-only | sort | uniq
PR 情報も収集してください。
# Get merged PRs since the tag (requires gh CLI)
gh pr list --state merged --search "merged:>=$(git log -1 --format=%ci $PREV_TAG | cut -d' ' -f1)" --json number,title,author,labels
ステップ 2:分析してカテゴリー分けする
各変更を、次のカテゴリーのいずれか 1 つだけに、記載順に分類してください。
| カテゴリー | 含めるもの | 除外するもの |
|---|---|---|
| 追加 | 新機能、新しい公開 API、新しい CLI コマンド | ユーザーに公開されない内部ユーティリティ |
| 変更 | 動作の変更、パフォーマンスの向上、ユーザーに影響する依存関係の更新 | 動作の変更を伴わないリファクタリング |
| 非推奨 | 将来の削除が告知された機能 | - |
| 削除 | 機能の削除、公開 API の削除 | 内部コードの削除 |
| 修正 | バグ修正、エラー処理の改善 | テストのみの修正 |
| セキュリティ | 脆弱性の修正、セキュリティ強化 | - |
完全に除外するもの:
- CI/CD 設定の変更(ユーザーに影響する場合を除く)
- ドキュメントのみの変更(新機能を明らかにする場合を除く)
- コードスタイル/フォーマットの変更
- テストのみの変更
- ユーザーから見える影響のない内部リファクタリング
- マージコミット
ステップ 3:バージョン番号を決定する
変更内容に基づき、セマンティックバージョニングに従って次のバージョンを提案してください。
- メジャー(X.0.0):公開 API の破壊的変更
- マイナー(x.Y.0):後方互換性のある新機能
- パッチ(x.y.Z):バグ修正のみ
既存のタグから、v プレフィックスの有無を含めたタグ形式を判定してください。
ステップ 4:リリースノートを作成する
次の正確な形式を使って CHANGELOG.md のエントリーを生成してください。
## [VERSION] - YYYY-MM-DD
### Added
- **scope:** Add new feature description ([#54](REPO_URL/pull/54))
### Changed
- **Breaking:** Rename `oldName()` to `newName()` for consistency ([#145](REPO_URL/pull/145))
**Migration:** Replace all calls to `oldName()` with `newName()`.
### Deprecated
- **scope:** Deprecate `legacy_function()` in favor of `new_function()` ([#143](REPO_URL/pull/143))
### Removed
- **Breaking:** Remove deprecated `old_function()` ([#141](REPO_URL/pull/141))
### Fixed
- **scope:** Fix race condition when multiple workers access shared state ([#139](REPO_URL/pull/139))
### Security
- **deps:** Update vulnerable package to patched version ([#49](REPO_URL/pull/49))
執筆ルール
形式の要件:
- すべてのエントリーは命令形の動詞で始めてください:追加、修正、削除、更新、改善、名称変更、非推奨化、パッチ適用
- スコープのプレフィックスがある場合は太字で含めてください:
**server:**、**cli:**、**api:** - 変更ごとに 1 行にしてください(破壊的変更を除く。破壊的変更には移行手順を記載します)
- 行末に PR/Issue へのリンクを含めてください
- 各カテゴリー内では重要度の高い順にエントリーを並べてください
- 空のカテゴリーは省略してください
破壊的変更:
- 太字の
**Breaking:**を先頭に付けてください - 各カテゴリー内の最初に記載してください
- 次の行に
**Migration:**ブロックを追加し、ユーザーが変更すべき内容を具体的に説明してください - API シグネチャの変更には変更前と変更後のコード例を含めてください
トーン:
- メンテナーではなく、ライブラリの利用者に向けて書いてください
- 実装方法ではなく、ユーザーにとって何が変わったかに焦点を当ててください
- 具体的に書き、「さまざまな改善」や「バグ修正」といった表現は避けてください
- 各エントリーは、PR を読まなくても理解できる内容にしてください
避けるべき悪い例:
# BAD - Too vague
- Fixed bugs
- Performance improvements
- Updated dependencies
# BAD - Implementation-focused
- Refactored the internal state machine to use async/await
# BAD - Missing context
- Fixed #234
参考にすべき良い例:
# GOOD - Specific and user-focused
- **server:** Fix timeout errors when processing files larger than 100MB ([#234](URL))
- **cli:** Add `--dry-run` flag to preview changes before execution ([#235](URL))
- **api:** Improve cold-start latency from 2.3s to 0.8s by lazy-loading plugins ([#236](URL))
ステップ 5:CHANGELOG.md を更新する
-
CHANGELOG.mdが存在する場合:## [Unreleased]セクションの後に新しいバージョンを挿入します(Unreleased がない場合は先頭に挿入します)。
-
CHANGELOG.mdが存在しない場合は、次のヘッダーを付けて作成します:
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
-
ファイル末尾のフッター参照リンクを更新します。 この手順は必須です。これらがないと、CodeRabbit などのレビュアーから、変更履歴が不完全だと指摘されます。次の 2 つを編集する必要があります。
a.
[Unreleased]を更新し、以前のバージョンではなく新しいバージョンと比較するようにします。 b.[Unreleased]のすぐ下に、以前のタグと新しいタグを比較する新しい[NEW_VERSION]行を挿入します。例の差分(
3.1.0の後に3.2.0をリリースする場合):-[Unreleased]: https://github.com/OWNER/REPO/compare/v3.1.0...HEAD +[Unreleased]: https://github.com/OWNER/REPO/compare/v3.2.0...HEAD +[3.2.0]: https://github.com/OWNER/REPO/compare/v3.1.0...v3.2.0 [3.1.0]: https://github.com/OWNER/REPO/compare/v3.0.0...v3.1.0編集後、ステップ 6 を実行して、両方のフッター行が存在し、正しいことを確認します。ステップ 6 は省略しないでください。これは、「比較リンクのフッターがない」という繰り返し発生するレビュアーからの指摘を防ぐための必須ゲートです。
ステップ 6:CHANGELOG のフッター比較リンクを確認する(必須ゲート)
これは、フッター比較リンクの適用ゲートです。gen-release-notes が成功を報告する前、およびリリースワークフローのコミット手順の前に実行する必要があります。参考情報ではありません。両方の grep -q チェックが終了コード 0 で終了しなければ、ゲートは不足している行を特定して失敗します。
次のブロックをそのまま実行します:
# Read the staged CHANGELOG.md blob (index), not the working tree, so unstaged
# edits cannot make the gate pass when the commit would actually fail.
STAGED_CHANGELOG=$(git show :CHANGELOG.md)
# Extract NEW and PREV versions from the staged CHANGELOG.md.
# We only match numeric `## [X.Y.Z]` headings so `## [Unreleased]` is skipped.
NEW_VERSION=$(printf '%s\n' "$STAGED_CHANGELOG" | grep -m1 -E '^## \[[0-9]+\.[0-9]+\.[0-9]+\]' | sed -E 's/^## \[([0-9]+\.[0-9]+\.[0-9]+)\].*/\1/')
PREV_VERSION=$(printf '%s\n' "$STAGED_CHANGELOG" | grep -m2 -E '^## \[[0-9]+\.[0-9]+\.[0-9]+\]' | sed -n '2p' | sed -E 's/^## \[([0-9]+\.[0-9]+\.[0-9]+)\].*/\1/')
if [ -z "$NEW_VERSION" ] || [ -z "$PREV_VERSION" ]; then
echo "GATE FAIL: could not extract NEW_VERSION ($NEW_VERSION) or PREV_VERSION ($PREV_VERSION) from staged CHANGELOG.md"
exit 1
fi
# Infer optional tag prefix (`v` or empty) from the existing [Unreleased] footer.
# Step 3 explicitly allows tags with or without `v`; never hardcode `v` here.
# Fall back to `v` only when no [Unreleased] footer exists yet (first release).
TAG_PREFIX=$(printf '%s\n' "$STAGED_CHANGELOG" | sed -nE 's|^\[Unreleased\]: .*/compare/(v?)[0-9]+\.[0-9]+\.[0-9]+\.\.\.HEAD$|\1|p' | head -1)
if ! printf '%s\n' "$STAGED_CHANGELOG" | grep -qE '^\[Unreleased\]:'; then
TAG_PREFIX="v"
fi
echo "Gating footer compare links: NEW=${TAG_PREFIX}${NEW_VERSION}, PREV=${TAG_PREFIX}${PREV_VERSION}"
# Escape dots so they match literally inside the regex.
NEW_RE=${NEW_VERSION//./\\.}
PREV_RE=${PREV_VERSION//./\\.}
# Check 1: the new [NEW_VERSION] footer line exists and points PREV->NEW.
printf '%s\n' "$STAGED_CHANGELOG" | grep -qE "^\[${NEW_RE}\]: .*compare/${TAG_PREFIX}${PREV_RE}\.\.\.${TAG_PREFIX}${NEW_RE}\$" \
|| { echo "GATE FAIL: missing footer line: [${NEW_VERSION}]: .../compare/${TAG_PREFIX}${PREV_VERSION}...${TAG_PREFIX}${NEW_VERSION}"; exit 1; }
# Check 2: the [Unreleased] footer line is advanced to compare from the new tag.
printf '%s\n' "$STAGED_CHANGELOG" | grep -qE "^\[Unreleased\]: .*compare/${TAG_PREFIX}${NEW_RE}\.\.\.HEAD\$" \
|| { echo "GATE FAIL: [Unreleased] is not advanced; expected: [Unreleased]: .../compare/${TAG_PREFIX}${NEW_VERSION}...HEAD"; exit 1; }
echo "Footer compare links verified: [${NEW_VERSION}] and [Unreleased] both present and correct."
合格条件(客観的): 上記の両方の grep -q の実行が、ステージング済みの CHANGELOG.md に対して終了コード 0 で終了すること。ブロックが Footer compare links verified: ... を出力し、終了コード 0 で終了する必要があります。
失敗した場合: ゲートが不足している行または誤った行を特定します。ステップ 5 に戻り、CHANGELOG.md を編集してその行を追加または修正してから、このブロックを再実行します。このブロックが終了コード 0 で終了するまで、ステップ 7 に進んだり、成功を報告したりしないでください。
ステップ 7:概要を出力する
変更履歴を更新した後、次の内容を提示します:
- 推奨するバージョン番号とその根拠
- カテゴリ別の変更概要
- 特別な注意が必要な破壊的変更
- CHANGELOG.md を更新したことの確認
Conventional Commits のマッピング
コミットの接頭辞を変更履歴のカテゴリに対応付けます:
| コミットの接頭辞 | 変更履歴のカテゴリ |
|---|---|
feat(scope): | 追加 |
feat!(scope): | 追加(Breaking の接頭辞付き) |
fix(scope): | 修正 |
perf(scope): | 変更 |
security(scope): | セキュリティ |
docs:, chore:, ci:, test:, style: | 除外 |