Cloudflare Workers SDKのパッケージ群をRenovateでアップデートする際、packageRules の matchSourceUrls で https://github.com/cloudflare/workers-sdk を指定すれば、wrangler、@cloudflare/vite-plugin、miniflareを1つのPRにまとめられます。
{
packageRules: [
{
groupName: "cloudflare workers-sdk",
// パッケージ名を個別に指定する方法
matchPackageNames: ["wrangler", "@cloudflare/vite-plugin", "miniflare"],
// or ソースリポジトリURLで一括指定する方法
matchSourceUrls: ["https://github.com/cloudflare/workers-sdk"],
},
],
}
Renovateのmonorepo presetにはまだ含まれていないため、手動でのグルーピング設定が必要です。この記事では、個別PRによるインストール失敗の問題、グルーピング設定の方法、そしてmonorepo presetへの提案で浮上したimmortal PRs問題を紹介します。
Cloudflare Workers SDKのパッケージ構成
Cloudflare Workers SDKは、GitHub上の cloudflare/workers-sdk というモノレポで開発されています。代表的なパッケージは以下の3つです。
- wrangler — Cloudflare WorkersのCLIツール。ローカル開発、ビルド、デプロイを担います
- @cloudflare/vite-plugin — ViteベースのフレームワークとCloudflare Workersを統合するプラグイン
- miniflare — Cloudflare Workersのローカルシミュレーター。wranglerの内部でも使われています
これらのパッケージは密結合です。依存の方向は @cloudflare/vite-plugin → wrangler → miniflare という一方向ですが、monorepo内の依存指定に workspace:* を使っているため、npmにpublishされた時点でexact versionに変換されます。@cloudflare/vite-plugin のCHANGELOGを見ると、パッチリリースのたびに「Updated dependencies」として固定バージョンが記載されています。
この仕組みにより、どれか1つだけバージョンを上げると他のパッケージが要求するexact versionと食い違い、パッケージの解決に失敗します。wrangler、@cloudflare/vite-plugin、miniflareは常にセットで更新する必要があります。
ラビー合同会社では、コーポレートサイト(labee.jp)と開発者ツールサイト(labee.dev)の両方をCloudflare Workersにデプロイしています。labee.jpではwranglerを、labee.devではさらに@cloudflare/vite-pluginも使用しており、どちらのリポジトリでもRenovateによる依存パッケージの自動アップデートを運用しています。
個別PRが引き起こす問題
Renovateのデフォルト設定では、パッケージごとに独立したPRが作成されます。cloudflare/workers-sdk モノレポのパッケージも例外ではなく、wranglerと@cloudflare/vite-pluginのアップデートがそれぞれ別のPRになります。
labee.devのリポジトリで実際に起きた事例を紹介します。ある週のRenovateの定期実行で、@cloudflare/vite-pluginのPRとwranglerのPRが別々に作成されました。どちらのPRも pnpm install の時点でエラーになります。
vite-pluginだけを更新すると、新しいvite-pluginが要求するwranglerのexact versionとプロジェクトにインストール済みのバージョンが一致しません。逆にwranglerだけを更新しても、既存のvite-pluginが古いwranglerのexact versionを要求しているため解決できません。個別のPRは単体では pnpm install すら通らない状態です。
すべてのPRをクローズして手動でまとめてアップデートすることになりました。Renovateが自動化のために作ったPRを捨てて手作業に戻るのでは本末転倒です。
Reactモノレポ(react、react-dom)やAstroモノレポ(astro、@astrojs/*)ではこの問題は起きません。Renovateのビルトインmonorepo presetに登録されており、デフォルトでグルーピングされるためです。Cloudflare Workers SDKはこのpresetに含まれていないため、ユーザー側でグルーピングを設定する必要があります。
packageRulesでグルーピングする
Renovateの packageRules を使えば、特定の条件に合致するパッケージをグルーピングできます。Cloudflare Workers SDKのパッケージをまとめるには、matchSourceUrls でソースリポジトリのURLを指定し、groupName でグループ名を設定します。
{
packageRules: [
{
groupName: "cloudflare workers-sdk",
matchSourceUrls: ["https://github.com/cloudflare/workers-sdk"],
},
],
}
matchSourceUrls はRenovateがnpmレジストリから取得するパッケージメタデータの repository フィールドを参照します。パッケージ名を個別に列挙する必要はありません。新しいパッケージがモノレポに追加されて依存に加えた場合も、自動的にグルーピング対象になります。
ラビー合同会社では、labee.jpとlabee.devの両方で使う共通のRenovate設定をGitHub Organization配下の .github リポジトリに配置しています。各リポジトリの renovate.json5 は、この共通設定をextendsで参照するだけのシンプルな構成です。
// .github/renovate.json5(共通設定、抜粋)
{
extends: [
"config:best-practices",
":timezone(Asia/Tokyo)",
":prHourlyLimitNone",
":prConcurrentLimitNone",
"schedule:earlyMondays",
"customManagers:biomeVersions",
],
packageRules: [
{
matchUpdateTypes: ["minor", "patch", "pin", "digest"],
automerge: true,
},
{
groupName: "cloudflare workers-sdk",
matchSourceUrls: ["https://github.com/cloudflare/workers-sdk"],
},
],
}
// 各リポジトリの renovate.json5
{
$schema: "https://docs.renovatebot.com/renovate-schema.json",
extends: [
"github>LabeeHive/.github:default.json5",
],
}
GitHubGitHub - LabeeHive/.githubContribute to LabeeHive/.github development by creating an account on GitHub.
Cloudflare Workers SDKを使うリポジトリが複数あるため、グルーピングを共通設定に入れています。各リポジトリで同じpackageRulesを書くのは冗長ですし、新しいリポジトリを作ったときに設定漏れが起きます。
matchSourceUrlsとmatchPackagePatternsの違い
グルーピングの条件指定には matchSourceUrls のほかに matchPackagePatterns や matchPackageNames も使えます。
matchPackageNames は、パッケージ名を直接列挙する方式です。
{
groupName: "cloudflare workers-sdk",
matchPackageNames: [
"wrangler",
"@cloudflare/vite-plugin",
"miniflare",
],
}
対象が明確ですが、モノレポに新しいパッケージが追加されて依存に加えた場合、設定の更新が必要です。
matchPackagePatterns は正規表現でパッケージ名をマッチさせます。@cloudflare/ で始まるパッケージをまとめられますが、@cloudflare/ai や @cloudflare/d1 など、workers-sdkモノレポに含まれないCloudflareパッケージも巻き込む可能性があります。wranglerやminiflareは @cloudflare/ スコープではないため、別途追加も必要です。
matchSourceUrls はnpmレジストリのメタデータに含まれるソースリポジトリURLでマッチさせます。cloudflare/workers-sdk リポジトリに含まれるパッケージだけが対象になるため、過不足なくグルーピングできます。このモノレポには create-cloudflare など無関係なパッケージも含まれますが、プロジェクトの依存に含まれていなければPRの対象にはなりません。依存に含まれないパッケージが巻き込まれる心配はありません。
なお、matchSourceUrls はnpmパッケージの repository フィールドを参照します。このフィールドが未設定のプライベートパッケージでは機能しないため、その場合は matchPackageNames で明示的に列挙してください。
グルーピング後の運用
グルーピング設定を追加した後、次のRenovate実行で効果を確認できます。labee.devでは以前、@cloudflare/vite-pluginとwranglerが別々のPRとして作られていましたが、設定変更後は「chore(deps): update cloudflare workers-sdk」という1つのPRにまとまっています。
@cloudflare/vite-pluginとwranglerが同じPRに含まれることで、exact versionの整合性が保たれた状態で pnpm install が走ります。個別PRをクローズして手動対応する作業は不要になりました。
automergeとの組み合わせも有効です。ラビー合同会社の共通設定では、minor、patch、pin、digestのアップデートタイプに対してautomergeを有効にしています。グルーピングされたPRがCIを通過すると自動マージされるため、Cloudflare Workers SDKのアップデートは完全に自動化されています。
ただし、グルーピングはアップデートのタイミングを揃えるものであり、互換性を保証するものではありません。majorアップデートはautomerge対象外です。特にwranglerのmajorアップデートではデプロイ設定の変更やAPIの非推奨化が伴うことがあるため、CHANGELOGを確認してからマージしてください。
monorepo presetの状況
Renovateのmonorepo presetに登録されれば、ユーザー側のpackageRules設定は不要になります。Cloudflare Workers SDKについてはmonorepo presetへの追加を提案しています。
GitHubAdd cloudflare/workers-sdk to monorepo presets · renovatebot/renovate · Discussion #42605Tell us more. cloudflare/workers-sdk is a monorepo that publishes several tightly coupled packages such as wrangler, @cloudflare/vite-plugin, and miniflare. These packages must be upgraded together...ただし、repoGroups でリポジトリ全体を登録する方式ではimmortal PRsの問題があります。cloudflare/workers-sdk の各パッケージはバージョン体系が異なるため(wranglerは 4.x、miniflareは 4.YYYYMMDD.x、@cloudflare/vite-pluginは 1.x)、バージョンが揃わずPRが更新され続ける可能性があります。
この問題を踏まえ、patternGroups で密結合なコアパッケージのみを登録する方向で検討中です。presetへの追加が実現するまでは、ユーザー側でのpackageRules設定が必要です。