[GitHub] モノリポ(npm workspaces)環境でサブプロジェクトごとに Grouped version updates for Dependabot を構成する際の注意点
こんにちは、CX 事業本部 Delivery 部の若槻です。
GitHub でコードの依存関係の管理を効率化できる Dependabot は、npm workspaces により構成されたモノレポ環境でも利用が可能です。
次のように構成ファイルでルートディレクトリを対象とすると、すべてのサブプロジェクトをアップデートの対象とすることができます。
version: 2 updates: - package-ecosystem: npm directory: / schedule: interval: daily
また、次のようにサブプロジェクトごとにアップデートを構成することもできます。サブプロジェクトごとにコードオーナーが異なっている場合にも便利です。
version: 2 updates: - package-ecosystem: npm directory: / schedule: interval: daily - package-ecosystem: npm directory: /sub1 schedule: interval: daily - package-ecosystem: npm directory: /sub2 schedule: interval: daily
さて今回は、上記のようなモノリポ(npm workspaces)環境でサブプロジェクトごとにアップデートする構成を Grouped version updates と組み合わせた際の注意点についてです。
サブプロジェクトごとのアップデートと、Grouped version updates を組み合わせた場合、期待動作とならない
Grouped version updates を使用すると、依存関係をアップデートする Pull Request をアップデートごとにまとめることができます。使用しなければ、依存関係ごとに Pull Request が作成されてノイズとなるため、Dependabot を利用する上では実質必須の機能と言えます。
サブプロジェクトごとにアップデートを構成している場合は、次のようにアップデートごとにグループを設定します。
version: 2 updates: - package-ecosystem: npm directory: / schedule: interval: daily groups: rootDpendencies: patterns: - "*" - package-ecosystem: npm directory: /sub1 schedule: interval: daily groups: sub1Dependencies: patterns: - "*" - package-ecosystem: npm directory: /sub2 schedule: interval: daily groups: sub2Dependencies: patterns: - "*"
上記構成を実際に動かしてみます。ルートおよびそれぞれのサブプロジェクトの package.json
に古いバージョンの依存関係を追加しておきます。
すると、プロジェクトごとに Pull Request が作成されました。
しかしルートの Pull Request にはロックファイル(package-lock.json
)に加えて、ルートだけでない各プロジェクトのマニフェストファイル(package.json
)の変更が含まれています。
一方でサブプロジェクトの Pull Request には、マニフェストファイルの変更のみが含まれています。
Grouped version updates を構成しない場合のように、プロジェクトごとにロックファイルおよび定義ファイルの変更が含まれることが期待動作 でしたが、残念ながらそうはなりませんでした。
この場合、ルートプロジェクトを更新する Pull Request の更新をマージするまでロックファイルの変更が反映されないため、ロックファイルの更新をもとに依存関係のインストールを CI で行っている場合などに、依存関係アップデート後のソースコードを CI がチェックできなくなってしまいます。(すべての Pull Request をマージ後に初めてチェックできるようになる)
versioning-strategy を increase にしても解決しない
この問題は Dependabot の Issue にも上がっていましたが、そこには「versioning-strategy
で increase
を指定すれば良い」とありました。
versioning-strategy
は、Dependabot による依存関係アップデート時のバージョン管理方法を指定するオプションです。
versioning-strategy
のオプションには次の 6 つがあります。npm の場合は auto
がデフォルトです。
Strategy | Description(自動翻訳) |
---|---|
auto |
アプリケーションとライブラリを区別しようとします。アプリケーションの場合は increase 、ライブラリの場合は widen を使用します。 |
increase |
常に最小バージョン要件を新しいバージョンに合わせて増やします。範囲がすでに存在する場合、通常は下限のみが増加します。 |
increase-if-necessary |
元の制約が新しいバージョンを許可する場合は、制約をそのままにして、そうでない場合は制約を増やします。 |
lockfile-only |
ロックファイルのみを更新するためのプルリクエストのみを作成します。パッケージマニフェストの変更が必要な新しいバージョンは無視します。 |
widen |
可能な場合は、新しいバージョンと古いバージョンの両方を含めるように許可されるバージョン要件を広げます。通常、これは最大許可バージョン要件のみを増やします。 |
N/A |
一部のパッケージマネージャは、versioning-strategy パラメータを設定することをサポートしていません。 |
サブプロジェクトの Dependabot のジョブログを見ると、プロジェクトがライブラリだと判断されて widen
が使用されている様子です。
では、versioning-strategy
を increase
に指定してみます。
version: 2 updates: - package-ecosystem: npm directory: / schedule: interval: daily groups: rootDpendencies: patterns: - "*" - package-ecosystem: npm directory: /sub1 schedule: interval: daily groups: sub1Dependencies: patterns: - "*" - package-ecosystem: npm directory: /sub2 schedule: interval: daily groups: sub2Dependencies: patterns: - "*"
しかし上記変更を適用しても、サブプロジェクトの Pull Request には引き続きロックファイルの変更が含まれず、マニフェストファイルの変更のみが含まれる挙動となりました。
ジョブログを見ると、更新時のストラテジーは widen
ではなく bump
になっており、increase
が適用されていない様子です。
考えられる対処方法
対処方法としては、次のようなものが考えられますが、それぞれデメリットがあります。
No | 対処方法 | デメリット |
---|---|---|
1 | 手動で package-lock.json を更新する。 | PR のブランチをローカルにプルして更新するなどの対応が必要。 |
2 | 自動で package-lock.json を更新する。 | GitHub Actions ワークフローを別途構成する必要。 |
3 | 対象ディレクトリをルートのみとする。 | すべてのプロジェクトの依存関係の更新が一つの PR にまとまってしまう。 |
4 | Grouped version updates を使わない。 | 依存関係ごとに PR が作成されてしまう。 |
個人的には、サブプロジェクトごとに更新を適切にグルーピングする管理を自動化できる 2 番目の方法が良いと思います。
おわりに
モノリポ(npm workspaces)環境でサブプロジェクトごとに Grouped version updates for Dependabot を構成する際の注意点についてご紹介しました。
良かれと思ってプロジェクトごとにアップデートを分けたらまさかの挙動となってしまいました。余裕があれば Issue を出したいと思います。
以上