30歳からのプログラミング

30歳無職から独学でプログラミングを開始した人間の記録。

standard-version と commitlint で npm パッケージのリリース管理を省力化する

standard-versionというライブラリを使うことで、リリース管理に伴う作業のいくつかを自動化できる。
具体的には以下の内容。

  • package.jsonversionフィールドの値の更新
  • CHANGELOG.mdの更新
  • 更新したpackage.jsonCHANGELOG.mdのコミット
  • Git のタグを打つ

これらを手作業で行うのは不毛だなと以前から思っていたので、standard-versionを導入した。

この記事ではstandard-versionの基本的な使い方を紹介する。
また、このライブラリを使うためにはコミットメッセージが重要になるので、コミットメッセージをチェックするためのcommitlintについても紹介する。

この記事を書くにあたり、以下のバージョンで動作確認をした。

  • standard-version@6.0.1
  • @commitlint/config-conventional@8.0.0
  • @commitlint/cli@8.0.0

standard-version を導入する

適当なプロジェクトを作って、standard-versionが何をしてくれるのかを見ていく。

空行だけのindex.txtと、以下の内容のpackage.jsonを用意する。

{
  "name": "sample",
  "version": "1.0.0",
  "scripts": {
    "release": "standard-version"
  },
  "devDependencies": {
    "standard-version": "^6.0.1"
  }
}

$ yarnしてstandard-versionをインストールした状態で、以下のようにコミットする。

$ git commit -m "feat: initial commit"

そして、$ yarn run release --first-releaseを実行する。

すると、以下の内容のCHANGELOG.mdが生成され、コミットされる。

# Changelog

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## 1.0.0 (2019-07-10)


### Features

* initial commit 03cbea8

さらに、直近のコミットに対してv1.0.0というタグが打たれている。
なので現時点でのコミット履歴は以下の通り。

8d5cd91 (HEAD -> master, tag: v1.0.0) chore(release): 1.0.0
03cbea8 feat: initial commit

さらにコミットを重ねるためにindex.txtを更新する。

diff --git a/index.txt b/index.txt
index e69de29..e2e3369 100644
--- a/index.txt
+++ b/index.txt
@@ -0,0 +1 @@
+patch のテスト。

コミットとreleaseを行う。

$ git commit -m "fix: update index.txt"
$ yarn run release

すると、CHANGELOG.mdpackage.jsonが更新され、コミットされる。

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8b6241..19a4565 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,15 @@
 
 All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-versio
n) for commit guidelines.
 
+### [1.0.1](///compare/v1.0.0...v1.0.1) (2019-07-10)
+
+
+### Bug Fixes
+
+* update index.txt f981c9c
+
+
+
 ## 1.0.0 (2019-07-10)
 
 
diff --git a/package.json b/package.json
index b2941ae..31a47e3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "sample",
-  "version": "1.0.0",
+  "version": "1.0.1",
   "scripts": {
     "release": "standard-version"
   },

タグも打たれ、コミット履歴は以下のようになる。

$ git log --oneline
15db18f (HEAD -> master, tag: v1.0.1) chore(release): 1.0.1
f981c9c fix: update index.txt
8d5cd91 (tag: v1.0.0) chore(release): 1.0.0
03cbea8 feat: initial commit

standard-version がやっていること

standard-versionを実行すると、以下の4つを行う。

  1. package.jsonのバージョンを更新する
  2. CHANGELOG.mdを更新する
  3. package.jsonCHANGELOG.mdをコミットする
  4. タグをつける

だが、--first-releaseオプションを付けると1のバージョンアップは行わず、現行のpackage.json#versionの値のまま2以降を行う。
そのため、CHANGELOG.mdを最初から作るときにのみ--first-releaseオプションを付け、二回目以降、あるいは既にCHANGELOG.mdが存在する場合は、このオプションは付けない。

バージョンアップと CHANGELOG.md 生成のルール

コミットメッセージに接頭辞をつけることで、その接頭辞に応じてバージョンアップが行われる。
例えばfeatはマイナーアップデート、fixはパッチアップデートになる。
また、feat!のように接頭辞の後ろにエクスクラメーションマークをつけると、それは破壊的変更を含むことを意味し、メジャーアップデートになる。
choredocsでコミットした内容はCHANGELOG.mdには反映されない。

そのため、上述のサンプルの続きとして次のようなコミットをして$ yarn run releaseすると、バージョンは2.0.0になる。
CHANGELOG.mdにはfe90828についてのみ記載され、choreである1f1e208については何も書かれない。

fe90828 feat!: new feature
1f1e208 chore: library install
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 19a4565..48f573b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,20 @@
 
 All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
 
+## [2.0.0](///compare/v1.0.1...v2.0.0) (2019-07-10)
+
+
+### Features
+
+* new feature fe90828
+
+
+### BREAKING CHANGES
+
+* new feature
+
+
+
 ### [1.0.1](///compare/v1.0.0...v1.0.1) (2019-07-10)

コミットのルールは Conventional Commits に準拠している。

www.conventionalcommits.org

Git のリモートリポジトリが登録されていれば、CHANGELOG.mdに記述されるコミット番号(上記のfe90828など)に、リモートリポジトリ上の当該コミットにリンクが張られる。

公式ドキュメントでは、プルリクエストのマージはSquash and Mergeで行うことを推奨している。
そうすると、CHANGELOG.mdの各項目に、当該プルリクエストへのリンクが自動的に生成される。

各種オプション

--dry-runオプション

--dry-runオプションをつけると、実際には何の変更も行うことなく、releaseしたときに何が行われるのかを確認することが出来る。

-tオプション

デフォルトでは、生成されるタグはバージョンにvという接頭辞がついたものになる。
この接頭辞は、-tオプションの引数で指定することが出来る。空文字を指定すれば(-t '')、接頭辞はつかずにバージョン番号のみのタグになる。

--release-asオプション

接頭辞に応じてバージョンアップしていくことは前述したが、--release-asオプションを使えば、次のバージョンを自分で指定することが出来る。

例として$ yarn run release --release-as 4.2.2 -t fooを実行すると、次のバージョンは4.2.2になり、foo4.2.2というタグが打たれる。

commitlint

standard-versionでのリリース管理は、コミットメッセージが重要になる。
コミットメッセージが正しくなければ上手く運用することは出来ない。

コミットメッセージが Conventional Commits に準拠しているか確認できるツールとして、commitlintがある。
commitlintはその名の通りコミットメッセージを対象とした Lint であり、コミットメッセージがルールに沿っているかチェックすることが出来る。この記事ではデフォルトのまま使うが、ルールの編集も当然行える。

ライブラリのインストールと、設定ファイルの出力を行う。

$ yarn add -D @commitlint/{config-conventional,cli}
$ echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

npm scripts"commitlint": "commitlint"を追加する。

$ yarn run commitlint --from=コミットIDを実行すると、指定したコミットののコミットから直近のコミットまでを、チェックする。

例えば、以下のようなコミットログになっているとする。

1d35a35 (HEAD -> master) feat: good commit 2
03b72d7 fix: good commit
b3cf4bc bad commit
a7eba0d feat: commitlint を導入した。

この状態で$ yarn run commitlint --from=b3cf4bcとすると、何もエラーは出ない。
$ yarn run commitlint --from=a7eba0dとすると、b3cf4bcもチェックの対象になり、エラーが出る。

⧗   input: bad commit
✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]

✖   found 2 problems, 0 warnings

コミットIDの代わりにタグを指定することも出来るし、--from=masterのようにブランチを指定することも可能。