standard-version で chore や doc をリリースノートに入れる方法

Conventional Commits にも参照がある chore や doc 形式のコミットメッセージが、standard-version でリリースノートに含まれないことが不満に思っていたけれど、昨日ようやくカスタマイズ方法を知ったので残しておきます。

結論

とりあえず楽したい人はプロジェクトルートに .versionrc.js の名前で以下を配置しておくと全て解決します。

module.exports = {
  preset: require.resolve('conventional-changelog-conventionalcommits'),
  types: [
    { type: 'feat', section: 'Features' },
    { type: 'fix', section: 'Bug Fixes' },
    { type: 'chore', section: 'Chores', hidden: false },
    { type: 'docs', section: 'Document Changes', hidden: false },
    { type: 'refactor', section: 'Refactoring', hidden: false },
    { type: 'test', section: 'Test Improvements', hidden: false }
  ]
}

chore でコミットしたい

bump up や何か軽微なソースコード以外の修正などがある場合に、chore でコミットメッセージを打ちたいケースはかなり頻繁にあります。

ただ、情報として必要なものも結構あるにもかかわらず standard-version はデフォルトで chore を出力してくれません。

ですが、なぜか standard-version 自身のコミットログには chore が使われており、また、それが CHANGELOG.md に反映されています。

ということで、カスタマイズすると恐らくは chore が使えるようになるはずなので見てみます。ちなみにあわせてドキュメントの更新もリリースノートに含めたいので、 doc / docs もサポートできることを目標とします。

standard-version のデフォルト挙動

standard-version はデフォルトの挙動を defaults.js に記述しています。とりあえずこれを追いながらカスタマイズ方法を模索してみます。

skip など普段 package.json で設定するような情報に加え、 dryRun や preset があることがわかります。ただ、これではまだルールがあまりつかめません。というのも、preset 側に設定が格納されているようであり、この defaults 自体には chore はおろか、 feat や fix の設定すらないからです。

// https://github.com/conventional-changelog/standard-version/blob/master/defaults.js#L3-L16
const spec = require('conventional-changelog-config-spec')

const defaults = {
  infile: 'CHANGELOG.md',
  firstRelease: false,
  sign: false,
  noVerify: false,
  commitAll: false,
  silent: false,
  tagPrefix: 'v',
  scripts: {},
  skip: {},
  dryRun: false,
  gitTagFallback: true,
  preset: require.resolve('conventional-changelog-conventionalcommits')
}

とはいえ準備自体はできそうなので、まずは以下のような .versionrc.js を作ります。

module.exports = {
  dryRun: true,
  preset: require.resolve('conventional-changelog-conventionalcommits')
}

あとはこの preset の中身を見るだけですが、 conventional-changelog-conventionalcommits パッケージに .versionrc 相当の設定があることを期待して見に行きましたが、結構コードが入り組んでいて本質的な定義に辿り着けそうにないので、 Spec そのものを見に行ってカスタマイズすることにします。

Conventional Changelog Configuration は、明確に conventional-changelog の Organization によってその Spec が定義されています。dryRun などは standard-version 由来の設定なので spec にはありませんが、 preset に関する情報はここに全て集約されているという認識で間違いありません。

最新版は以下のページにて閲覧可能です。

https://github.com/conventional-changelog/conventional-changelog-config-spec/blob/master/versions/2.1.0/README.md

読み進めていくと、そこに types というセクションがあり、以下のように記述されています。

// https://github.com/conventional-changelog/conventional-changelog-config-spec/blob/master/versions/2.1.0/README.md#types
"types": [
  {"type": "feat", "section": "Features"},
  {"type": "fix", "section": "Bug Fixes"},
  {"type": "chore", "hidden": true},
  {"type": "docs", "hidden": true},
  {"type": "style", "hidden": true},
  {"type": "refactor", "hidden": true},
  {"type": "perf", "hidden": true},
  {"type": "test", "hidden": true}
]

どうやら chore や doc 系のコメントが反映されないのは、この hidden オプションが有効になっていることが由来していそうです。type によって prefix によるカテゴリ分けをしながら、hidden で可視不可視を、section には可視状態の場合に CHANGELOG.md に h3 として出力されるセクション名が設定できる様子です。

これがわかったので、 .versionrc.js に反映すると、動作してくれるでしょう。ひとまず dryRun をオンにしつつ、動作を確認します。

module.exports = {
  dryRun: true,
  preset: require.resolve('conventional-changelog-conventionalcommits'),
  types: [
    { type: 'feat', section: 'Features' },
    { type: 'fix', section: 'Bug Fixes' },
    { type: 'chore', section: 'Chores', hidden: false },
    { type: 'docs', section: 'Document Changes', hidden: false },
    { type: 'refactor', section: 'Refactoring', hidden: false },
    { type: 'test', section: 'Test Improvements', hidden: false }
  ]
}

dryRun の結果、無事 Chores セクションと Document Changes セクションができていたので OK。最後に dryRun を外して完成。

module.exports = {
  dryRun: true,
  preset: require.resolve('conventional-changelog-conventionalcommits'),
  types: [
    { type: 'feat', section: 'Features' },
    { type: 'fix', section: 'Bug Fixes' },
    { type: 'chore', section: 'Chores', hidden: false },
    { type: 'docs', section: 'Document Changes', hidden: false },
    { type: 'refactor', section: 'Refactoring', hidden: false },
    { type: 'test', section: 'Test Improvements', hidden: false }
  ]
}

これまでこのカスタマイズを知らずにセクションが十分でない CHANGELOG を作ってきてしまったので、今管理しているパッケージもできればこれを順次適用していきたい。