目次

1. 初めに

変更履歴(例:CHANGELOG.md)を作成する際はコミットログを見ながら手作業でまとめていましたが、 当初はそこまで多くはなかったので問題はありませんでした。

しかし最近少し多くなってきたため、手作業での作成だとそもそもやるのが億劫になってきました。 そこで変更履歴を自動生成できたら嬉しいなと思ってググったところ、コミットログに基づいて自動生成できるツールがありました。

本記事ではConventional Commits(下記参照)と呼ばれるコミットメッセージの規約に従ったコミットログに基づいて、 変更履歴を自動生成するツールを調査したので紹介します。

また、Conventional CommitsはフロントエンドWebアプリケーションフレームワークである Angularの規約(下記参照)をベースにした規約です。

なお、調査結果の詳細を読みたくない方は下記リンクへジャンプしてください。

2. 変更履歴自動生成ツールの一覧

まずはConventional Commits(下記参照)で紹介されており、開発言語TOP10(下記参照)や個人的に気になっている開発言語を対象に、 変更履歴自動生成の機能が提供されているツールを一覧化したいと思います。 その際にGitHubリポジトリの開発言語とStar数(2023/03/29)を記載します。

No ツール名 開発言語 Star数 URL 備考
  (開発言語TOP10)        
01 conventional-changelog/conventional-changelog-cli JavaScript 6.9k URL  
02 semantic-release/semantic-release-cli JavaScript 342 URL semantic-releaseのCLI版
03 semantic-release/semantic-release JavaScript 17.6k URL semantic-release-cliの本体
04 commitizen-tools/commitizen Python 1.5k URL  
05 python-semantic-release/python-semantic-release Python 553 URL  
06 jgoodman8/pyhist Python 18 URL  
07 tomasbjerre/git-changelog-command-line Java 36 URL git-changelog-libのCLI版
08 tomasbjerre/git-changelog-lib Java 172 URL git-changelog-command-lineの本体
09 marcocesarato/php-conventional-changelog PHP 168 URL  
10 adamtabrams/change Shell 61 URL  
  (個人的に気になっている開発言語)        
11 goreleaser/chglog Go 213 URL  
12 leodido/go-conventionalcommits Go 53 URL  
13 bvieira/sv4git Go 53 URL  
14 gembaadvantage/uplift Go 39 URL  
15 joselitofilho/go-conventional-commits Go 10 URL  
16 PSanetra/git-semver Go 11 URL  
17 cocogitto/cocogitto Rust 355 URL  
18 chaaz/versio Rust 69 URL  

Star数が伸びていないリポジトリもありますが、変更履歴を出力する機能は全てのリポジトリで実装されているみたいなので、 興味のある方は採用してみても良いかもしれません。

また余談ですが、どんなリポジトリでもドキュメントがあるのとないのでは理解するための敷居が全然違うので、 ドキュメントはやはり大切ですね。

3. 変更履歴自動生成ツールの動作確認

次に前章で紹介したツールのサンプルを作成してみます。 ただし、ツールで何ができるのかを理解することが目的のため、 基本的には自身の開発環境(Python 3.10)に適しているツールのみを対象とします。 サンプルを作成したツール以外に関してはドキュメントの確認のみ行っています。

3.1. No.04: commitizen-tools/commitizen

1つ目のツールは、Pythonで実装されたツールです。

3.1.1. インストール方法

まずはpoetry(パッケージ管理ツール)をインストールします。

$ python3 --version
Python 3.10.10

$ pipx install poetry
(省略)

$ poetry --version
Poetry (version 1.4.1)

$ poetry config virtualenvs.in-project true

次にcommitizenをインストールします。

$ cd workspace/Git/python/changelog-sample

$ poetry add commitizen --group dev
(省略)

$ poetry show commitizen
 name         : commitizen                    
 version      : 2.42.1                        
 description  : Python commitizen client tool 

dependencies
 - argcomplete >=1.12.1,<2.1
 - charset-normalizer >=2.1.0,<3.0.0
 - colorama >=0.4.1,<0.5.0
 - decli >=0.5.2,<0.6.0
 - jinja2 >=2.10.3
 - packaging >=19
 - pyyaml >=3.08
 - questionary >=1.4.0,<2.0.0
 - termcolor >=1.1,<3
 - tomlkit >=0.5.3,<1.0.0
 - typing-extensions >=4.0.1,<5.0.0

required by
 - commitizen-cz-custom-commits ^2.42.1

3.1.2. ツール実行ログ

次にツールを実行する前のコミットログを確認します。 これに基づいて変更履歴が自動生成されます。

$ git log --oneline
19d8b3d (HEAD -> main, origin/main, origin/HEAD) build: create exe env of automatic changelog generator
5cc9ed9 feat: update a feature for the user # L3: BREAKING CHANGE: make incompatible change to existing features
3b677aa chore: do chores excluding those mentioned above
3b11de7 docs: add documents
c8265c7 ci: add CI configuration files and scripts
1aa34ef build: add the build system and external dependencies
6a74576 test: add tests
d15450e perf: improve performance
2fb93e6 refactor: improve code (without changing external behavior)
85d2dd2 style: apply a format style (without affecting the meaning of the code)
4064860 fix: fix a bug for the user
b9131c5 feat: add a feature for the user
6da62b4 (tag: v0.0.0) Initial commit

次にcommitizenを実行します。 バージョンはコミットログに基づいて自動計算されます。

$ poetry run cz bump
chore: bump from 0.0.0 to 1.0.0
tag to create: v1.0.0
increment detected: MAJOR

tags in full_changelog: ['v1.0.0', 'v0.0.0']

[main 95a1fa6] chore: bump from 0.0.0 to 1.0.0
 2 files changed, 25 insertions(+), 2 deletions(-)

Done!

補足事項として、実行する前にpyproject.tomlがプロジェクトルートに配置されている必要があります。

詳細

$ cat pyproject.toml
[tool.poetry]
name = "changelog-sample"
version = "0.0.0"
description = "changelog sample"
authors = ["xxx"]
license = "MIT"
readme = "README.md"
packages = [
    {include = "changelog_sample", from = "src"}
]

[tool.poetry.build]
generate-setup-file = false

[tool.poetry.dependencies]
python = "^3.10"

[tool.poetry.group.dev.dependencies]
commitizen = "^2.42.1"
commitizen-cz-custom-commits = {path = "../commitizen-cz-custom-commits", develop = true}

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.commitizen]
name = "cz_custom_commits" # コミットルール名(デフォルト:cz_conventional_commits)
version = "0.0.0"
version_files = [
    "pyproject.toml:version"
]
tag_format = "v$version"
update_changelog_on_bump = true
bump_message = "chore: bump from $current_version to $new_version"
changelog_file = "CHANGELOG_cz.md"
# major_version_zero = true # for initial development
github_repo_owner = "<GitHubアカウントID>"
github_repo_name = "changelog-sample"

3.1.3. ツールヘルプ

参考までにツールのヘルプを載せておきます。

詳細

$ poetry run cz --help
usage: cz [-h] [--debug] [-n NAME] [-nr NO_RAISE] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ...

Commitizen is a cli tool to generate conventional commits.
For more information about the topic go to https://conventionalcommits.org/

options:
  -h, --help            show this help message and exit
  --debug               use debug mode
  -n NAME, --name NAME  use the given commitizen (default: cz_conventional_commits)
  -nr NO_RAISE, --no-raise NO_RAISE
                        comma separated error codes that will not rise error, e.g: cz -nr 1,2,3 bump. See codes at https://commitizen-tools.github.io/commitizen/exit_codes/

commands:
  {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}
    init                init commitizen configuration
    commit (c)          create new commit
    ls                  show available commitizens
    example             show commit example
    info                show information about the cz
    schema              show commit schema
    bump                bump semantic version based on the git log
    changelog (ch)      generate changelog (note that it will overwrite existing file)
    check               validates that a commit message matches the commitizen schema
    version             get the version of the installed commitizen or the current project (default: installed commitizen)

$ poetry run cz bump --help
usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog] [--no-verify] [--yes] [--tag-format TAG_FORMAT] [--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}]
               [--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}] [--check-consistency] [--annotated-tag] [--gpg-sign] [--changelog-to-stdout] [--retry] [--major-version-zero]
               [--prerelease-offset PRERELEASE_OFFSET]
               [MANUAL_VERSION]

positional arguments:
  MANUAL_VERSION        bump to the given version (e.g: 1.5.3)

options:
  -h, --help            show this help message and exit
  --dry-run             show output to stdout, no commit, no modified files
  --files-only          bump version in the files from the config
  --local-version       bump only the local version portion
  --changelog, -ch      generate the changelog for the newest version
  --no-verify           this option bypasses the pre-commit and commit-msg hooks
  --yes                 accept automatically questions done
  --tag-format TAG_FORMAT
                        the format used to tag the commit and read it, use it in existing projects, wrap around simple quotes
  --bump-message BUMP_MESSAGE
                        template used to create the release commit, useful when working with CI
  --prerelease {alpha,beta,rc}, -pr {alpha,beta,rc}
                        choose type of prerelease
  --devrelease DEVRELEASE, -d DEVRELEASE
                        specify non-negative integer for dev. release
  --increment {MAJOR,MINOR,PATCH}
                        manually specify the desired increment
  --check-consistency, -cc
                        check consistency among versions defined in commitizen configuration and version_files
  --annotated-tag, -at  create annotated tag instead of lightweight one
  --gpg-sign, -s        sign tag instead of lightweight one
  --changelog-to-stdout
                        Output changelog to the stdout
  --retry               retry commit if it fails the 1st time
  --major-version-zero  keep major version at zero, even for breaking changes
  --prerelease-offset PRERELEASE_OFFSET
                        start pre-releases with this offset

$ poetry run cz changelog --help
usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME] [--unreleased-version UNRELEASED_VERSION] [--incremental] [--start-rev START_REV] [rev_range]

positional arguments:
  rev_range             generates changelog for the given version (e.g: 1.5.3) or version range (e.g: 1.5.3..1.7.9)

options:
  -h, --help            show this help message and exit
  --dry-run             show changelog to stdout
  --file-name FILE_NAME
                        file name of changelog (default: 'CHANGELOG.md')
  --unreleased-version UNRELEASED_VERSION
                        set the value for the new version (use the tag value), instead of using unreleased
  --incremental         generates changelog from last created version, useful if the changelog has been manually modified
  --start-rev START_REV
                        start rev of the changelog.If not set, it will generate changelog from the start

3.1.4. ツール実行結果

次にツールを実行した後のコミットログを確認します。 バージョンの更新がコミットされ、タグが作成されています。

$ git log --oneline
95a1fa6 (HEAD -> main, tag: v1.0.0) chore: bump from 0.0.0 to 1.0.0
19d8b3d (origin/main, origin/HEAD) build: create exe env of automatic changelog generator
5cc9ed9 feat: update a feature for the user
3b677aa chore: do chores excluding those mentioned above
3b11de7 docs: add documents
c8265c7 ci: add CI configuration files and scripts
1aa34ef build: add the build system and external dependencies
6a74576 test: add tests
d15450e perf: improve performance
2fb93e6 refactor: improve code (without changing external behavior)
85d2dd2 style: apply a format style (without affecting the meaning of the code)
4064860 fix: fix a bug for the user
b9131c5 feat: add a feature for the user
6da62b4 (tag: v0.0.0) Initial commit

最後に自動生成された変更履歴を確認します。 ちなみに<GitHubアカウントID>には実際の値が出力されます。

$ cat CHANGELOG.md
# CHANGELOG

## [v1.0.0](https://github.com/<GitHubアカウントID>/changelog-sample/compare/v0.0.0...v1.0.0) (2023-04-18)

### BREAKING CHANGE

- make incompatible change to existing features

### Feat

- update a feature for the user ([5cc9ed9](https://github.com/<GitHubアカウントID>/changelog-sample/commit/5cc9ed9a8a2deae4dd43ae62527f3919bf36316d))
- add a feature for the user ([b9131c5](https://github.com/<GitHubアカウントID>/changelog-sample/commit/b9131c5394cff65fa70dcd08ca79be543dc387e8))

### Fix

- fix a bug for the user ([4064860](https://github.com/<GitHubアカウントID>/changelog-sample/commit/4064860c09bfa69170b6918d1801587b9b90adbd))

### Refactor

- improve code (without changing external behavior) ([2fb93e6](https://github.com/<GitHubアカウントID>/changelog-sample/commit/2fb93e624dbcfa4fb8514d119fdee9a3f0d8ba5b))

### Perf

- improve performance ([d15450e](https://github.com/<GitHubアカウントID>/changelog-sample/commit/d15450e86043ad416cd536523e53c9bde6329b9e))

## v0.0.0 (2023-04-09)

- Initial commit

3.2. No.05: python-semantic-release/python-semantic-release

2つ目のツールは、Pythonで実装されたツールです。

3.2.1. インストール方法

まずはpoetry(パッケージ管理ツール)をインストールします。

$ python3 --version
Python 3.10.10

$ pipx install poetry
(省略)

$ poetry --version
Poetry (version 1.4.1)

$ poetry config virtualenvs.in-project true

次にpython-semantic-releaseをインストールします。

$ poetry add python-semantic-release --group dev
(省略)

$ poetry show python-semantic-release
 name         : python-semantic-release                           
 version      : 7.33.2                                            
 description  : Automatic Semantic Versioning for Python projects 

dependencies
 - click >=7,<9
 - click-log >=0.3,<1
 - dotty-dict >=1.3.0,<2
 - gitpython >=3.0.8,<4
 - invoke >=1.4.1,<2
 - packaging *
 - python-gitlab >=2,<4
 - requests >=2.25,<3
 - semver >=2.10,<3
 - tomlkit >=0.10,<1.0
 - twine >=3,<4
 - wheel *

3.2.2. ツール実行ログ

次にツールを実行する前のコミットログを確認します。 これに基づいて変更履歴が自動生成されます。

$ git log --oneline
19d8b3d (HEAD -> main, origin/main, origin/HEAD) build: create exe env of automatic changelog generator
5cc9ed9 feat: update a feature for the user # L3: BREAKING CHANGE: make incompatible change to existing features
3b677aa chore: do chores excluding those mentioned above
3b11de7 docs: add documents
c8265c7 ci: add CI configuration files and scripts
1aa34ef build: add the build system and external dependencies
6a74576 test: add tests
d15450e perf: improve performance
2fb93e6 refactor: improve code (without changing external behavior)
85d2dd2 style: apply a format style (without affecting the meaning of the code)
4064860 fix: fix a bug for the user
b9131c5 feat: add a feature for the user
6da62b4 (tag: v0.0.0) Initial commit

次にpython-semantic-releaseを実行します。 バージョンはコミットログに基づいて自動計算されます。

$ poetry run semantic-release publish
Current version: 0.0.0, Current release version: 0.0.0
Bumping with a major version to 1.0.0
Pushing new version
error: Cmd('git') failed due to: exit code(128)
error:   cmdline: git push origin main
error:   stderr: remote: Repository not found.
error: fatal: Authentication failed for <repository url>
# An option like `push_changes` that specifies whether or not to push changes to the repository is not implemented yet,
# so if a env `GH_TOKEN` is not set, output error log when pushing.

補足事項として、実行する前にpyproject.tomlがプロジェクトルートに配置されている必要があります。

詳細

$ cat pyproject.toml
[tool.poetry]
name = "changelog-sample"
version = "0.0.0"
description = "changelog sample"
authors = ["xxx"]
license = "MIT"
readme = "README.md"
packages = [
    {include = "changelog_sample", from = "src"}
]

[tool.poetry.build]
generate-setup-file = false

[tool.poetry.dependencies]
python = "^3.10"

[tool.poetry.group.dev.dependencies]
python-semantic-release = "^7.33.2"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.semantic_release]
branch = "main"
version_toml = [
    "pyproject.toml:tool.poetry.version",
    "pyproject.toml:tool.commitizen.version"
]
version_source = "commit"
# major_on_zero = true # for initial development
commit_subject = "chore: bump to {version}"
commit_message = ""
commit_author = "semantic-release <noreply@github.com>" # this is author, but not comitter
changelog_sections = "breaking, feature, fix, performance"
changelog_components = "semantic_release.changelog.changelog_headers,semantic_release.changelog.compare_url"
changelog_file = "CHANGELOG_sr.md"
upload_to_repository = false # upload distributions to pypi repository
upload_to_release = false # upload distributions to GitHub releases
tag_format = "v{version}"

3.2.3. ツールヘルプ

参考までにツールのヘルプを載せておきます。

詳細

$ poetry run semantic-release --help
Usage: semantic-release [OPTIONS] COMMAND [ARGS]...

Options:
  -v, --verbosity LVL             Either CRITICAL, ERROR, WARNING, INFO or
                                  DEBUG
  --major                         Force major version.
  --minor                         Force minor version.
  --patch                         Force patch version.
  --prerelease                    Creates a prerelease version.
  --prerelease-patch / --no-prerelease-patch
                                  whether or not prerelease always gets at
                                  least a patch-level bump  [default:
                                  prerelease-patch]
  --post                          Post changelog.
  --retry                         Retry the same release, do not bump.
  --noop                          No-operations mode, finds the new version
                                  number without changing it.
  -D, --define TEXT               setting="value", override a configuration
                                  value.
  --help                          Show this message and exit.

Commands:
  changelog      Generate the changelog since the last release.
  print-version  Print the current or new version to standard output.
  publish        Run the version task, then push to git and upload to an...
  version        Detect the new version according to git log and semver.

$ poetry run semantic-release version --help
Usage: semantic-release version [OPTIONS]

  Detect the new version according to git log and semver.

  Write the new version number and commit it, unless the noop option is True.

Options:
  -v, --verbosity LVL             Either CRITICAL, ERROR, WARNING, INFO or
                                  DEBUG
  --major                         Force major version.
  --minor                         Force minor version.
  --patch                         Force patch version.
  --prerelease                    Creates a prerelease version.
  --prerelease-patch / --no-prerelease-patch
                                  whether or not prerelease always gets at
                                  least a patch-level bump  [default:
                                  prerelease-patch]
  --post                          Post changelog.
  --retry                         Retry the same release, do not bump.
  --noop                          No-operations mode, finds the new version
                                  number without changing it.
  -D, --define TEXT               setting="value", override a configuration
                                  value.
  --help                          Show this message and exit.

$ poetry run semantic-release changelog --help
Usage: semantic-release changelog [OPTIONS]

  Generate the changelog since the last release.

  :raises ImproperConfigurationError: if there is no current version

Options:
  -v, --verbosity LVL             Either CRITICAL, ERROR, WARNING, INFO or
                                  DEBUG
  --major                         Force major version.
  --minor                         Force minor version.
  --patch                         Force patch version.
  --prerelease                    Creates a prerelease version.
  --prerelease-patch / --no-prerelease-patch
                                  whether or not prerelease always gets at
                                  least a patch-level bump  [default:
                                  prerelease-patch]
  --post                          Post changelog.
  --retry                         Retry the same release, do not bump.
  --noop                          No-operations mode, finds the new version
                                  number without changing it.
  -D, --define TEXT               setting="value", override a configuration
                                  value.
  --unreleased / --released       Decides whether to show the released or
                                  unreleased changelog.
  --help                          Show this message and exit.

$ poetry run semantic-release publish --help
Usage: semantic-release publish [OPTIONS]

  Run the version task, then push to git and upload to an artifact repository
  / GitHub Releases.

Options:
  -v, --verbosity LVL             Either CRITICAL, ERROR, WARNING, INFO or
                                  DEBUG
  --major                         Force major version.
  --minor                         Force minor version.
  --patch                         Force patch version.
  --prerelease                    Creates a prerelease version.
  --prerelease-patch / --no-prerelease-patch
                                  whether or not prerelease always gets at
                                  least a patch-level bump  [default:
                                  prerelease-patch]
  --post                          Post changelog.
  --retry                         Retry the same release, do not bump.
  --noop                          No-operations mode, finds the new version
                                  number without changing it.
  -D, --define TEXT               setting="value", override a configuration
                                  value.
  --help                          Show this message and exit.

3.2.4. ツール実行結果

次にツールを実行した後のコミットログを確認します。 バージョンと変更履歴の更新がコミットされ、タグが作成されています。

$ git log --oneline
89dfb7b (HEAD -> main, tag: v1.0.0) chore: bump to 1.0.0
19d8b3d (origin/main, origin/HEAD) build: create exe env of automatic changelog generator
5cc9ed9 feat: update a feature for the user
3b677aa chore: do chores excluding those mentioned above
3b11de7 docs: add documents
c8265c7 ci: add CI configuration files and scripts
1aa34ef build: add the build system and external dependencies
6a74576 test: add tests
d15450e perf: improve performance
2fb93e6 refactor: improve code (without changing external behavior)
85d2dd2 style: apply a format style (without affecting the meaning of the code)
4064860 fix: fix a bug for the user
b9131c5 feat: add a feature for the user
6da62b4 (tag: v0.0.0) Initial commit

最後に自動生成された変更履歴を確認します。 ちなみに<GitHubアカウントID>には実際の値が出力されます。

$ cat CHANGELOG_sr.md
# CHANGELOG

<!--next-version-placeholder-->

## v1.0.0 (2023-04-10)
### Breaking
* make incompatible change to existing features ([`5cc9ed9`](https://github.com/<GitHubアカウントID>/changelog-sample/commit/5cc9ed9a8a2deae4dd43ae62527f3919bf36316d))

### Feature
* Update a feature for the user ([`5cc9ed9`](https://github.com/<GitHubアカウントID>/changelog-sample/commit/5cc9ed9a8a2deae4dd43ae62527f3919bf36316d))
* Add a feature for the user ([`b9131c5`](https://github.com/<GitHubアカウントID>/changelog-sample/commit/b9131c5394cff65fa70dcd08ca79be543dc387e8))

### Fix
* Fix a bug for the user ([`4064860`](https://github.com/<GitHubアカウントID>/changelog-sample/commit/4064860c09bfa69170b6918d1801587b9b90adbd))

### Performance
* Improve performance ([`d15450e`](https://github.com/<GitHubアカウントID>/changelog-sample/commit/d15450e86043ad416cd536523e53c9bde6329b9e))

**[See all commits in this version](https://github.com/<GitHubアカウントID>/changelog-sample/compare/v0.0.0...v1.0.0)**

3.3. No.01: conventional-changelog/conventional-changelog-cli

3つ目のツールは、JavaScriptで実装されたツールです。

3.3.1. インストール方法

まずは、Node.js(JavaScript実行環境)及びnpm(JavaScript系パッケージ管理ツール)をインストールします。

$ curl -fsSL https://deb.nodesource.com/setup_19.x | sudo -E bash -
$ # サードパーティ用のaptリポジトリ情報(ディレクトリ`/etc/apt/sources.list.d/`)にノードソース`Node.js 19.x`を追加する
(省略)

$ cat /etc/apt/sources.list.d/nodesource.list
$ # サードパーティ用のaptリポジトリ情報(ディレクトリ`/etc/apt/sources.list.d/`)を確認する
deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_19.x bullseye main
deb-src [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_19.x bullseye main

$ sudo apt update && sudo apt install -y nodejs
(省略)

$ node --version
v19.8.1

$ npm --version
9.5.1

次にconventional-changelog-cliをインストールします。

$ cd workspace/Git/python/changelog-sample

$ sudo npm install conventional-changelog-cli
(省略)

$ npm ls
changelog-sample@0.0.0 /root/workspace/Git/python/changelog-sample
└── conventional-changelog-cli@2.2.2

3.3.2. ツール実行ログ

次にツールを実行する前のコミットログを確認します。 これに基づいて変更履歴が自動生成されます。

$ git log --oneline
19d8b3d (HEAD -> main, origin/main, origin/HEAD) build: create exe env of automatic changelog generator
5cc9ed9 feat: update a feature for the user # L3: BREAKING CHANGE: make incompatible change to existing features
3b677aa chore: do chores excluding those mentioned above
3b11de7 docs: add documents
c8265c7 ci: add CI configuration files and scripts
1aa34ef build: add the build system and external dependencies
6a74576 test: add tests
d15450e perf: improve performance
2fb93e6 refactor: improve code (without changing external behavior)
85d2dd2 style: apply a format style (without affecting the meaning of the code)
4064860 fix: fix a bug for the user
b9131c5 feat: add a feature for the user
6da62b4 (tag: v0.0.0) Initial commit

次にconventional-changelog-cliを実行します。 バージョンはコミットログに基づいて自動計算される訳ではなく、 どのバージョンを上げるかユーザが指定する必要があります。

$ npm version major

> version
> conventional-changelog --preset angular --release-count 0 --tag-prefix v --pkg package.json --infile CHANGELOG_cc.md --same-file && git add CHANGELOG_cc.md

v1.0.0

補足事項として、実行する前にpackage.jsonがプロジェクトルートに配置されている必要があります。

詳細

$ cat package.json
{
  "version": "0.0.0",
  "scripts": {
    "version": "conventional-changelog --preset angular --release-count 0 --tag-prefix v --pkg package.json --infile CHANGELOG_cc.md --same-file && git add CHANGELOG_cc.md"
  },
  "dependencies": {
    "conventional-changelog-cli": "^2.2.2"
  }
}

3.3.3. ツールヘルプ

参考までにツールのヘルプを載せておきます。

詳細

$ npm version --help
Bump a package version

Usage:
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]

Options:
[--allow-same-version] [--no-commit-hooks] [--no-git-tag-version] [--json]
[--preid prerelease-id] [--sign-git-tag]
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
[-ws|--workspaces] [--no-workspaces-update] [--include-workspace-root]

alias: verison

Run "npm help version" for more info

$ 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 do not 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, conventionalcommits, ember, eslint, express, jquery 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

    --skip-unstable           If given, unstable tags will be skipped, e.g., x.x.x-alpha.1, x.x.x-rc.2

    -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/blob/master/packages/conventional-changelog-cli/test/fixtures/config.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 (:pkg-name@1.0.0)
    -t, --tag-prefix          Tag prefix to consider when reading the tags
    --commit-path             Generate a changelog scoped to a specific directory

3.3.4. ツール実行結果

次にツールを実行した後のコミットログを確認します。 バージョンと変更履歴の更新がコミットされ、タグが作成されています。

$ git log --oneline
c9559e3 (HEAD -> main, tag: v1.0.0) 1.0.0
19d8b3d (origin/main, origin/HEAD) build: create exe env of automatic changelog generator
5cc9ed9 feat: update a feature for the user
3b677aa chore: do chores excluding those mentioned above
3b11de7 docs: add documents
c8265c7 ci: add CI configuration files and scripts
1aa34ef build: add the build system and external dependencies
6a74576 test: add tests
d15450e perf: improve performance
2fb93e6 refactor: improve code (without changing external behavior)
85d2dd2 style: apply a format style (without affecting the meaning of the code)
4064860 fix: fix a bug for the user
b9131c5 feat: add a feature for the user
6da62b4 (tag: v0.0.0) Initial commit

最後に自動生成された変更履歴を確認します。 ちなみに<GitHubアカウントID>には実際の値が出力されます。

$ cat CHANGELOG_cc.md
# [1.0.0](https://github.com/<GitHubアカウントID>/changelog-sample/compare/v0.0.0...v1.0.0) (2023-04-10)


### Bug Fixes

* fix a bug for the user ([4064860](https://github.com/<GitHubアカウントID>/changelog-sample/commit/4064860c09bfa69170b6918d1801587b9b90adbd))


### Features

* add a feature for the user ([b9131c5](https://github.com/<GitHubアカウントID>/changelog-sample/commit/b9131c5394cff65fa70dcd08ca79be543dc387e8))
* update a feature for the user ([5cc9ed9](https://github.com/<GitHubアカウントID>/changelog-sample/commit/5cc9ed9a8a2deae4dd43ae62527f3919bf36316d))


### Performance Improvements

* improve performance ([d15450e](https://github.com/<GitHubアカウントID>/changelog-sample/commit/d15450e86043ad416cd536523e53c9bde6329b9e))


### BREAKING CHANGES

* make incompatible change to existing features



# 0.0.0 (2023-04-09)



4. 変更履歴自動生成ツールの仕様まとめ

前章では自身の開発環境にて変更履歴自動生成ツールを用いたサンプルを作成してみました。 その結果、基本的には以下の機能が提供されていることが確認できました。

  • コミットメッセージに基づいてバージョンとタグが作成されること
  • コミットメッセージのヘッダの種別(type)ごとに変更履歴が生成されること
  • 変更履歴(CHANGELOG.mdなど)とバージョン(pyproject.tomlpackage.json)の更新が同時にコミットされること
    • 変更履歴とバージョンの更新が鶏と卵の関係になっているが、内部でよしなに処理してくれる

また、ツールごとに大きく異なる点も確認できました。

  • 変更履歴に旧タグと新タグの差分確認用のリンクが出力されること
  • 変更履歴にコミットへのリンクが出力されること

更に特徴的だった点が自動生成の部分をカスタムできる枠組みを提供しているツール(commitizen-tools/commitizen)もあったことです。 よく見かけたのは設定ファイルで少しカスタムできるというツールでしたが、ツールごとに一長一短で物足りなさを感じていました。 しかし、この特徴的なツールはカスタム用のスーパークラスが用意されていて、 各自のリポジトリで好きなように実装してもいいですよというスタンスのツールでした。 なので、今回調査したツールの中では一番のお気に入りです。

また、細かいところで気になる点もありましたが、個人の好みの問題になりそうなので割愛します。

5. 最後に

本記事ではConventional Commitsに従ったコミットログに基づいて変更履歴を自動生成するツールを紹介しました。 これで今後は変更履歴を自動生成することができるので、当初感じていた億劫になることはなくなると思います。 ただ、CI関連はドキュメントにてできることを確認しただけでサンプルを作成していません。 今後必要になった際にサンプルを作成してみたいと思います。

6. 参考URL

今回、調査や検証を行った際に訪問したサイトのURLになります。 記事の中でリンクを貼っているサイトのみチェックマークを付けています。

6.1. Commit Message Guidelines by Angular

6.2. Conventional Commits

6.3. GitHub Programming Language Ranking

6.4. conventional-changelog-cli

6.5. github-changelog-generator