週末のコーディング、楽しんでいますか?
個人開発を進めていると、依存関係の管理って意外と面倒ですよね。新機能の実装に集中したいのに、依存関係の更新に時間を取られることがしばしば...。ただ、依存関係の更新を怠ると、アップデート時の対応工数が高まりセキュリティリスクも無視できない状態になります。
この問題は個人開発だけでなく、大規模プロジェクトでも同様です。GitHub の事例がその良い例です。GitHub は以前 Rails のアップグレードに数ヶ月、時には年単位の時間を要していましたが、現在では毎週の自動更新プロセスを導入し、大幅な効率化を実現しています。
私も個人開発のリポジトリは半年に一回程度しか依存関係の更新をしていませんでした。その結果、まとめて依存のバージョンを上げようとすると問題の切り分けが難しく、細かくアップデートをするにも骨が折れました。リポジトリを複数管理しているともはや手に負えず、優先度が低いものは放置せざるを得ませんでした。
そんな状況を改善するため、Renovate を導入して依存関係の自動更新を始めてみました。この記事では、その経験と個人開発における依存関係管理の効率化について共有したいと思います。
Renovate について
Renovate は、プロジェクトの依存関係を自動的に更新してくれるオープンソースのツールです。
主な特徴は下記です。
- 自動更新: 定期的にプロジェクトの依存パッケージをチェックし、新しいバージョンがあれば更新のプルリクエストを作成します。
- 柔軟な設定: 更新の頻度、対象パッケージ、更新方法などを細かくカスタマイズできます。
- CI/CD 連携: GitHub Actions や Circle CI などの CI/CD ツールと簡単に統合できます。GitHub Actions の workflow に書いている依存も自動更新してくれます。
Renovate を使用することで、依存関係更新の対応コストの削減しつつ、プロジェクトを常に最新の状態に保つことでライブラリのバグや脆弱性にいち早く対応できます。
個人開発への Renovate 適用
私が個人で開発している企業テックブログ RSSでは、以下のような設定で Renovate を導入しています。他のリポジトリにも似た設定をしていて、今のところはこの形に落ち着いています。
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"schedule": ["every weekend"],
"timezone": "Asia/Tokyo",
"dependencyDashboard": false,
"automerge": true,
"branchConcurrentLimit": 0,
"prHourlyLimit": 0,
"labels": ["dependencies", "renovate"],
"packageRules": [
{
"matchUpdateTypes": ["patch", "minor"],
"groupName": "minor and patch dependencies",
"automerge": true
},
{
"matchUpdateTypes": ["major"],
"groupName": "major dependencies",
"automerge": false
},
{
"matchPackageNames": ["renovate"],
"enabled": false
}
]
}
この設定では、何かがあったときに目が通しやすい週末に稼働させています。
また、メジャーバージョンのアップデート以外は自動マージにしていて、最低限のテストによりデグレを防止しています。
設定すると以下ような PR が来るようになり、テストが通れば自動でマージされます。
それぞれの設定項目について簡単に説明します。
-
"extends"
: Renovate の推奨設定を使用 -
"schedule"
: 更新を週末に限定 -
"timezone"
: タイムゾーンを東京に設定。スケジュールが日本のローカルタイムで動作 -
"dependencyDashboard"
: false にして依存関係ダッシュボードを無効化。ここは好みによります -
"automerge"
: true に設定することで、条件を満たす更新を自動的にマージ。packageRules
で細かいルールを設定 -
"branchConcurrentLimit"
: 0 に設定することで、同時に作成できるブランチ数の制限をなくす -
"prHourlyLimit"
: 0 に設定することで、1 時間あたりの PR 作成数の制限をなくす -
"labels"
: 識別しやすいように PR にラベルを指定 -
"packageRules"
: 特定のパッケージや更新タイプに対する細かい設定- パッチとマイナーアップデートは自動マージを有効
- メジャーアップデートは自動マージを無効
- renovate パッケージ自体の更新は無効にします。私のリポジトリでは renovate.json の設定のバリデーション用に入れていますが、更新が多いので無効化しています。
より詳しい設定や導入方法などは、すでに他の方が丁寧にまとめているのでそちらを参考にしてください。
もし自動更新によるセキュリティの懸念が無視できないリポジトリであれば、もう少し慎重な設定にするのが良いでしょう。例えば Node.js のパッケージを開発しているならば、 color.js
の件のようなサプライチェーン攻撃を防ぐためにも、ある程度手動で運用することになります。
細かい Tips
Tips というほどでもないですが、 renovate パッケージ を入れていると、ローカルで書いた renovate.json
のバリデーションがすぐ回せます。
{
"scripts": {
"renovate-validate": "renovate-config-validator",
},
"devDependencies": {
"renovate": "^37.253.1",
}
}
$ yarn renovate-validate
また、asdf の .tool-versions
や nodenv の .node-version
などを置いていると、Node.js 自体のバージョンも同じ条件でアップデートしてくれます。
週末 Renovate の感想
「自動で PR が作成されて CI が通ってマージされる」というのが、単純に体験が良いですね。週末だけにしているのも、確認の工数的に個人開発においてはバランスがいいなと感じています。
マイナーバージョンアップでも時折テストが落ちることがありますが、問題の切り分けも簡単で修正が比較的楽にできます。ただ、テストをすり抜けて盛大にバグることもあったので、そのたびにテストを拡充していました。自動更新はリスクを伴うのでプロジェクトの規模や重要度によって条件は要調整です。
副次的な効果としては、依存関係の更新内容の情報が自然と入ってくる状態になったことや、最低限でもきちんとテストを書こうという意識が強くなったことでしょうか。
さいごに
しばらく運用してみていますが、個人開発のワークフローが改善されたのは実感しています。より本質的な作業へ集中できるようになったのは大きいですね。
一度設定してしまえば他のプロジェクトへの流用もしやすいので、投資としては十分に価値があるかと思います。
導入してみると面倒な点も見えてくるかと思いますが、まだやったことがなければ一度この自動更新を体験してみるのは本当におすすめします。