github-release について
単一パッケージの GitHub リポジトリ向けリリース管理スキルです。`gh` と `git` で変更やタグを分析し、SemVer を提案して、変更履歴、リリースブランチ、プルリクエストを準備します。
主な機能
- 01リリース前の読み取り専用調査
- 02差分に基づく変更分類
- 03SemVer バージョンの提案
- 04変更履歴の作成と更新
- 05リリースブランチと PR の手順
活用シーン
- 01ライブラリリリース前の変更評価
- 02バージョン変更履歴とリリース PR の準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ github/ awesome-copilot --skill github-releaseインストール後、Claude Code で/github-releaseを入力して読み込まれたか確認します。
同梱ファイルreferences/semver-rules.mdreferences/commit-classification.md
詳細
GitHub リリーススキル
このスキルは、分析から変更履歴の作成、PR の作成まで、単一パッケージの GitHub リポジトリにおけるリリースワークフロー全体を自動化します。gh(GitHub CLI)と git のみを使用し、ほかのツールは必要ありません。
ステップ 1〜4 は読み取り専用の調査です。バージョン番号が確定するステップ 5 までは、リポジトリに何も書き込みません。
このスキルを使うタイミング
ユーザーが GitHub リポジトリの新しいリリースを作成する、新バージョンを公開する、バージョンを上げる、リリースブランチを作成する、変更履歴を生成する、またはリリース PR を開くことを希望した場合は、いつでもこのスキルを使ってください。「新しいバージョンを出しましょう」や「そろそろリリースしましょう」のような気軽な言い方の場合も実行します。
前提条件
以下の例には Bash と PowerShell の両方のバリエーションがあります。Windows ユーザーは PowerShell のブロックを使うことをおすすめします。
開始する前に、環境を確認してください。
gh auth status # must be authenticated
gh repo view --json nameWithOwner # must be inside a GitHub repo
git status # working tree should be clean
いずれかの確認に失敗した場合は、そこで中止し、続行する前に修正が必要な点をユーザーに伝えてください。
次に、ユーザーに次の質問を 1 つしてください。
「ライブラリの公開ソースコードが含まれているディレクトリはどこですか? (例:
src/、lib/、pkg/— 利用者が実際に目にする内容に絞って差分を確認するために使います。リポジトリ全体をスキャンする場合は Enter キーを押してください。)」
回答を PUBLIC_PATH として保存してください。回答が空の場合、PUBLIC_PATH は .(リポジトリのルート)です。次のパスは、すべての差分から除外してください:tests/、test/、spec/、__tests__/、docs/、*.lock、*-lock.json、*.sum、生成ファイル(「編集禁止」のヘッダーコメントがあるファイル)、ビルド成果物。
9 ステップのリリースワークフロー
すべてのステップを順番に進めてください。実行するコマンドとその出力をユーザーに見せてください。明示的に指示された場合のみ、一時停止して確認を求めてください。
ステップ 1 - main が最新であることを確認する
git checkout main
git pull origin main
ここでは main にとどまってください。バージョンが確定した後のステップ 5 でリリースブランチを作成します。
ステップ 2 - 最新のバージョンタグを取得する
なぜ
gh release listを使わないのですか? GitHub Releases は Git タグに追加できる任意の機能です。多くのリポジトリでは、GitHub Release を作成せずにgit tagでリリースにタグを付けているため、バージョンタグが存在していてもgh release listの結果が空になることがあります。Git からタグを直接読み取るのが、信頼できる情報源です。
# Fetch all tags from remote to ensure local view is current
git fetch --tags
# Find the latest version tag, sorted semantically
# --sort=-version:refname handles 1.10.0 > 1.9.0 correctly (unlike alphabetical)
PREV_TAG=$(git tag --sort=-version:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+' | head -1)
echo "Latest tag: $PREV_TAG"
# Fetch all tags from remote to ensure local view is current
git fetch --tags
# Find the latest version tag, sorted semantically
# --sort=-version:refname handles 1.10.0 > 1.9.0 correctly (unlike alphabetical)
$prevTag = git tag --sort='-version:refname' | `
Select-String '^[vV]?\d+\.\d+\.\d+' | `
Select-Object -First 1 -ExpandProperty Line
if ($prevTag) {
$prevSha = git rev-list -n 1 $prevTag
} else {
$prevSha = git rev-list --max-parents=0 HEAD
}
Write-Output "Latest tag: $prevTag"
次に、タグがローカルだけでなくリモートにも存在することを確認してください。
git ls-remote --tags origin | grep "refs/tags/$PREV_TAG$"
リモートの確認で何も返されない場合、そのタグはローカルにしかなく、プッシュされていないようだとユーザーに警告してください。続行する前にプッシュした方がよい場合があります。
PREV_TAGは、見つかったタグ名をそのまま設定します(例:v1.4.2)。計算時には先頭のvを取り除き、名前を付ける際にはそのまま残してください。- タグがまったく存在しない場合は、
PREV_TAGを(none)とし、PREV_SHAを最初のコミットに設定して、新しいバージョンの既定値を1.0.0にしてください(ステップ 4 のバージョン決定ロジックをスキップし、ステップ 5 に進んでください)。 - タグが実際のコミットを指していない場合(孤立タグ)は、
git rev-list --max-parents=0 HEADにフォールバックし、ユーザーに警告してください。
PREV_SHA=$(git rev-list -n 1 "$PREV_TAG" 2>/dev/null || git rev-list --max-parents=0 HEAD)
ステップ 3 - 前回のリリース以降の変更を分析する
このステップでは、相互に補完する 2 つの情報を使います。コードの差分を主な情報源とし、コミットメッセージから意図に関する補足情報を得ます。
3a - コード差分(主要なシグナル)
# Focused diff on the public source path, excluding noise
git diff "$PREV_SHA"..HEAD -- "$PUBLIC_PATH" \
':(exclude)tests/' ':(exclude)test/' ':(exclude)spec/' \
':(exclude)__tests__/' ':(exclude)docs/' \
':(exclude)*.lock' ':(exclude)*-lock.json' ':(exclude)*.sum'
# Focused diff on the public source path, excluding noise
git diff "$($prevSha)..HEAD" -- $publicPath `
':(exclude)tests/' ':(exclude)test/' ':(exclude)spec/' `
':(exclude)__tests__/' ':(exclude)docs/' `
':(exclude)*.lock' ':(exclude)*-lock.json' ':(exclude)*.sum'
差分の出力全体を読みます。変更されたファイルごとに、以下を特定します。
- 削除されたシンボル - 以前は存在していた関数、クラス、メソッド、定数、エクスポートされた名前が、現在は存在しないものです。これは MAJOR の強いシグナルです。
- シグネチャの変更 - 両方のバージョンに存在するものの、パラメーター、戻り値の型、またはスローされるエラーが異なる関数です。これは MAJOR の強いシグナルです。
- 新たにエクスポートされたシンボル - 以前は存在しなかった公開関数、クラス、定数です。これは MINOR のシグナルです。
- 内部のみの変更 - 公開インターフェースに触れない変更(プライベートヘルパー、エクスポートされていない関数、アルゴリズムの内部処理)です。これは PATCH です。
- バグ修正 - 公開 API を変更せずに、論理的に誤っていることが明らかな箇所(例:オフバイワン、null チェック、誤った条件)を修正するものです。これは PATCH です。
差分が非常に大きい(数千行)場合は、まず統計サマリーを実行して、詳細に読むファイルの優先順位を決めます。
git diff "$PREV_SHA"..HEAD --stat -- "$PUBLIC_PATH"
変更が最も多いファイルと、公開インターフェースを定義していると推測される名前のファイル(例:index.*、api.*、exports.*、public.*、mod.*、__init__.*)を重点的に読みます。
3b - コミットログ(二次的なシグナル)
git log "$PREV_SHA"..HEAD --oneline --no-merges
以下に活用します。
- 差分だけでは意図が明らかでないコード変更の背景を理解します(例:セキュリティ修正であることを示すラベルが付いた1行の変更)。
PUBLIC_PATH以外のパスにありながら、ユーザーに見える変更を見つけます(例:cmd/ディレクトリ内の CLI フラグの変更)。- コードだけでは全体像が分からない変更履歴の項目に、背景情報を補います。
変更メッセージのパターンを変更の種類に対応付ける方法については、references/commit-classification.md を参照してください。
3c - 2つのシグナルを照合する
シグナルが一致する場合は、その分類を確信を持って採用します。
シグナルが食い違う場合は、コード差分を優先します。例:
- コミットには
fix: typoとあるものの、差分で公開メソッドの削除が確認できる場合は、MAJOR として扱います。 - コミットには
feat: new APIとあるものの、差分がプライベートな内部処理にしか触れていない場合は、PATCH として扱います。 - コミットには
chore: refactorとあるものの、差分で新たなエクスポートされたシンボルが追加されている場合は、MINOR として扱います。
気づいた不一致は記録し、ステップ 6 の変更履歴レビュー時にユーザーに伝えます。
ステップ 4 - 次の SemVer バージョンを決定する
ステップ 3 の分析に次のルールを適用します(詳細なルールは references/semver-rules.md を参照してください)。
| 条件 | バージョン更新 |
|---|---|
| 公開 API に対する破壊的変更(削除、シグネチャの変更、動作の変更)がある | MAJOR |
| 破壊的変更を伴わない、新たなエクスポートされたシンボルまたは機能の追加 | MINOR |
| バグ修正、パフォーマンス改善、セキュリティ修正、ドキュメント、雑務のみ | PATCH |
複数の種類が含まれるリリースでは、最も優先度の高いものを採用します。
MAJOR > MINOR > PATCH。
NEXT_VERSION を計算します。
PREV_TAGをMAJOR.MINOR.PATCHの整数に分割します。- 該当するバージョン更新を適用します。
vMAJOR.MINOR.PATCHの形式にします。
提案するバージョンを、具体的なコード上の発見事項を挙げた簡潔な理由とともにユーザーに提示します。コミットメッセージだけを根拠にしないでください。例:
「v2.1.0 を提案します。差分では
src/client.goに2つの新しいエクスポート関数(NewClientとWithTimeout)が追加され、既存の公開シンボルの削除や変更はありません。コミットメッセージからも、これらが機能追加であることを確認できます。」
質問します:「このバージョンでよさそうですか? それとも変更しますか?」 続行する前に、確認を待ちます。
ステップ 5 - リリースブランチを作成する
バージョンが確定したので、最初から正しい名前でブランチを作成します。
git checkout -b release/vX.Y.Z
git push -u origin release/vX.Y.Z
Step 6 - CHANGELOG.md を更新
既存の CHANGELOG.md を読み込みます(存在しない場合は作成します)。Keep a Changelog 形式に厳密に従ってください。
挿入する構造(# Changelog ヘッダーの直下、先頭に挿入):
## [X.Y.Z] - YYYY-MM-DD
### Added
- ...
### Changed
- ...
### Deprecated
- ...
### Removed
- ...
### Fixed
- ...
### Security
- ...
ルール:
- 日付は本日の日付を
YYYY-MM-DD形式で使用します。 - エントリがないセクションは省略してください。空の見出しは残さないでください。
- エントリはユーザーの視点に立った平易な英語で記述してください。主にコード差分から読み取れる内容に基づき、コミットメッセージの文脈で補足します。
良い例: "Added
WithTimeoutoption to HTTP client constructor." 悪い例: "feat: add timeout cfg param" - 検出内容を以下のセクションに対応付けてください:
- 新しいエクスポートシンボル → Added
- 破壊的な削除 → Removed
- 既存 API への破壊的変更 → Changed(破壊的変更であることを明記)
- バグ・ロジックの修正、パフォーマンス改善 → Fixed
- セキュリティ修正 → Security
- 内部リファクタリング、ドキュメント、chore、テスト → ユーザーに影響がない限り省略
- コミットメッセージから、コード差分だけでは伝わらない意図が判明した場合(例: 1 行の変更に偽装されたセキュリティ修正)、その文脈を変更履歴のエントリに含めてください。
- ファイル末尾の差分リンクも更新してください:
[X.Y.Z]: https://github.com/OWNER/REPO/compare/vPREV...vNEXT
ディスクに書き込む前に、提案する変更履歴セクションをユーザーに提示してください。 ステップ 3c で何らかのシグナルの矛盾が見つかった場合は、ユーザーが確認できるようにここで明示してください。 次のように確認します: "Does this changelog look accurate? Any entries to add, remove, or reword?" (この変更履歴は正確ですか?追加、削除、または言い換えたいエントリはありますか?) フィードバックを反映してから、ディスクに書き込みます。
Step 7 - コミットとプッシュ
git add CHANGELOG.md
git commit -m "chore: release vX.Y.Z"
git push origin release/vX.Y.Z
次に進む前に、プッシュが成功したことを確認してください。
Step 8 - プルリクエストを作成
⚠️ IMPORTANT: PR の本文は必ず --body-file で渡してください。インラインテキストの --body は使用しないでください。
\n などのインラインエスケープシーケンスは PowerShell では改行として解釈されず、PR にそのまま文字列として表示されてしまいます。ファイルを使うことで Markdown の書式が正しく反映されます。
gh pr create \
--base main \
--head release/vX.Y.Z \
--title "Release vX.Y.Z" \
--body "$(cat <<'EOF'
## Release vX.Y.Z
This PR prepares the **vX.Y.Z** release.
### What's included
### Checklist
- [ ] Changelog reviewed
- [ ] Version bump verified
- [ ] CI passing
After merging, create the tag on the merge commit:
\`\`\`
git tag vX.Y.Z <merge-commit-sha>
git push origin vX.Y.Z
\`\`\`
EOF
)"
# Create PR body using here-string (preserves actual newlines, not escape sequences)
$prBody = @"
## Release vX.Y.Z
This PR prepares the **vX.Y.Z** release.
### What's included
<paste changelog here>
### Checklist
- [ ] Changelog reviewed
- [ ] Version bump verified
- [ ] CI passing
After merging, create the tag on the merge commit:
```
git tag vX.Y.Z <merge-commit-sha>
git push origin vX.Y.Z
```
"@
# Write to file and use --body-file (do NOT use inline --body with escape sequences)
$prBody | Out-File -FilePath release_pr_body.md -Encoding utf8 -NoNewline
gh pr create --base main --head release/vX.Y.Z --title "Release vX.Y.Z" --body-file release_pr_body.md
変更履歴のセクションを PR 本文の "What's included" ブロックに貼り付けてください(手動レビュー用にプレースホルダーのままにしておくことも可能です)。
Step 9 - ユーザーへの引き継ぎ
ユーザーに次のように伝えてください:
リリース PR を作成しました! ??
新しいバージョン: vX.Y.Z
PR がレビューされマージされたら、マージコミット上でタグを自分で作成する必要があります:
git tag vX.Y.Z <merge-commit-sha> git push origin vX.Y.Zその後、GitHub Releases に移動し、そのタグからリリースを公開してください。変更履歴のセクションはリリースノートにそのままコピーできます。
エラーハンドリング
| 状況 | 対応 |
|---|---|
gh auth status が失敗する | 処理を中止し、gh auth login を実行するようユーザーに伝える |
| git リポジトリ内にいない | 処理を中止し、リポジトリへ cd するようユーザーに伝える |
| 作業ツリーに未コミットの変更がある | 警告し、stash するか中止するかをユーザーに確認する |
| 前回のタグ以降にコミットがない | リリースするものがないことをユーザーに伝える |
| タグは存在するがどのコミットも指していない | 最初のコミットを差分の基点として使用し、ユーザーに警告する |
| 最新のタグはローカルに存在するがリモートにはない | 警告し、先にタグをプッシュするか、そのまま続行するかをユーザーに確認する |
PUBLIC_PATH の差分は空だがコミットは存在する | 警告する。すべての変更が内部向けの可能性があるため、それでも続行するかをユーザーに確認する |
git push が失敗する(例: 保護されたブランチのルール) | エラーをそのまま報告し、ブランチ保護の設定を確認するよう提案する |
PowerShell でのトラブルシューティング
- ローカルでは動作するコマンドが gh の使用方法を表示したり、サブコマンドを別のトークンとして扱ったりする場合は、PATH 上の gh.exe が呼び出されていることを確認してください(
Get-Command gh)。また、展開されていないネストされた置換を渡さないようにし、上記の PowerShell のパターンを使用してください。 - 推奨されるテスト:
gh --version、git fetch --tags、そして PowerShell スニペットを実行して$prevTagを設定し、git diff --name-only $prevSha..HEAD -- src/を実行する。
制限事項
ghCLI がインストールされ、認証済みである必要があります。- 現在のバージョンを特定するために git タグが必要です。
参照ファイル
references/semver-rules.md- 拡張された SemVer の判断ルールとエッジケースreferences/commit-classification.md- コミットメッセージを変更の種類に分類するためのヒューリスティクス