Gitタグ駆動リリースの実装 - CLIツールの継続的デリバリー
RedmineCLIで実践したGitタグ駆動の自動リリースシステム。GitHub Actionsを使って、タグを打つだけでマルチプラットフォーム対応バイナリを配布する仕組みの構築方法。
はじめに
「v0.8.1」とタグを打つ。 たったそれだけで、Windows、macOS、Linuxの各プラットフォーム向けバイナリが自動的にビルドされ、GitHubのリリースページに公開される。
手動でのビルドやアップロードは一切不要。 これが、Gitタグ駆動リリースの世界です。
今回は、RedmineCLIで実装した自動リリースシステムについて、その設計思想と実装の詳細を共有します。
なぜタグ駆動なのか
従来のリリースフローの問題
以前は、リリースのたびに以下の作業を手動で行っていました。
- 各プラットフォーム向けにビルド
- バイナリをZIPに圧縮
- GitHubのリリースページを作成
- ファイルを1つずつアップロード
- リリースノートを記載
- チェックサムを計算して追記
5つのプラットフォームに対応すると、この作業だけで30分以上かかります。 しかも、ファイル名を間違えたり、アップロードし忘れたり、ヒューマンエラーのリスクも高い。
Gitタグという自然な節目
Gitタグは、そもそもリリースポイントを示すために存在します。 だったら、タグを打つ行為とリリース作業を直結させるのが自然ではないでしょうか。
# これだけでリリース完了
git tag v0.8.1
git push origin v0.8.1
この2つのコマンドで、すべてが自動的に進行します。
実装の全体像
GitHub Actionsワークフローの構成
リリースワークフローは、3つのジョブで構成されています。
- create-release: リリースの作成
- build-and-release: 各プラットフォームでのビルドとアップロード
- generate-checksums: チェックサムファイルの生成
name: Release
on:
push:
tags:
- 'v*'
jobs:
create-release:
# リリースを作成
build-and-release:
# 5つのプラットフォームで並列ビルド
generate-checksums:
# 最後にチェックサムを生成
タグからバージョンを抽出
タグ名からバージョン番号を抽出する処理は、OSによって微妙に異なります。
# Unix系
- name: Extract version from tag (Unix)
if: runner.os != 'Windows'
id: extract_version_unix
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
# Windows
- name: Extract version from tag (Windows)
if: runner.os == 'Windows'
id: extract_version_windows
shell: pwsh
run: |
$VERSION = "${{ github.ref_name }}".TrimStart('v')
echo "version=$VERSION" >> $env:GITHUB_OUTPUT
v0.8.1
というタグから0.8.1
というバージョン番号を抽出しています。
プレリリースの自動判定
GitHub Actionsでは、バージョン番号に基づいて自動的にプレリリースを判定できます。
- name: Create Release
uses: softprops/action-gh-release@v2
with:
prerelease: ${{ contains(steps.extract_version.outputs.version, '-') }}
バージョンに-
が含まれる場合(例:v0.8.2-beta
、v1.0.0-rc1
)は自動的にプレリリースとして扱われます。
これにより、正式版とベータ版を明確に区別できます。
配布ファイルの命名規則
一貫性の重要性
配布ファイルの命名規則は、最初にしっかりと決めておく必要があります。 後から変更すると、パッケージマネージャーの設定変更が必要になるからです。
redmine-cli-{version}-{platform}.zip
例
redmine-cli-0.8.1-win-x64.zip
redmine-cli-0.8.1-osx-arm64.zip
redmine-cli-0.8.1-linux-x64.zip
プラットフォーム識別子の統一
strategy:
matrix:
config:
- name: "Windows x64"
os: windows-latest
rid: win-x64
output: redmine.exe
- name: "macOS ARM64"
os: macos-latest
rid: osx-arm64
output: redmine
Runtime Identifier (RID)をそのままファイル名に使用することで、一貫性を保っています。
.NETのバージョニング戦略
動的バージョン指定
ビルド時にタグから抽出したバージョンを動的に設定します。
- name: Publish Native AOT
run: |
dotnet publish RedmineCLI/RedmineCLI.csproj \
-c Release \
-r ${{ matrix.config.rid }} \
-p:PublishAot=true \
-p:StripSymbols=true \
-p:Version=${{ steps.extract_version.outputs.version }} \
-p:IncludeSourceRevisionInInformationalVersion=false
開発ビルドとの使い分け
csprojファイルにはデフォルトバージョンを設定しておきます。
<PropertyGroup>
<Version>0.1.0</Version>
</PropertyGroup>
開発中のビルドでは、このバージョンにコミットハッシュが付加されます。
0.1.0+243a42fff1b8121e722042217735a13662b78eec
リリースビルドでは、タグから取得したクリーンなバージョン番号になります。
0.8.1
マルチプラットフォーム並列ビルド
マトリックスビルドの活用
5つのプラットフォームを並列でビルドすることで、リリース時間を大幅に短縮しています。
strategy:
matrix:
config:
- name: "Windows x64"
os: windows-latest
rid: win-x64
- name: "macOS x64"
os: macos-latest
rid: osx-x64
- name: "macOS ARM64"
os: macos-latest
rid: osx-arm64
- name: "Linux x64"
os: ubuntu-latest
rid: linux-x64
- name: "Linux ARM64"
os: ubuntu-24.04-arm
rid: linux-arm64
各プラットフォームで独立してビルドが実行され、完了次第リリースにアップロードされます。
リリースノートの自動生成
Claude Codeを活用したリリースノート作成
RedmineCLIでは、前のバージョンとの差分から自動的にリリースノートを生成しています。 実際のワークフローでは、gitのログとClaude Codeを使って、意味のあるリリースノートを作成します。
# 前のタグからの変更を取得
git log $PREVIOUS_TAG..HEAD --pretty=format:"- %s"
このコミット履歴をClaude Codeに渡して、以下のような整理されたリリースノートを生成します。
- 新機能の追加
- バグフィックス
- パフォーマンスの改善
- 破壊的変更の明記
人間が書くような自然な文章で、技術的な詳細を含みながらも読みやすいリリースノートが自動生成されます。
リリース検証の自動化
チェックサムの自動生成
すべてのバイナリがアップロードされた後、チェックサムファイルを自動生成します。
- name: Generate checksums
run: |
cd downloads
sha256sum *.zip > ../redmine-cli-${{ steps.extract_version.outputs.version }}-checksums.txt
ユーザーは、このファイルでダウンロードしたバイナリの整合性を確認できます。
リリース後の動作確認
実際にリリースされたバイナリをダウンロードして動作確認する方法。
# GitHub CLIでダウンロード
gh release download v0.8.1 --pattern "*osx-arm64*"
# 解凍して実行
unzip redmine-cli-0.8.1-osx-arm64.zip
./redmine --version
# 出力: 0.8.1
得られた効果
リリース時間の短縮
手動作業で時間がかかっていたリリース作業が、タグを打つだけで完了。 実際のビルドとアップロードは数分で完了します。
ヒューマンエラーの排除
- ファイル名の間違い:命名規則が自動適用される
- アップロード忘れ:すべて自動化
- バージョンの不整合:タグから自動取得
頻繁なリリースが可能に
リリース作業の心理的負担がなくなったことで、小さな改善も積極的にリリースできるようになりました。 バグ修正やマイナーアップデートを、ユーザーに素早く届けられます。
まとめ
Gitタグ駆動リリースは、CLIツール開発において非常に効果的なアプローチです。
実装のポイント
- 命名規則を最初に決める: 後から変更は困難
- バージョニング戦略を明確に: 開発ビルドとリリースビルドの区別
- 並列処理を活用: マトリックスビルドで時間短縮
- 検証も自動化: チェックサムの生成まで含める
今後の展望
現在は、パッケージマネージャーの更新はまだ半自動です。 将来的には、これも完全自動化したいと考えています。
タグを打つだけですべてが完了する。 それが、理想的な継続的デリバリーの姿です。