changesets-gitlabを使って、changesets を自動化してみた
はじめに
この記事では、changesetsでできること・changesets-gitlabを使ってどう自動化したかについてまとめました。
changesetsの概要
まず最初に簡単にですがchangesetsの概要について触れていきます。
Changesetsは、パッケージごとの変更内容(機能追加、バグ修正、破壊的変更など)を個別のファイルで記録する仕組みです。任意のタイミングで変更のログを記録して、設定を行うことでChangelogの作成と自動的にパッケージのバージョンアップを行なってくれます。
changesetsの使い方
変更記録の作成
各機能追加や修正を行った後に以下のコマンドを使用する。
$ npx changeset
変更内容を記録するためのmdファイルを作成していきます。
🦋 What kind of change is this for <プロジェクト名>? (current version is 0.2.4) · patch
🦋 Please enter a summary for this change (this will be in the changelogs).
🦋 (submit empty line to open external editor)
🦋 Summary · changelogに記載したい内容
🦋
🦋 === Summary of changesets ===
🦋 patch: <プロジェクト名>
🦋
🦋 Is this your desired changeset? (Y/n) · true
ターミナルに出力される質問に従って回答していきます。
質問内容
- 変更の種類の確認(🦋 What kind of change is this for <プロジェクト名>? )
- どのレベルのバージョンを上げるかを選択する(patch、minor、major)
- 変更内容の要約入力(🦋 Please enter a summary for this change (this will be in the changelogs).)
- changelogに記載したい内容を書く
- 変更内容の確認(🦋 Is this your desired changeset?)
- 変更内容に問題なければ、Yesと回答する
mdファイルが自動生成
質問への回答が完了すると、.changesetフォルダ配下に変更が記録されたmdファイルが作成されます。ファイル名はランダムです。
CHANGELOG.mdの作成
リリースのタイミングで変更記録を元にCHANGELOG.mdを作成します。
$ npx changeset version
上記のコマンドを実行すると、
- .changesetフォルダ配下に変更が記録されたmdファイルを元にCHANGELOG.mdの生成
- .changesetフォルダ配下に変更が記録されたmdファイルは削除
- package.jsonのversionをインクリメント
- レベルが異なるバージョンの変更があった場合は、上位のレベルで変更されます。例えば、minorとmajorが存在していたら、majorバージョンでインクリメントされます。
概要、使い方としては以上になります。
実装の準備
cliツールをインストール
最初に、changesetsのcliツールをインストールします。
$ npm install --save-dev @changesets/cli
初期化
$ npx changeset init
🦋 Thanks for choosing changesets to help manage your versioning and publishing
🦋
🦋 You should be set up to start using changesets now!
🦋
🦋 info We have added a `.changeset` folder, and a couple of files to help you out:
🦋 info - .changeset/README.md contains information about using changesets
🦋 info - .changeset/config.json is our default config
changesetを初期化すると、ルートに.changesetフォルダが作成されます。
中には、config.jsonとREADME.mdが存在しています。
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
こちらですでに変更の記録ができるようになっています(npx changesetが使用できる)
自動化の対応
changesets-gitlabを使用して、CHANGELOG.mdの作成とマージリクエストの自動生成を実現します。
changesets-gitlabをインストール
$ npm install changesets-gitlab --save-dev
package.jsonのスクリプト設定
package.jsonにスクリプトを追加して、CI上でchangesets-gitlabを実行できるようにします。
"scripts": {
...
"changesets": "changesets-gitlab"
}
CIの設定
定義したジョブは以下のようにしました。
update:changesets:
stage: update_packages
rules:
- if: '$CI_COMMIT_REF_NAME == "main"'
when: on_success
script:
- npm ci
- npm run changesets
variables:
GITLAB_TOKEN: ${PROJECT_ACCESS_TOKEN} # required
INPUT_COMMIT: update changelog and package. # optional
INPUT_TITLE: Update Changelog and Package. # optional
mainブランチへのマージ完了時に、changesets-gitlabが実行されるようにしています。
環境変数 | 入力 | 備考 |
---|---|---|
GITLAB_TOKEN | アクセストークン | プロジェクトアクセストークンでも可 |
INPUT_COMMIT | コミットメッセージ | 指定なしならVersion Packagesとなる |
INPUT_TITLE | マージリクエストのタイトル | 指定なしならVersion Packagesとなる |
環境変数は、上記3つを指定しました。
備考にもありますが、GITLAB_TOKEN
は、プロジェクトトークンを新しく作成して、変数として定義して使用しました。INPUT_COMMIT
とINPUT_TITLE
の指定は任意です。
また、環境変数には、INPUT_VERSION
というものが存在しています。任意の値で指定しなければ内部でchangeset version
を実行してくれます。
ここまでの対応で、変更記録を含むブランチがmainブランチにマージされると、自動でマージリクエストが生成されるようになります。
Changelogのフォーマットをカスタマイズ
changesetsには、生成されたChangelogのフォーマットをカスタマイズすることが可能です。
デフォルトの設定だと、changesetsの変更点がplain textとして出力されるだけなのでカスタマイズしました。
変更には、getReleaseLine・getDependencyReleaseLineの2つの関数を使用します。getReleaseLineは、スクショの赤枠部分で、getDependencyReleaseLineはスクショの青枠部分です。後はバージョン番号の横に日付を入れたかったのですが、現状では見出しのカスタマイズはできないようでした...
話は上がっているようなので今後に期待です🙏
では、changelog-function.jsのような名前のファイルを作成して、以下のような実装例でカスタマイズしていきます
const changelogFunctions = {
getDependencyReleaseLine: () => Promise.resolve(''), // 今回は特にカスタマイズなし
getReleaseLine: (changeset, _, options) => {
if (!changeset || !options.repo) {
return
}
let mrNumber
const replacedChangelogSummary = changeset.summary
.replace(/#(\d+)/, (_, pr) => {
let num = Number(pr)
if (!isNaN(num)) mrNumber = num
return ''
})
.trim()
const mrLink = `${options.repo}/-/merge_requests/${mrNumber}`
return mrNumber
? `- ${replacedChangelogSummary}([#${mrNumber}](${mrLink}))`
: `- ${replacedChangelogSummary}`
}
}
export default changelogFunctions
getReleaseLineの関数を使用してリリースノート一行のみカスタマイズを行いました。
実装の中身としては、変更内容の要約にgitlabのマージリクエスト番号(#付きで)が入力されていたら、リンクになるようにしてみました。また、関数の返り値はをマークダウンで書くことで、リストやテキストリンクを表現することができます。
後は、上記の関数が実行されるようにconfig.jsonに追記します。
repoに、gitlabのリポジトリURLを入れてあげるとgetReleaseLineの引数であるoptions.repoで値を受け取ることができます。
{
...
"changelog": [
"./changelog-function.js", { "repo": "gitlabのリポジトリURL" }
],
...
}
これでマージリクエストが自動生成された時に、CHANGELOG.mdのフォーマットを変更することができました。と同時に自動化とフォーマットのカスタマイズ対応も以上となります。
その他
changesetsの実装をする中で困ったことを2点共有します。
もしどなたかの参考に少しでもなればと思い記載させていただきます🙇♂️
1. lockファイルが更新されない問題
changeset version
の実行時に、package.jsonのバージョンは更新されますが、package.lock.jsonのバージョンは更新されません。
issuesにも上がっていますが、対応はまだのようです。そのため、現状ではlockファイルも更新したい場合は、自動生成されたマージリクエストが作成された時に、CI上でnpm installlをする or package.lock.jsonのバージョンを直接書き換える関数を用意して実行する、等の別途でアプローチが必要そうです...(私は暫定的ですが直接書き換える関数を用意する方を選択しました)
2. フォーマットのカスタマイズはTypescriptで書くことができない?
Typescriptのサポートをしていない?ようです...
型定義ファイルも存在しているので、Typescriptで書きたかったのですが現状ではJavascriptで書きました。
おわりに
changesetsを導入することで変更履歴やバージョンの管理が楽になりました。また、gitlabの場合はchangesets-gitlabを使うことで、自動でマージリクエストを作成してくれたりと便利になりました🙌
Discussion