生産性向上ブログ

継続的な生産性向上を目指すエンジニアのためのブログ

Renovate で CircleCI Orbs のバージョンを自動で最新に更新する(ついでに Docker イメージタグも)

renovatebot.com

Renovate が CircleCI Orbs に対応していることを思い出したので、まとめてみます。

CircleCI Orbs のバージョン更新問題

CircleCI Orbs は、一言で言うと CircleCI の設定をモジュール単位でパッケージ管理するための仕組みです。設定の共通化や再利用でとても便利です。

www.kaizenprogrammer.com

CircleCI Orbs については過去に入門記事を書いたので、詳細はそちらをご参照ください。

個々の Orb は、基本的にセマンティックバージョニングでバージョンを管理しており、Orb の定義を .circleci/config.yml に記述するときは次のような指定方法があります。

cypress-io/cypress@volatile
cypress-io/cypress@1
cypress-io/cypress@1.5
cypress-io/cypress@1.5.1

volatile を指定すると、実行時におけるその Orb 最新バージョンを使用します。これはバージョンをいちいち指定しなくていいので一見楽ですが、メジャーアップデートで後方互換性がなくなってビルドが急に壊れたりする可能性があり危険なので、本格的な開発用途では使うべきではないでしょう。

1 を指定すると 1.x.y の中での最新バージョン、1.5 を指定すると 1.5.x の中での最新バージョンを使用します。セマンティックバージョニング的にはメジャーアップデート以外であれば後方互換性が保たれるので一見安全ですが、Orb の開発者がセマンティックバージョニングのルールを破ったりする可能性があり、必ずしもビルドが急に壊れないとは言えないです。

1.5.1 のように厳密にバージョンを指定すると必ず同じ Orb が使用されるのでリスクはなくなります。しかし、今度は Orb が更新されるたびに最新バージョンに更新していく手間が発生します。もし複数のリポジトリで同じ Orb を使っていたりすると、Orb の更新のたびに各リポジトリで更新作業を行っていくことになり、さらに手間です。

Renovate × CircleCI

renovatebot.com

上記の問題に対して、Renovate を使うと厳密にバージョン指定を行いつつ、Orb のバージョンを安全かつほぼ自動で最新に追従することができます。

Renovate とは

Renovate は、CircleCI Orbs だけでなく、Node, Golang, PHP, Python, Ruby, Docker など様々な言語やツールのパッケージ更新に対応しています。

www.slideshare.net

Renovate についての概要は、npm 中心ですがこちらのスライドがわかりやすいです。

従来の Greenkeeper とかですと依存パッケージのバージョン更新のプルリク作成までが自動で、テスト結果を確認してマージするのは手動でしたが、Renovate ではテストが通れば自動で更新を取り込むところまでできます。

設定のカスタマイズ性も高く、メジャー、マイナー、パッチアップデートでそれぞれ挙動を分けたり、特定パッケージだけ指定して挙動を変更することもできます。

github.com や gitlab.com 上では App をインストールすれば使えます。OSS CLI 版や有償のオンプレ版もあるので GitHub Enterprise や GitLab CE/EE や Bitbucket Cloud などでも使えるようです。

Renovate のインストール

ここからは GitHub 上で簡単にサンプルを動かしてみながら解説します。まずは、Renovate の GitHub App のインストールからです。

まずは、GitHub 上に適当にリポジトリを作成します。そして、適当に以下のような .circleci/config.yml を作成し、CircleCI のビルドを有効にします。

version: 2.1

orbs:
  cypress: cypress-io/cypress@1.4.0

(ジョブやワークフローの設定はなんでもいいので省略)

github.com

その後、↑ の GitHub App を開き Install を実行して、作成したリポジトリにインストールします。すると、リポジトリにオンボーディングのプルリクエストが自動で作成されます。

f:id:miya-jan:20190207085008p:plain

プルリクの内容としては、Renovate のデフォルトの設定ファイルを作成するだけです。これをマージするまでは Renovate はなにも自動で更新したりしません。

f:id:miya-jan:20190207085030p:plain

オンボーディングのプルリクエストをマージすると、また新たにプルリクエストが自動で作成されました。

f:id:miya-jan:20190207085054p:plain

これは、上記の設定で記述した cypress-io/cypress の Orb が最新でないため、更新するためのプルリクエストです。リリースノートとかも自動でとってきてコメントに入れてくれるのでわかりやすいです。

CircleCI Orbs の更新はデフォルトの設定だと次のような挙動になるようです。

  • volatile の Orb は無視
  • 範囲指定の Orb があると厳密にバージョン指定するプルリクエストが作成される(cypress-io/cypress@1.5 だと cypress-io/cypress@1.5.1 に直す)
  • 厳密にバージョン指定されてると最新バージョンへ更新するプルリクエストが作成される(上記画像のケース)

自動マージする設定

デフォルトだと自動でマージまでは行われないですが、renovate.json の設定を変えると CI が通ったら自動でマージするようにできます。設定オプションの詳細については公式ドキュメントを参照してください。

{
  "extends": ["config:base", ":automergePatch"]
}

例えば、上の設定ですとパッチバージョンアップや範囲指定のバージョンを厳密なバージョンに固定するための変更が自動でマージされ、ブランチの削除まで行われます。

他にも、設定すればプルリクの作成を省略することもできます。

Docker イメージのバージョンを自動更新する

ここまでは Orbs のバージョンの話でしたが、実は .circleci/config.yml 内の Docker イメージのバージョンも自動で更新してくれます。

f:id:miya-jan:20190207085236p:plain

また、設定で以下のように pinDigests: true を設定しますと Docker イメージを digests 指定で固定してくれます。

{ "extends": ["config:base"], "pinDigests": true }

f:id:miya-jan:20190207085215p:plain

Docker イメージは同じタグでも上書きで更新されることがあるので、ビルドの再現性を保ちたい場合はとても便利な機能です。設定すれば digest の自動更新も可能です。

CircleCI ユーザーなら Orbs を使っていなくてもこの機能だけで普通に便利だと思うので、ぜひ Renovate を試してみましょう。

Renovate の実行タイミング

実験中、GitHub App 版 Renovate の実行タイミングがいまいちわかりづらかったのですが、たぶん次のタイミングで実行されてるようです。

  • renovate.json が変更されたとき
  • Renovate が作成した変更がマージされたとき
  • 1 時間に 1 回

しかし、たまに 2 時間以上実行されないときもあったので、まだちょっとよくわかってない部分もあります。

まとめ

Renovate を使った CircleCI Orbs の自動更新について書きました。Orbs に限らず Docker のイメージタグの自動更新にも使えるので、とても便利だと思います。

Renovate の設定はとても柔軟なので、自分に合った設定を探求することが必要そうです。便利な一方で、新たな沼とも言えるかもしれません。設定を共有したり取り込んだりすることも可能なので、最強の設定を考えて公開していくのもいいと思います。

この記事を書いてる最中に issue を 1 つ見つけて登録したのですが、登録から 1 時間ほどで Fix されました。かなりアクティブに開発されているようなので、気になるところとか要望とかあればどんどんフィードバックしていくとよさそうです。