lernaからlerna-lite + turborepoに移行する
Secretlintはmonorepoとなっていて、パッケージを公開する際にlernaを利用していました。 しかし、lernaは現在メンテナンスされていないため、publish機能だけを取り出したlerna-liteと効率的なmonorepo向けのビルドツールであるTurborepoへ移行しました。
追記: NxによってLernaがメンテナンスされるそうです。
- Announcement: Passing the torch · Issue #3121 · lerna/lerna
- Lerna is dead — Long Live Lerna. If you’re in a hurry, here’s the TL;DR: | by Juri Strumpflohner | May, 2022 | Nrwl
次の記事で書いていますが、Lernaはもともとall-in-one的なツールでしたが、それぞれの分野でメジャーなものが各機能と同等のものを実装しています。 一番大きな所としては、Workspaces機能を各パッケージマネージャーが実装したため、Lerna独自でこの機能を持つ必要性がかなり薄くなりました。
元々はLernaがWorkspace管理(依存関係の管理)、タスク管理(パッケージの依存を見てタスクを実行)、Publish管理(バージョンの更新やCHANGELOGの作成、公開)などの機能を持ったツールとしてスタートしています。
Workspace管理は、npm 7+/Yarn/pnpmなどのパッケージマネージャーがworkspaces機能としてサポートし始めました。 タスク管理は、TurborepoやNx(Nxは全部入り)などがより効率的に実行できるツールとして誕生しています。 Publish管理は、まだ成熟したツールは少ないですがchangesets/Ship.js/lerna-lite、パッケージマネージャー自体が持っていることがあります。
一方で、monorepoのバージョン管理ツールでlernaより使われているものはありません。
https://www.npmtrends.com/changesets-vs-lerna-vs-shipjs-vs-@microsoft/rush
パッケージマネージャー自体は、publishはサポートしていますが、パッケージのバージョン更新については扱っていないことが多いです。
Lernaでは、–canaryでのCanaryバージョンの公開、–conventional-commitsでのConventional Commitsのサポート、–create-release githubでのGitHubリリースの連携などがありました。
この辺の機能を使ったリリースフローは自分の中である程度固まっていて、あまり代替となるツールはありませんでした(あっても別のリリースフローになってしまう)
lerna-liteは、この部分(具体的にはlerna version
とlerna publish
)の機能だけを取り出してメンテナンスされているForkです。
このリリースフロー以外の機能については、npmやYarn自体でもある程度なんとかなりますが、この部分だけはリリースフロー自体が大きく変えない限り変わるものがありませんでした。
今回は、Lernaからlerna-liteへの移行と、 合わせてTurborepoでのビルドやテストの効率化を行いました。
lerna run
からTurborepoへの移行
TurborepoはVercelに買収されて、Vercelで開発されているmonorepo向けのビルドシステムです。 リモートキャッシュや並列ビルドなども対応したビルドシステムです。
Bazelなどもこれらの機能を持っていますが、設定が複雑になることが知られています。
Turborepoは、設定はスクリプトにおける依存関係をpackage.json
に追加するだけ(大部分は定型的)で、簡単に導入できるようになっています。
他のmonoreoツールについては、次のサイトでも解説されています。
まずは、リリース周り以外のビルドやテストなどをLernaではなくTurborepoを使って実行するようにしました。 次のPRで実際の変更が見れます。
Yarn v1 + Lernaから、Yarn v1 + Turborepoに移行していくつか異なる点はありました。(Turborepo v1.1)
- Turborepoの方が厳密なので、入れ忘れていたdevDependenciesがエラーになった
ENV_A=1 turbo run build
と実行して、各パッケージのnpm run build
にはENV_A
が渡されなかった- Turborepoは循環参照を見つけても、ハングするだけでエラーを報告してくれなかった(Lernaではエラーを報告してくれた)
- 今後改善される可能性はありそう
速度については、ローカルキャッシュで導入したのでCI自体はそこまで多くは変わりませんでした。
キャッシュがあって、変更がないときのturbo run
の結果はキャッシュが使われるので、何度も実行する場合には早くなったと思います。
これで、lerna version
とlerna publish
以外では、Lernaを使わないようにできました。
LernaをLerna-Liteに移行
lernaからlerna-liteへの移行は簡単です。
lerna version
とlerna publish
は互換性がある同じ名前のコマンドが用意されているので、次のようにインストールするだけです。
yarn remove lerna -W
yarn add @lerna-lite/cli --dev -W
@lerna-lite/cli
を入れるとlerna
コマンドが利用できるので、他に変更する必要はありません。
実際のPRは次で見れます。
Secretlintでは、lerna run
を先に外したので使っていませんでしたが、@lerna-lite/runを使うとlerna run
コマンドも利用できます。
npmを使っている場合は、lerna-liteはnpm 8が必要になっています。 Node.jsは14が必要で、最初は16が必要でしたが修正しています。
これで、lernaからlerna-lite + turborepoに移行できました。
おわり
Secretlintでは、パッケージをCIからリリースするようにしています。
- secretlint/create-release-pr.yml at master · secretlint/secretlint
- パッケージのバージョンを上げてリリース用のPRを作成
- secretlint/publish.yml at master · secretlint/secretlint
- バージョンが上がったパッケージがあったらnpm registryへリリース
- ついでにDockerへもpushする
npmのMFAがpublishに対して有効の場合は、OTP codeが必要ですが、OTP codeには有効期限があるため大量のパッケージをpublishすると期限が切れてしまう可能性があります。 そのため、有効期限がないnpm automation tokensを作成して、CI経由でpublishしています。
しかし、このnpmのtokenはリポジトリ/パッケージ単位ではなくユーザー単位になっています。 複数人で開発するリポジトリでは、リポジトリへ個人のnpm tokenは設定すると、別のメンテナーから利用できてしまう問題があります。 そのため、monorepoごとにnpmユーザーを作成して、そのnpmユーザーのnpm automation tokensを利用する必要があります。
- npm publishのMFA有効化したい
— azu (@azu_re) March 26, 2022
- → monorepoのpublishでOTPがタイムアウトする
- → monorepoはtoken作らないといけない
- → リポジトリscopeのtokenは作れないので、botユーザーで代用
- → botユーザーのMFA管理が増える
- → MFA管理ツールがどれもロックイン感あって、増やしにく
- 最初に戻る
これがとても面倒で、GitHubの権限でGitHub Actionsからnpmへpublishする機能が入ってくれると、こんなややこしいことをしなくて済むのにと思いました。
リポジトリ単位のnpm tokenを扱うツールとしては、GCP周りのライブラリで使われているWombat Dressing Roomがあります。
- GoogleCloudPlatform/wombat-dressing-room: proxy designed to reduce the attack surface of npm publish
リリースノートについては、GitHubがPRから自動的に作成する機能を追加したりしています。 そのため、Lernaの–create-release githubなどのリリースノート周りの機能もあまり使わなくなってきた気がします。
ローカルからpublishするよりもCIからpublishする方がクリーンで安全なので、今後はそういう方向になっていく感じはします(lernaはローカル = 人間向けの機能がちょこちょこあるので、この辺もomit出来そう)。 ただし、先ほども書いたnpm publishに必要なトークンの管理が面倒という問題があるので、この部分が改善されてきたら、またリリースフローは変わりそうな気がしました。
お知らせ欄
JavaScript Primerの書籍版がAmazonで購入できます。
JavaScriptに関する最新情報は週一でJSer.infoを更新しています。
GitHub Sponsorsでの支援を募集しています。