こんにちは! N Inc.でフロントエンドの開発に参加している五十嵐(@thegodofneet)です。みなさんはデプロイフロー、整えていますか?
main ブランチに push したら CI/CD が走って本番環境にデプロイ…というユースケースはよく耳にするかもしれませんが、インフラや DX のレイヤーの話で、私みたいなアプリケーションエンジニアには縁のない話。そう思うかもしれません。
しかし、先日 npm モジュールを GitHub Packages に公開する必要を迫られやむなく「semantic-release」という CLI ツールを試してみたところ、任意のブランチに push したらレジストリに公開されるというフローを簡単にセットアップできたのみならず、勝手にメジャーバージョンかマイナーバージョンかを判定してくれたり、モジュールの更新履歴を記した CHANGELOG.md を自動で生成して tag を切ってくれたりと大変体験がよかったためシェアしようと思います。
この記事では
- semantic-release の機能説明とセットアップの方法
- GitHub Actions から npmjs.com レジストリに公開する方法
- 設定のカスタマイズと CHANGELOG の生成方法
を解説します。
semantic-release でできること
semantic-release は Node.js 向けの完全自動の バージョン管理 & パッケージ公開ツール です。Conventional Commits というコミットメッセージのルールに基づいて記述された変更点を元に、 Semantic Versioning というバージョン番号の仕様に基づいてバージョン管理を行います。
例えば現在のバージョンが 1.0.0
だとしましょう。新機能を追加した際にはコミットメッセージを:
git commit -m "feat: 新機能Aの追加"
のように feat:
で始めれば、次のリリース時に 1.1.0
のように 2 桁目が更新されます。他にも バグ修正 を行った際は fix:
で 1.0.1
のように 3 桁目を、破壊的変更 を行った際は BREAKING CHANGE:
で 2.0.0
のように 1 桁目の数字を自動的にインクリメントしてくれます。
このコミットの記述方法とバージョン管理方法は Electron や Angular でも採用されており、ライブラリ開発者はもちろん、利用者側も変更点がわかりやすく package.json とも相性が良いです。
semantic-release のインストール
semantic-release は npm の公式レジストリで公開されており、下記のコマンドでインストールできます。
yarn install semantic-release
--help
でヘルプを表示してインストールされていることが確認できます
yarn run semantic-release --help
設定ファイルの作成
インストールが完了したら、 semantic-release を利用するために、リリースを行えるブランチを設定します。このツールは Babel や ESlint のように .releaserc
または release.config.js
というファイルを package.json
と同じディレクトリに作成するか、 package.json
自体に release
というフィールドを作成することで設定の記述が行なえます。
// release.config.js
{
branches: ["main"];
}
上記内容でファイルを作成すると main
ブランチで semantic-release の利用が可能になります。試しに yarn run semantic-release
と実行してみましょう。
無事プラグインが読み込まれ、コミットメッセージを解析しているのがわかると思います。 デフォルトではローカル環境ではパッケージは公開されず、 GitHub Actions や Circle CI といった CI 環境でのみパッケージが公開されるようになっており、それ以外の場合はドライラン扱いになるので安心して試すことができます。
GitHub Actions で自動リリースの設定
semantic-release 自体は単なる CLI ツールのため、どこかにホストしなければパッケージ公開を自動化することはできません。この記事では GitHub Actions を用いた設定の方法を紹介します。
はじめに、パッケージをレジストリに公開するための設定をします。 package.json と同じディレクトリに .npmrc
という名前で下記の内容のファイルを作成してください。
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
このファイルは npm CLI での環境設定や認証情報を設定するファイルで、ここでは npm 公式レジストリ registry.npmjs.org でのアクセストークンとして NPM_TOKEN
という環境変数を利用する旨を設定しました。
続いて、この環境変数を CI 上で代入するための設定を行います。まず npmjs.org の設定画面 にアクセスし、新しいトークンを生成します。
自分の npmjs.com アカウントのトークンが取得できたら、次はトークンを GitHub 上に渡します。 Settings > Secrets > New Repository Secret からトークンをシークレットとして登録すると、GitHub Actions 上で実行されるジョブから secrets.<シークレット名>
として設定した値を利用できるようになります。ここでは先程 .npmrc
に設定した NPM_TOKEN
と同じ名前にします。
.npmrc
ではわざわざ環境変数を利用しなくても文字列を直書きすることが可能ですが、オープンソースとして公開されている場合や、ソースコードが流出した際のリスクを考えると、このようにサービス上からのみ利用できるように設定しておくのが安全です。
これでパッケージを公開するための認証ができるようになったので、次は GitHub Actions のワークフローを登録します。 package.json と同じディレクトリに .github/workflows
というディレクトリを作成し、そのディレクトリ内に任意の名前で Yaml ファイルを作成します。
name: Publish
on:
push:
branches:
- master # -- (1)
jobs:
build:
runs-on: ubuntu-latest
env:
NPM_TOKEN: ${{secrets.NPM_TOKEN}} # -- (2)
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn run semantic-release # -- (3)
注意点は下記の 3 つです。
on.push.branches
に自動リリースを行いたいブランチを記述します。前節で書いた設定ファイル.releaserc
と同じブランチである必要があります。- semantic-release CLI を実行するジョブ内で
.npmrc
で展開するためにシークレットsecrets.NPM_TOKEN
を環境変数NPM_TOKEN
として渡します。 - 最後に semantic-release CLI を実行します。バンドルのビルドやテストを実行した後に行われているかを確認してください。
作成したファイルを push すると、 GitHub リポジトリ上の Actions タブ内に Publish という名前でワークフローが作成され、 master に新しいコミットが push されたときにそれまでのコミットメッセージに対して semantic-release が実行されるようになりました。
加えて、 on
をカスタマイズすることでトリガーのタイミングを変更することが可能です。例えば 毎日 0 時に最新のコミットをビルドして配信したい という場合は、下記のように schedule というイベントを使うことで毎晩定期的に実行することができます:
#...
on:
schedule:
- cron: "0 0 * * *"
semantic-release は常に最後のリリースから最新のコミットまでの差分を検出し必要なときにだけリリースを行うため、昨晩から変更がない場合は無駄にリリースされることはありません。
設定のカスタマイズ
.releaserc
では先ほど紹介した 利用可能なブランチの他にも、ブランチごとのタグの設定や、利用するプラグインの設定が行えるようになっていて、デフォルトでは下記の設定が有効になっています。
キー | 説明 | デフォルト値 |
---|---|---|
branches |
リリースを行う対象になるブランチ | ["master", "next"] |
plugins |
利用するプラグイン一覧 | ['@semantic-release/commit-analyzer', '@semantic-release/release-notes-generator', '@semantic-release/npm', '@semantic-release/github'] |
branches
の設定
安定版とプレビュー版を並行してリリースしている開発環境ではブランチごとにリリースやバージョンアップの方針を変更する必要があると思います。実は semantic-release ではデフォルトで登録されているブランチ名に限ってちょうどよい設定が割り当てられています。
ブランチ名 | 説明 |
---|---|
master |
普通のリリースが行われる |
next |
next タグ(NPM の機能)にリリースされ、npm install foo@next のようにしてインストールできる。チーム内でテストする際などに使える |
next-major |
next タグと同じ。メジャーリリースとパッチで開発ブランチを分けている人用。 |
beta |
beta タグにリリースされ、npm install foo@beta のようにしてインストールできるようになる。 |
alpha |
alpha タグにリリースされ、npm install foo@alpha のようにしてインストールできるようになる。 |
さらに、実は branch キーは文字列だけでなくオブジェクトを渡すことができ、ブランチ名に対して対象となるリリースタグや対応する本番ブランチが設定できるようになっています。
// release.config.js
{
branches: [
"master",
// 'develop' ブランチを モジュール名@next として公開
{ name: "develop", channel: "next" },
];
}
この設定を利用すれば git-flow のようなブランチ名の管理設定にしていても、対応するブランチに push すれば自動てタグ付きでレジストリに公開することができ、実際にそのような設定をしてくれるプラグインもあります。
CHANGELOG の生成
デフォルトでは commit-analyzer
、 release-notes-generator
、 npm
、 github
の 4 つのプラグインが有効になっており、これだけでもコミットから差分を検知して npm や GitHub に公開することが可能です。
もしリポジトリ上のファイルからパッケージの更新履歴を調べたい場合は、別途プラグインを導入することで Conventional Commit に基づいた CHANGELOG.md
を自動生成することが可能です。下記コマンドで changelog
と git
プラグインをインストールできます。
yarn add --dev @semantic-release/changelog @semantic-release/git
追加したプラグインはそれぞれ以下の役割があります。
- @semantic-release/changelog: コミットログから自動的に CHANGELOG.md を生成するためのプラグインです。
- @semantic-release/git: リリースフローが実行された後に変更があったファイルをコミットして origin に push するプラグインです。 CHANGELOG.md のほかに、 package.json の version フィールドをコミットするためにも使われます。
つぎに、設定ファイルでプラグインを読み込みます。ファイルの plugins
にプラグイン名を追加します。
// release.config.js
{
branches: [/* ... */],
plugins: [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/github",
"@semantic-release/git"
]
}
設定ファイルをコミットして対象のブランチでリリースをトリガーすると、次のリリースから CHANGELOG が生成されるようになり、リリースノートに書かれるのと同等な内容が CHANGELOG.md に出力され、リポジトリにコミットされるようになりました。
まとめ
この記事では semantic-release の機能説明と GitHub Actions との連携方法、設定のカスタマイズ方法とプラグインの解説をしました。
最近は Dependabot のような Semantic Versioning を活用した依存パッケージの自動更新ツールも登場しており、バージョンの数字を規則的に更新することの重要性が以前より更に増してきています。バージョンを正しく管理することで利用者にとって使いやすいライブラリになることは言うまでもありません。ぜひ semantic-release を活用して、堅牢なデプロイフローを構築してみてください!