Dependabot 運用ノウハウ
- 以前の発表『コードとドキュメントの品質を上げる技術』の続きに近い話
- システム(とはいえ今回の運用対象のほとんどは静的サイト)を常に最新の状態に更新し続けるためにDependabotを活用している
- そのままでは意外と時間を取られるので、GitHub Actionsを使っていかに自律的に運用するかを考えているという話
- 対象エコシステムはnpmのパッケージとGitHub Actionsのアクションが多い
- npmのパッケージの場合、更新対象は直接依存のみとしている
- まともにメンテナンスされているライブラリやフレームワークであれば、内部の依存パッケージも更新されていくという考え
- 間接依存まで対象にすると大量のPRが作られ、Cloudflareのビルド制限などに引っかかる恐れもある
- マージ自体は自動化しているため(後述)、PRレビューの負荷自体は主な懸念ではない
- pnpmの場合、Dependabotのpnpmへの対応が限定的なため、そもそも間接依存の更新はサポートされていない
- セキュリティ修正も対象だが、主な位置付けは最新バージョンへの継続的な追従
- 静的サイトではセキュリティアップデートの恩恵は限定的
- 検出される脆弱性はビルド時に関わるものがほとんど
- ユーザに影響する脆弱性もフォーム等がなければあまり関係しない
- 静的サイトではセキュリティアップデートの恩恵は限定的
- 設定例: https://github.com/uyupun/tmp-official/blob/main/.github/dependabot.yml
PRの自動マージ
Section titled “PRの自動マージ”- DependabotがPRを作成したあと、GitHub Actionsのワークフローで自動マージを行う
- パッチ、マイナーバージョンの更新はビルドとプレビューが成功していれば自動マージ
- メジャーバージョンは後方互換性がない場合があるため、自動マージせず、ローカルで起動確認をしたり、リリースノートを確認する
- 設定例: https://github.com/uyupun/tmp-official/blob/main/.github/workflows/dependabot-auto-merge.yml
パッケージのグルーピング
Section titled “パッケージのグルーピング”peerDependencyの関係にあるパッケージは同一PRにまとめる必要がある- e.g.
reactとreact-dom、astroとstarlight - バラバラのPRで更新すると片方のバージョンのみが上がった状態になり、ビルドが通らないことがある
- 特にメジャーバージョンのアップデート時は注意
- 実際にエラーが起きたPR: https://github.com/uyupun/takada-semi/pull/157
- e.g.
dependabot.ymlのgroupsでまとめたいパッケージを指定することで、同一PRにまとめられる- 設定例: https://github.com/uyupun/takada-semi/blob/a68fe686e53497d23bc835e903d8b12ef2001432/.github/dependabot.yml#L12-L16
パッケージと設定ファイルのバージョン同期
Section titled “パッケージと設定ファイルのバージョン同期”- パッケージのバージョンと設定ファイル内のバージョンを合わせる必要があるケースがある
- e.g.
biome(設定ファイルの$schemaのURLにバージョンが含まれる) - 設定ファイルの例: https://github.com/uyupun/tmp-official/blob/ceae8eee938f1f8a6e48c98e034fe81a4f5dedea/biome.json#L2
- e.g.
- Renovateを使えばこの同期を自動化しやすいが、すでにDependabotを使っており、依存サービスを安易に増やしたくない
- 代わりにGitHub Actionsで
package.jsonの更新を検知し、Biome等の特定のライブラリの更新に合わせて設定ファイルのスキーマバージョンも更新するワークフローで対応 - 設定例: https://github.com/uyupun/tmp-official/blob/main/.github/workflows/update-biome-schema.yml
PRの自動マージのリトライ
Section titled “PRの自動マージのリトライ”- Dependabotはリポジトリ毎に同じ時間帯にまとめてPRを作成する
- 大量のPRが一気に作られると、GitHubの内部機構によって自動マージがブロックされることがある
- おそらくコンフリクト防止のための仕組みと思われる
- そのため、自動マージのワークフローが失敗したときに発火し、自動マージをリトライするワークフローを別途作っている
- ランダムな時間待機したあと、GitHub CLI経由で自動マージのワークフローを再実行する作り
- 設定例: https://github.com/uyupun/tmp-official/blob/main/.github/workflows/retry-dependabot-auto-merge.yml
サプライチェーン攻撃対策
Section titled “サプライチェーン攻撃対策”- 完全に対応できているとは言い難いが、いくつか考えていることはある
- 近年、サプライチェーン攻撃が頻発している
- 被害事例: Shai-Hulud、Trivy、LiteLLM、Axiosなど
- 従来は「常に最新バージョンへアップデートする」ことが脆弱性対策として有効だった
- Dependabotで常に最新へ追従し続けているのもその前提から来ている
- しかし自動更新がそのままサプライチェーン攻撃のリスクにもなり得るというジレンマがある
- リスクの整理
- ライブラリの脆弱性の影響は静的サイトなので比較的小さい
- ビルド後はただのファイル配置であり、ほとんどのライブラリの脆弱性はビルドプロセス中にのみ影響する
- ビルド後の静的サイトに脆弱性が残るパターンもあり得るが、ユーザ入力を受け付ける箇所が極めて少ないためリスクも小さい
- クレデンシャル漏洩はCIの脆弱性経由で起こり得る
actionlintである程度防げている- ただし、依存しているアクションの中身までは考慮できない
- 標的にされるリスクは有名リポジトリではないため攻撃者にとってのメリットは小さい
- ただし、管理している複数リポジトリのうち1つでも対応できていなければクレデンシャル奪取のリスクは変わらない
- 全リポジトリで横断的に対策する必要がある
- ライブラリの脆弱性の影響は静的サイトなので比較的小さい
- 方針
- 現状の自動更新の仕組みは恩恵が大きいので維持する
- バージョン固定ではなく、パッケージを検証するライブラリやAPIをCI/CDプロセスに別途組み込む形で対処できると理想的
- GitHub Actionsのアクションは現状
@v6のようにメジャーバージョンのみ指定しているが、SHAハッシュへ書き換えることは現実的な対処法として有効
- 運用系のタスクはどんどん自動化して手放していかないと、いずれパンクする
- 個人的にはCloudflare + GitHub Actions + Dependabotの組み合わせは、ほぼ無料で実現できる上に自由度が高くて良いと思う
- 今後はこういったワークフローにもAIが取り込まれていくと思うので、引き続き注視しつつ進化させていきたい