conventional-changelog-cliでCHANGELOGを自動生成してみる
メンテしているプロダクトのリリースノートやCHANGELOGを毎回作成していると、「自動化できないものか・・・」という気持ちになります。そしてだんだん雑な内容になり、みんなが使いにくい俺得ライブラリになってさらにちゃんと […]
目次
メンテしているプロダクトのリリースノートやCHANGELOGを毎回作成していると、「自動化できないものか・・・」という気持ちになります。そしてだんだん雑な内容になり、みんなが使いにくい俺得ライブラリになってさらにちゃんとドキュメントを書かないという悪循環へ・・・
最近Conventional Commitでコミットメッセージを書いていれば、よしなにしてくれるツールがある様子であることを知ったので、早速試してみました。
事前準備: GitでConventional Commitを2〜3回実行する
「コミット内容からCHANGELOGを作成する」というツールを使うため、一度Conventional Commitでコミットログを残しておきましょう。
この記事では、以下のコミットを事前に実行しました。
$ git commit -m "feat: create a new function to say hello world
> 
> BREAKING CHANGE: `default export` will be a function"
$ git commit -m "feat: add new props
> 
> hello('John') => 'Hello World. Welcome John'"
$ git commit -m "fix: add space"
Step1: conventional-changelog-cliのインストール
コミット履歴からCHANGELOGを作成できるCLIツールです。
$ npm init -y
$ yarn add -D conventional-changelog-cli
$ ./node_modules/.bin/conventional-changelog --help
  Generate a changelog from git metadata
  Usage
    conventional-changelog
  Example
    conventional-changelog -i CHANGELOG.md --same-file
  Options
    -i, --infile              Read the CHANGELOG from this file
    -o, --outfile             Write the CHANGELOG to this file
                              If unspecified, it prints to stdout
    -s, --same-file           Outputting to the infile so you don't need to specify the same file as outfile
    -p, --preset              Name of the preset you want to use. Must be one of the following:
                              angular, atom, codemirror, ember, eslint, express, jquery, jscs or jshint
    -k, --pkg                 A filepath of where your package.json is located
                              Default is the closest package.json from cwd
    -a, --append              Should the newer release be appended to the older release
                              Default: false
    -r, --release-count       How many releases to be generated from the latest
                              If 0, the whole changelog will be regenerated and the outfile will be overwritten
                              Default: 1
    -u, --output-unreleased   Output unreleased changelog
    -v, --verbose             Verbose output. Use this for debugging
                              Default: false
    -n, --config              A filepath of your config script
                              Example of a config script: https://github.com/conventional-changelog/conventional-changelog-angular/blob/master/index.js
    -c, --context             A filepath of a json that is used to define template variables
    -l, --lerna-package       Generate a changelog for a specific lerna package (:[email protected])
    -t, --tag-prefix          Tag prefix to consider when reading the tags
    --commit-path             Generate a changelog scoped to a specific directory
Step2: CLIでCHANGELOGを作成する
converntional-changelog-cliを使うことで、コミットメッセージからCHANGELOGを作成できます。今回の例ですと、このように出力されます。
$ ./node_modules/.bin/conventional-changelog -p angular
# 1.0.0 (2019-09-02)
### Bug Fixes
* add space b5eb664
### Features
* add new props 7b25dbf
* create a new function to say hello world 7fd039f
### BREAKING CHANGES
* will be a function
-pオプションでCHANGELOGのフォーマットを指定できます。先程のはAngularでしたが、ESLintにするとこのように変わります。
$ ./node_modules/.bin/conventional-changelog -p eslint
# 1.0.0 (2019-09-02)
### feat
* add new props 7b25dbf6a5d44132c90eeb412596491c00d09102
* create a new function to say hello world 7fd039fb4fc664a15088e7b990ce56e6092ca4df
### fix
* add space b5eb664b79cbf529f6b2f31ee60977e95a1e8c84
このままだと標準出力に表示されたメッセージを自分で入力する必要がありますが、以下のように書くことで保存できます。
$ ./node_modules/.bin/conventional-changelog -p eslint -i CHANGELOG.md -s
$ cat CHANGELOG.md
# 1.0.0 (2019-09-02)
### feat
* add new props 7b25dbf6a5d44132c90eeb412596491c00d09102
* create a new function to say hello world 7fd039fb4fc664a15088e7b990ce56e6092ca4df
### fix
* add space b5eb664b79cbf529f6b2f31ee60977e95a1e8c84
Step3: npm versionでCHANGELOGを生成する
npmで配布するライブラリなどでは、npm version -> npm publish でバージョンアップ-> 公開します。厳密にはいろいろなやり方があると思いますが、細かい部分については省略します。
この場合、npm versionを実行したタイミングでgit tagも実行されます。
git tagが実行されたタイミングでCHANGELOGを作成すると、おそらく適切なタイミングでログを出せるのではないかと思いましたので、試してみました。
package.jsonにコマンドを追加する
以下のように変更しました。
{
  "name": "convential-commit-test",
  "version": "1.1.1",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "postversion": "npm run changelog",
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'update changelog'"
  },
postversionはnpm versionでpackage.jsonのversionとgit tagのバージョンが更新されたあとに実行されるコマンドです。ここでnpm run changelogを実行し、CHANGELOG.mdを更新させています。
preversionも存在しますが、バージョンが変わる前にCHANGELOG.mdが生成されるため手でCHANGELOG.mdのバージョン番号を修正する必要があります。
npm versionでCHANGELOGを生成する
あとはnpm versionを実行するだけです。
$ npm version patch
v1.1.1
> [email protected] postversion /Users/sandbox/test/convential-commit-test
> npm run changelog
> [email protected] changelog /Users/sandbox/test/convential-commit-test
> conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'update changelog'
[master c7c0321] update changelog
 1 file changed, 10 insertions(+), 1 deletion(-)
CHANGELOG.mdはこのように更新されました。
## [1.1.1](/compare/v1.1.0...v1.1.1) (2019-09-02)
### Bug Fixes
* move CHANGELOG creation timing (pre -> post) 372f899
# [1.1.0](/compare/7fd039f...v1.1.0) (2019-09-02)
### Bug Fixes
* add space b5eb664
### Features
* add new props 7b25dbf
* create a new function to say hello world 7fd039f
### BREAKING CHANGES
* will be a function
おわりに
今回はnpm versionでしたが、Circle CIなどのCIツール側で実行するようにすれば、「masterマージでCHANGELOG生成」のようなプロダクトの運用よりな使い方もできそうです。