npm ライブラリ更新自動化 草案
ライブラリを定期的にアプデしたほうが良い理由
- Regular updates tend to be small
- アップデートの変更履歴は小さく、すぐに読めて理解しやすい。PR をマージするために必要な変更があったとしても数か所だけである可能性が高い。
- 変更履歴を定期的に読むことで、ライブラリにおける最新の方向性を感じ取ることができる。
- Applying major updates is easier
- 最新のベストプラクティスに従ったり、関数や変数の最新の名前を使用したりすることで、メジャーバージョンへのアップデートが容易となる。
- You'll be ready for CVE patches
- 最新バージョンがクリティカルな CVE (Common Vulnerabilities and Exposures, 共通脆弱性識別子) のパッチをリリースしたときにすぐに対応することができる。
- You'll look for ways to automate the updates
- 頻繁にアップデートをするようになると、アップデートを自動化する方法を探し始める。
ライブラリのアプデをサボってしまう理由
- Developers get blamed when things break in production
- 本番で障害が発生した時に開発者が責められる。
- There are no tests, so merging updates is scary
- テストがないので依存関係のアップデートをマージするのは怖い。
- The test suite is slow
- テストスイートの実行に時間がかかる。
- Releasing a new version of the project must be done by hand
- プロジェクトの新しいバージョンのリリースは手動で行わなければならない。
- Updating must be done by hand
- アップデートは手動で行わなければならない。
- The company doesn't allow developer time for updates
- 会社が開発者にアップデートの時間を与えない。
- The company has complex rules about updates
- 会社におけるアップデートのルールが複雑である。
Renovate
Renovate は以下のような流れで依存関係の更新 PR を自動で作成してくれる GitHub App である。
- The repository has a package.json and package-lock.json with version 1.0.0 of a dependency
(バージョンが 1.0.0 の依存関係があるとする)- Renovate sees that version 1.1.0 is available
(Renovate がバージョン 1.1.0 が利用可能であることを確認する)- Renovate patches the package.json to change the dependency's version from 1.0.0 to 1.1.0
(Renovate が package.json に手を加え、依存関係のバージョンを 1.1.0 に変更する)- Renovate runs npm install to let npm update the package-lock.json
(Renovate は npm install を実行し、package-lock.json も更新する)- Renovate commits the package.json and package-lock.json
(Renovate が package.json と package-lock.json の差分をコミットする)- Renovate creates the PR
(Renovate が 更新 PR を作成する)
Renovate はリポジトリにある CI/CD コンフィグや IaC ファイルのような DevOps 関連のファイル (Docker、Kubernetes、Terraform) も "パッケージマネージャ" として扱い、それらを見つけて更新することも可能とのこと。
インストール
ここ からインストールする。
登録が必要とのこと。
初期設定プルリク
インストールが完了すると、自動で初期設定用のプルリクを作成してくれる。
Welcome to Renovate! This is an onboarding PR to help you understand and configure settings before regular Pull Requests begin.
🚦 To activate Renovate, merge this Pull Request. To disable Renovate, simply close this Pull Request unmerged.
デフォルトの設定では、以下のように PR が作成される。
- 依存関係ごとに別々の PR となる
- メジャーアップデートとそれ以外のアップデートは別々に管理される
With your current configuration, Renovate will create 129 Pull Requests:
今回のプロジェクトの場合、初期設定のまま進めると 129 個のプルリクを作ってくれるとのこと。
流石に多すぎるため未使用のパッケージをいくつか削除したところ、プルリクが更新されていた。
Renovate will update your PR description each time it finds changes.
変化を検出するとプルリクを更新してくれるらしい。122 個に減った。
それでもまだ多いため、npm update --save
を実行してnpm i
し、ビルドエラーをいくつか解消したところ、半分ほど減らすことができた。
Dependency Dashboard
Renovate has a Dependency Dashboard that shows an overview of the state of your repositories' dependencies.
これを有効にしておくと、 すべての依存関係のアップデートに関するステータス (保留中, 対応中, 以前にクローズしたもの) をダッシュボードとして閲覧できる issue をリポジトリに作ってくれる。
また、選択した依存関係の新しいアップデートを承認するワークフローも可能となる。
{
"extends": ["config:recommended", ":dependencyDashboard"]
}
ちなみに、設定ファイルに問題があるかどうかは下記のコマンドで確認できる。
> npx -y -p renovate -- renovate-config-validator
INFO: Validating renovate.json
ERROR: Found errors in configuration
"file": "renovate.json",
"errors": [
{
"topic": "Configuration Error",
"message": "Invalid configuration option: hogehoge"
}
]
> npx -y -p renovate -- renovate-config-validator
INFO: Validating renovate.json
INFO: Config validated successfully
そして、破壊的変更を含みがちなメジャーアップデートについては、ユーザーが承認するまで更新 PR を作らないように設定することもできる。
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended", ":dependencyDashboard"],
"major": {
"dependencyDashboardApproval": true
}
}
npm package をアップデート
Renovate によって大量のプルリクが作られる前に、ある程度 npm package たちをアップデートしておきたい。
npm outdated
まずは、古くなっているパッケージを一覧で確認する。
npm outdated [<package-spec> ...]
This command will check the registry to see if any (or, specific) installed packages are currently outdated.
By default, only the direct dependencies of the root project and direct dependencies of your configured workspaces are shown. Use --all to find all outdated meta-dependencies as well.
-
wanted
:package.json
で指定されている semver[1] の制約を満たす最大のバージョン -
latest
: レジストリにて最新とタグ付けされているバージョン -
location
: パッケージが物理ツリーのどこにあるか -
depended by
: どのパッケージに依存されているか - 赤文字: semver を満たす新しいバージョンがあり、すぐアップデートするべきパッケージ
- 黄文字: semver 以上の新しいバージョン があり、注意して対応するべきパッケージ
npm update
次に、パッケージのアップデートを行う。
npm update [<pkg>...]
This command will update all the packages listed to the latest version (specified by the tag config), respecting the semver constraints of both your package and its dependencies (if they also require the same package).
最新バージョンにリストされた全てのパッケージを、sember の制約を満たしつつアップデートしてくれる。
使いそうなオプション
-
save
: インストールしたパッケージをpackage.json
に依存関係として保存する。 -
dry-run
: その名の通りドライラン。実際には実行しないが、実行した場合の結果を表示する。
> npm update --save
added 334 packages, removed 875 packages, and changed 661 packages in 3m
npm audit
最後に、パッケージのセキュリティ監査を行う。
npm audit [fix|signatures]
The audit command submits a description of the dependencies configured in your project to your default registry and asks for a report of known vulnerabilities. If any vulnerabilities are found, then the impact and appropriate remediation will be calculated.
The command will exit with a 0 exit code if no vulnerabilities were found.
0 exit code
(脆弱性皆無) を目指したい。
> npm audit
# npm audit report
...
34 vulnerabilities (2 low, 13 moderate, 10 high, 9 critical)
監査後に自動で修正できる分については下記コマンドで修正可能。package-lock.json
に差分が出る。
> npm audit fix
...
added 168 packages, and audited 7227 packages in 13s
...
31 vulnerabilities (2 low, 14 moderate, 10 high, 5 critical)
-
Semantic Versioning の略。APIの変更に互換性のない場合はメジャーバージョンを、後方互換性があり機能性を追加した場合はマイナーバージョンを、後方互換性を伴うバグ修正をした場合はパッチバージョンを上げるルールのこと。 ↩︎