npm
フロントエンド
YARN
Renovate
ClassiDay 1

フロントエンド開発でパッケージのアップデートを継続的におこなう

フロントエンド開発でパッケージのアップデートを継続的におこなう

これは Classi Advent Calendar 2018 1 日目の記事です。
フロントエンドエンジニアの @kasaharu です。

はじめに

  • 昨今のフロントエンド開発はフレームワークと呼ばれるものから便利なライブラリまで幅広いパッケージを使って行われている
  • しかし、これらは導入したときのままであることが多く、バージョンアップすることを怠ると後々問題の原因になったりする
    • バージョンを上げないとセキュリティ問題に対応できなくなったり、パッケージそのものがサポートされなくなったりする
  • また、逆にバージョンを上げることでパフォーマンス改善などの恩恵を受けられる場合もあるが、その機会を損失していたりする
  • 今回は、できるだけ負荷にならずに継続的なパッケージアップデートを習慣化するために Renovate というサービスを使用しているのでそのまとめをする

Renovate とは

renovate.png

  • Automated Dependency Updates と謳っている
  • 対象リポジトリの package.json を監視し、パッケージに更新があった場合に Pull Request(PR) を作成してくれる
    • package.json の他に .circleci/config.yml や Dockerfile なども監視対象になる
  • GitHub, GitLab に対応しており BitBucket にも対応予定
  • GitHub の public リポジトリなら無料で使える

導入

  • Marketplace から "Open Source" プランを選択しインストールをする renovate_install.png
  • インストールすると GitHub - settings - Applications にアプリが表示される
  • Renovate の Configure ボタンを押して "Repository access" から Renovate を使いたいリポジトリを選択し、保存する
  • 対象のリポジトリに Renovate から "Configure Renovate" というタイトルの PR が届くのでそれをマージして設定完了
    • renovate.json が追加される
  • 設定が完了すると "Pin dependencies" というタイトルの PR が届くので問題なければマージする
    • 今の package.json に記載されている各パッケージのバージョンを固定
    • バージョンアップを Renovate にゆだねるので固定してしまって問題ない

特徴

  • package.json の他に Dockerfile, .circleci/config.yml も監視する
    • Docker image で使っている Node.js のバージョンアップなどにも使える
  • アップデートするパッケージの PR が open の状態で次のバージョンが出た場合、古い PR を自動でクローズして次の PR が作られる
    • PR が無駄にたまらない
  • まとめてアップデートしたほうがいいパッケージを Monorepo としてグルーピングして PR を作る仕組みがある
  • コンフリクトした場合は自動で rebase してコンフリクトを解消する
  • PR を手動でマージした後にブランチを消し忘れても Renovate が自動で削除する delete_branch.png

便利なオプション

オプション 説明
schedule Renovate が PR を作成する時間帯を指定できる
labels PR にラベルが設定でき Renovate から来た PR かどうかを一覧ですぐに判別できる
automerge 「patch バージョンは auto merge」や「devDependencies は auto merge」などの設定が柔軟にできる
rebaseLabel GitHub の PR に該当のラベルをつけると即時 rebase が行われる
デフォルトは "rebase"
enabled 特定のパッケージはバージョンアップの対象外にすることが可能
lockFileMaintenance lock file のメンテナンスが可能

Classi での使い方

renovate.json
{
  "extends": [
    "config:base"
  ],
  "timezone": "Asia/Tokyo",
  "schedule": ["every weekend"],
  "labels": ["renovate"],
  "patch": { "automerge": true },
  "lockFileMaintenance": {
    "enabled": true,
    "schedule": [
      "before 3am on the first day of the month"
    ]
  },
  "packageRules": [
    {
      "groupName": "Unit test package",
      "packagePatterns": ["^jasmine", "^karma"]
    },
    {
      "groupName": "Angular DevKit",
      "packagePatterns": ["^@angular-devkit/"]
    },
    {
      "packagePatterns": ["^mysql"],
      "enabled": false
    }
  ]
}
  • assignees, reviewers にはチームメンバーを指定
  • スケジューリング : 毎週末
    • これにより月曜日にはアップデートが必要なパッケージの PR が作られている
  • patch バージョンアップは auto merge

    • PR を作成して、マージするまでを Renovate が自動でやるのでパッケージアップデートにかける時間を削減できる auto_merge.png
  • PR に "rebase" ラベルをつけることで即時 rebase するように設定
    rebase.png

  • グルーピング機能を使って angular-devkit などのパッケージを 1 つの PR で作成する

    • グルーピング設定するとそれぞれ作成されていた PR は自動でクローズされ、新規でグルーピングされた PR が作られる
angular-devkit/build-angular 単体 angular-devkit/build-ng-packagr 単体 Grouping 後
a.png b.png c.png
  • Docker image で使用している MySQL のバージョンは Renovate で変更したくないので "enabled": false にしている
  • 毎月 1 日 3 時に lock file(yarn.lock) のメンテナンスをするように設定
    • package.json に記載されているパッケージのアップデートをやっていても、依存しているパッケージのバージョンでハマったことがあったので lock file も定期的にメンテナンスするように設定

まとめ

実際に仕事で使い始めて 2 ヶ月以上経過しましたが、毎週月曜日の定期作業として習慣化してきました。
テストが通ることで動作保証するため、単体テストのコードカバレッジ 100% をルール化し、テストを書くモチベーションの一つにもなっています。
code_coverage.png

また、こまめに上げることで major バージョンアップ時もあまり時間がかからないのを実感しています。
これを読んだ人も是非試してみてください。

明日は @tetsuroito さんです。

参考