Hiratake Web ロゴ

Changesets でパッケージをリリースする

投稿した日
更新した日
書いたひと
icon
ひらたけ

Changesets を使ってパッケージをリリースする方法について、備忘録的な感じで書いておこうと思います。

Changesets とは

そもそも Changesets とは?ということについて、ざっくり説明します。

Changesets は、 Node.js のパッケージをリリースする際に使用するツール です。
ReactVue.js などを用いてウェブアプリケーションを開発するときなどに、マシンへ Node.js をインストールし、 以下のようなコマンドを実行してライブラリをインストールすると思います。

# React
$ npm install react
# Vue.js
$ npm install vue

この際にインストールしているのが Node.js のパッケージであり、Changesets はこういったパッケージを作る側が、パッケージをリリースするときに使うツールということになります。

パッケージをリリースする際には、一般的に次のような対応をすることになります。

  • 変更履歴の更新
  • 新しくリリースするバージョンの指定
  • レジストリでのリリース

こういった作業を 毎回手動で行うのは非常に手間 ですし、たくさんのひとと共同で開発しているパッケージの場合、 変更履歴を書く際にどこでどういう変更をしたのかが分からなくなります

Changesets を使用することで、導入時の設定などは必要ですが、 こういった作業をある程度自動化することができます

他の似たツールとして semantic-release があります。こちらはコミットの履歴から自動的に変更履歴を生成したり、どのバージョン番号に更新するのかを決めたりしてくれるので、作業者がリリースのために何か作業をするということは必要ありません。

しかし、コミットするときのメッセージの形式を全員で揃える必要がありますし、変更履歴にコミットのメッセージが掲載されてしまうので気軽なコミットがしづらくなってしまいます。

Changesets は .changeset というフォルダに Markdown 形式で変更点を記録していき、 パッケージをリリースするタイミングでそれらを 1 つにまとめて変更履歴を生成 します。なので、 semantic-release よりは多少手間はかかってしまいますが、自由度は Changesets のほうが高いと思います。

環境

今回確認した環境は、以下のとおりです。

パッケージのリリース先は npm 、リポジトリは Public リポジトリとして GitHub 上に存在しています。

また、リポジトリは pnpm workspace を使用した monorepo 構成となっています。パッケージが packages/ ディレクトリ内に存在しています。

monorepo/
 ├ packages/
 │ └ hogehoge/
 │   └ package.json
 ├ package.json
 ├ pnpm-lock.yaml
 └ pnpm-workspace.yaml

導入

Changesets の導入は、以下のドキュメントを参考に行います。

まず、monorepo のルートプロジェクトへ @changesets/cli をインストールします。

$ pnpm add -wD @changesets/cli
$ pnpm changeset init

実行すると、 .changeset というディレクトリと、その中に Changesets の設定をするための config.json が作られます。

次に、config.json を開き、設定を変更します。初期状態では access という項目が restricted という設定となっており、このままの状態ではプライベートなパッケージとしてリリースされてしまい、 アクセス権を持っているユーザしかパッケージを利用できない状態 となってしまいます。こちらを public へ変更します。

{
  "access": "public",
  ...
}

その他の設定については、ドキュメント を確認し必要に応じて変更してください。

これで Changesets の設定は完了です。続いて、GitHub でパッケージのリリースを自動で行うためのワークフローの設定を行います。

GitHub には GitHub Actions という、コードのビルドやテストなどを自動化するための仕組みがあります。Changesets には、この GitHub Actions でパッケージをリリースするための Action が用意されており、こちらを使用します。

基本的には こちらのワークフローの例 をそのまま使用すれば問題ないと思います。pnpm を使用している場合は、pnpm のドキュメントにあるワークフローの例 を参考にワークフローを設定すると良いでしょう。

pnpm を使用する場合、Git でコミットされていない変更があると pnpm publish -r の実行時に失敗してしまうようなので、以下のように package.json のスクリプトを変更するか、.npmrc で設定を変更する必要があります。

{
  "scripts": {
    "ci:publish": "pnpm publish -r --no-git-checks"
  },
  ...
}

次に、ワークフロー内で使用するトークンを GitHub のリポジトリに設定します。ブラウザで GitHub 上のリポジトリを開き、「Settings」のタブから設定画面を開きます。その後、左側のメニューから Secrets and variables > Actions を開き、「New repository secret」からトークンを設定します。

トークンは npm の「Access Tokens」から生成できます。生成したトークンを、先ほどの GitHub の画面から NPM_TOKEN という名前で登録します。

これで Changesets でパッケージをリリースする準備は完了です。GitHub で Changesets を使用する場合、changeset bot の使用が推奨されているので、必要に応じてリポジトリへ追加してください。

パッケージをリリースする

設定ができたので、実際にパッケージをリリースしてみます。

一般的なプロジェクトでは、 main ブランチに直接コミットはせず、別のブランチを作成してコミットし、プルリクエストを作成してマージするという流れかと思いますので、その前提で進めます。

まずは、以下のコマンドを実行してパッケージの変更内容についての説明を追加します。

$ pnpm changeset

表示された説明に従って、パッケージの選択と、バージョンの選択(major/minor/patch)を行い、最後に変更内容についての説明を入力します。

入力した内容は .changeset ディレクトリ内に Markdown 形式で保存されますので、こちらのファイルを開いて後から内容を編集することもできます。生成された Markdown ファイルは、他のファイルの変更と一緒にコミットします。

その後、GitHub でプルリクエストを作成します。導入時に changeset bot を導入した場合は、プルリクエストに対してコメントがされると思います。内容を確認し、問題なければプルリクエストをマージします。

正しくワークフローが実行されると、リリースをするためのプルリクエストが自動的に作成されます。 この作成されたプルリクエストをマージすると、パッケージがリリースされます


pnpmEmotion のリポジトリなどで使われているのを見て、なんとなく使ってみたいなと思い使ってみましたが、設定もそれほど難しくなく monorepo でも扱いやすくてよかったです。

ただ、最後のリリースをするためのプルリクエストに対しては、Lint や Test などのワークフローが実行されない(無限ループになってしまうのを防ぐため?GitHub 側の仕様っぽい)みたいで、ブランチの保護で特定のワークフローが成功しないとマージできないようにしているときにどうしようもなくなってしまいました。

これをどうにかしたいけど方法が思いつかないので詳しいひといたら教えてください🙏
今はとりあえず空のコミットを手動で追加して動かしてます。