この記事は、弁護士ドットコム Advent Calendarの17日目の記事です。
この記事で伝えたいこと
- GitHub Actions とsemantic-releaseで、自動で高品質npmパッケージをリリースできます
- 使う人も作る人も簡単にメンテナンスできるようことが大事
- textlint ルールを npm パッケージとして OSS 公開
誰でも使いやすいパッケージとは何か
使いやすいパッケージとは、大きく下記の4つがあげられます。
- セマンティックバージョンで変更内容とバージョンが紐づいてわかりやすい
- リリース頻度が多く機能追加、バグ修正に素早く対応している
- リリースノートが正しく書かれて、変更内容が瞬時に把握できる
- テストがあり、動作が担保されている。
パッケージの中身も当然大事です。ですがいくら中身が良くても一般公開時にこれらが欠けると、使いづらくなってしまいます。
変更内容を見てリリースノート作って、バージョンを決めるのは大変
セマンティックバージョンで毎回整合性が担保できていますか?何をリリースしたか確認して、必要な変更だけリリースノート書けていますか?
これらを愚直に手動で実現するのは大変です。
作業が増えるほど、リリースのハードルがあがます。デザイナーさんも簡単にリリースできるようにするなど、夢のまた夢です。
パッケージ公開までのフローを設計する
可能な限り作業を自動化する前提で考えます。手動での介入を最小限にすることで、ミスを減らし、運用コストを削減できます。
npmパッケージリリース支援ライブラリ
よく使われるふたつのライブラリがあります。今回は自動化前提なのでsemantic-release
を採用しました。
semantic-release
CI で実行&完全に自動化することが前提のライブラリです。
新しいリリースをメンテナやユーザに通知したり、コミットメッセージを使用してコードベースの変更を文書化できます。
マージに基づいて、 Git タグうち&npm などで公開できます。
standard-version
バージョン管理、変更ログの生成、および Git タグ付けを処理してくれます。コミットメッセージの分解は同じです。
大きく違うのはローカルで動かす前提で、リモート反映はしないこと。またnpm のパッケージ公開までは対応してません。
コミットメッセージとバージョン
commit メッセージ
コミットメッセージはAngular のコミットメッセージフォーマットに従います。
これによりコミットメッセージを解析して、自動でバージョンが決まりCHANGELOG.mdが更新されます。
<種別>: <具体的な変更内容>
例
fix: 日本語の副詞「と」のルールを修正
バージョン
デフォルトのcommit時の種別とバージョンの対応は下記です。設定を変更すれば、オリジナルの種別を追加できます。
種別 | 内容 | マージリリース | バージョン |
---|---|---|---|
feat | 新しい機能 | 〇 | Miner Release |
fix | バグ修正&軽微な修正 | 〇 | Patch Release |
perf | コードのパフォーマンス修正 | 〇 | Patch Release |
BREAKING CHANGE | 互換性のない破壊的変更 | 〇 | Major Release |
etc.. |
コミッター全員がコミットメッセージ綺麗するのが必須?
GitHubにはマージ方法が 3 種類あります。
- Create a merge commit
- フィーチャブランチからのすべてのコミットがマージコミット内でベースブランチに追加されます。
- Rebase and merge
- トピックブランチ(あるいはheadブランチ)のすべてのコミットが、マージコミットなしに個別にベースブランチに追加されます。
- Squash and merge
- そのプルリクエストのコミットは1つのコミットにsquashされます。
Squash and merge
を使い、マージする際にメンテナーが Squash して commit メッセージを加工するのが良いでしょう。そうすれば、全てのコミッターがコミットメッセージを完璧にする必要はないです。
万が一ルールに沿っていなくても、無視されるので影響はありません。
semantic-releaseの設定
package.json
に使うプラグインとブランチを指定します。
今回は、commit解析によるCHAGELOG.md&リリースノートの作成、GitHubを使ったGitでのタグうちと差分のcommitまで行います。
"release": {
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/github",
"@semantic-release/git"
],
"branches": [
"main"
]
}
処理のイメージは下記のようになります。
ステップ | 説明 |
---|---|
条件の確認 | すべての条件を確認して、条件があっているか確認します。 |
最後のリリースを取得 | 分析して、最後のリリースに対応するコミットを取得します。 |
コミットの分析 | 前回のリリース以降に追加されたコミットに基づいて、リリースのタイプを決定します。 |
リリースを確認する | リリースの適合性を確認します。 |
メモを生成する | 前回のリリース以降に追加されたコミットのリリースノートを生成します。 |
Gitタグを作成する | 新しいリリースバージョンに対応するGitタグを作成します。 |
準備 | リリースを準備します。 |
公開 | リリースを公開します。 |
通知する | 新しいリリースまたはエラーを通知します。 |
GitHub Action Workflowで自動化
npmのリリースのためにNPM_TOKEN
にnpmのアクセストークンをGitHubのレポジトリのSECRETS
に設定しておきます。GitHubの操作も行いますが、自動でGITHUB_TOKEN
という名前のGitHubアクセストークンが設定されているので対応不要です。
GitHub Actions のワークフローは、Test と Release のふたつを想定します。
こちらは、Release用のワークフローです。起動条件にTestの成功を指定し、テストが通った時だけ起動します。
name: Release
on:
workflow_run:
workflows:
- Test
branches:
- main
types:
- completed
jobs:
release:
name: Release
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup NodeJS 14
uses: actions/setup-node@v2
with:
node-version: 14
- name: Install dependencies
run: npm ci
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-release
リリースの流れ
プルリクエストのマージからまとめるとこうなります。
- プルリクエストをマージ
- Test ワークフロー
- テスト実行
- Release ワークフロー
- Test が無事に終わっていたらトリガー
- Git タグを解析して、最後のリリースに該当するコミットを取得
- 前回のリリース以降に追加されたコミットをもとに、リリースの種類を決定
- リリースの適合性を確認
- 前回のリリース以降に追加されたコミットのリリースノートを作成
- 新しいリリースバージョンに対応する Git タグを作成
- npm package リリース
- 新しいリリースやエラーを通知
このフローで公開しているtextlintルールパッケージ
実際に上記のワークフローを使いtextlintのルールをnpmで公開しました。
弁コムサービス内の文字校正のレビューコストが高くなってました。ルールの数が増えると、レビューに時間がかかります。レビュアーによっても指摘内容が異なり、レビューの難易度もあがります。
そのためMarkdown などのテキストファイルを特定のルールにしたがってチェックするtextlintを導入しました。Slackをインターフェイスにして、裏側でtextlintの上記のルールを使ったAPIが動いてます。
一緒に作ったデザイナーさんの記事もあるので、ぜひ見てください。
まとめ
GitHub Actions & semantic-version での自動リリースは非常に便利なので、楽に高品質なパッケージを公開しましょう。
使う人も作る人にも優しいOSSの提供を目指します。