「手動のバージョニング」という悪夢
Gitログを確認してCHANGELOGを作成するだけで、何時間も費やしたことはありませんか?私は以前、修正内容が機能追加(feature)なのかバグ修正(fix)なのかを確認し、package.jsonのバージョンを手動で書き換え、変更点を一行ずつ入力するという疲れるループに陥っていました。ほんの少し注意を怠るだけで、バージョンの更新を忘れたり、重要なコミットを見落としたりしてしまいます。
かつて、バージョンを更新せずにコードをプロダクション環境にデプロイしてしまったことがありました。モニタリングシステムが古いバージョンのエラーを報告し、同僚は新機能が反映されているのか分からず混乱してしまいました。その失敗の後、私はすべてを自動化することに決めました。semantic-releaseこそが、1回のリリースにつき少なくとも15〜20分の時間を節約してくれる解決策でした。
semantic-releaseの仕組み
このツールは**Conventional Commits**(規則的なコミットメッセージ)に基づいて、次のバージョン番号を自動的に決定します。Major、Minor、Patchのどれを選択するかを手動で判断する必要はありません。
ルールは非常にシンプルです。fix: ...を使用すればPatchバージョンが上がります。feat: ...を使用すればMinorバージョンが上がります。特に、BREAKING CHANGEというキーワードが含まれている場合、システムは自動的にMajorバージョンへジャンプします。すべてがコンピュータ의ロジックに従って正確に行われます。
必要なパッケージのインストール
まず、プラグインをdevDependenciesにインストールします。以下は、Node.js環境で私がよく使用するツールセットです:
npm install --save-dev semantic-release @semantic-release/changelog @semantic-release/git @semantic-release/github @semantic-release/npm
各プラグインにはそれぞれ特定の役割があります:
- commit-analyzer: コミット履歴を分析して新しいバージョンを決定します。
- release-notes-generator: CHANGELOGの内容を自動的に生成します。
- changelog: 変更内容を
CHANGELOG.mdファイルに書き込みます。 - git: 更新されたファイルをリポジトリに自動的にコミットします。
- github: タグとリリースノートを添えてGitHub Releaseを作成します。
実戦的な .releaserc の設定
私は設定を一元管理するために.releasercファイルを使用しています。これは実際のプロジェクトで適用している設定テンプレートです:
{
"branches": ["main", "master"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md"
}
],
"@semantic-release/npm",
[
"@semantic-release/git",
{
"assets": ["package.json", "package-lock.json", "CHANGELOG.md"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
"@semantic-release/github"
]
}
重要な注意点: メッセージ内の[skip ci]というフレーズは、無限のCI/CDループを避けるのに役立ちます。これがないと、ボットによるコミットが再びパイプラインをトリガーし続け、リソースの無駄遣いやシステムのハングアップを引き起こす可能性があります。
GitHub Actionsへの統合
semantic-releaseの真の力は自動パイプラインにあります。.github/workflows/release.ymlファイルを以下の内容で作成してください:
name: Release
on:
push:
branches:
- main
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 'lts/*'
- run: npm ci
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-release
GITHUB_TOKEN変数はあらかじめ用意されています。ただし、パッケージをnpmに公開したい場合は、SecretsにNPM_TOKENを追加する必要があります。内部プロジェクトの場合は、プラグイン設定で"npmPublish": falseに設定してください。
デプロイ前の確認
コードをマージする前に、ドライラン(dry-run)モードで実行してログを確認することをお勧めします:
npx semantic-release --dry-run
このコマンドを使用すると、実際のファイル変更やタグ作成を行わずに、次のバージョンが何になるかを正確に把握できます。すべて問題なければ、git pushするだけで、あとはパイプラインが処理してくれます。
その結果、GitHub上にプロフェッショナルな**Releases**ページが作成されます。同僚はあなたに質問することなく、一目で変更内容を把握できるようになります。
実践から得られた教訓
一つ目は、fix: update codeやfeat: 作業完了といった投げやりなコミットの習慣を捨てることです。こうした無意味な文章はCHANGELOGにそのまま表示され、クライアントに対するプロジェクトの信頼を損なうことになります。
二つ目は、チーム開発において**Squash and Merge**を優先することです。これにより、メインブランチの履歴に入る前に、コミットメッセージを最終的に整えることができます。
最後は、commitlintとhuskyを導入することです。このペアは、開発者のローカル環境で規格外のコミットを阻止し、プロセスが常にスムーズに動作することを保証します。
semantic-releaseを導入することは、手間を省くだけでなく、プロフェッショナルなワークフローを構築することにもつながります。機械は人間よりも反復作業を正確に行うことができます。そのメリットを活用しない手はないでしょう。

