WHITEPLUS TechBlog

株式会社ホワイトプラスのエンジニアによる開発ブログです。

Renovate で Go の依存ライブラリを自動更新する

こんにちは!
コアシステム開発Gでテックリードをやっている古賀です。

私たちのチームで管理しているGoアプリケーションでは、可能な限り最新バージョンのライブラリを使うように「手動でこまめに」メンテナンスを行っていました。
具体的には、Google Cloud のリリースノートを見てSDKのアップデートをキャッチアップして、対象のライブラリを手動で更新するというものです。

しかし、ライブラリの更新頻度が高いため直近の業務を優先させている期間は更新が止まってしまうことや、Google Cloud 以外のライブラリでも更新有無を定期的にキャッチアップする手間があることに課題を抱えていました。

そこで、Renovate を導入して更新作業を自動化し、メンテナンスを安定的に実施できるようにしました。

本記事では次の内容を紹介します。

  • Renovate とは何か、なぜ必要なのか
  • Renovate のインストール方法
  • go.mod内の依存ライブラリを Renovate で自動更新する方法

Renovate とは何か

依存関係を自動更新するツール。 Renovate が実行されると Renovate は依存関係の参照を検索し、新しいバージョンが利用可能な場合は Pull Request を作成し、バージョンを自動的に更新してくれます。

なぜ必要なのか

依存ライブラリが多いとそれらのアップデートに追随して更新していくのはなかなか大変な作業です。
アップデートが頻繁なライブラリ(Google Cloud SDK, AWS SDK など)があれば尚更で、更新作業は後回しにされやすくなります。
Renovate を使って自動化することで作業負荷を軽減することができます。
つまり、少ない作業工数でアプリケーションを安全に利用できる状態を維持しやすくできます。

類似のツールに Dependabot がありますが、きめ細かい設定ができる点で今回 Renovate を選択しました。

前提

次のようなディレクトリ構成のリポジトリを事前に用意します。

.
├── go.mod
└── main.go


module renovate-golang-tutorial

go 1.23.3

require (
    cloud.google.com/go/firestore v1.14.0
    cloud.google.com/go/storage v1.36.0
    go.opentelemetry.io/otel v1.33.0
    go.opentelemetry.io/otel/sdk v1.33.0
)


package main

import (
    "cloud.google.com/go/firestore"
    "cloud.google.com/go/storage"
    "context"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/trace"
)

func main() {
    // 依存ライブラリを使用していることを示すためのコードです。特に意味はありません。
    firestore.NewClientWithDatabase(context.Background(), "", "")
    storage.NewClient(context.Background(), storage.WithJSONReads())
    trace.NewTracerProvider()
    otel.Tracer("example.com/basic")
}

go mod tidyを実行して go.sum を生成します。
使用する Renovate のバージョンは 39.107.0 です。

Renovate のインストール

GitHub App を使って Renovate をインストールする方法を記載します。
このアプリはパブリックリポジトリとプライベートリポジトリのどちらでも無料でインストールできます。

まず Renovate の Github App ページ に移動し、[Configure] ボタンを選択します。

私の場合、ユーザアカウントか組織アカウントかを選択する画面が表示されました。

Configureとあるのはアカウントに紐づくどこかのリポジトリで既に Renovate をインストールしているものです。
ここでは Configure が付いていない sample-account を選択し、リポジトリ選択画面が表示されました。

Renovate を実行したいリポジトリを選択して install ボタンを押します。
そうすると、次のような renovate.json をリポジトリルートに追加するPRが自動生成されます。

renovate.jsonconfig:recommended は使用する言語によらず多くのユーザに推奨される設定が施されているpresetsです。 presetsとは簡単に言うと、extends配列に加えることで使用できるビルトインの設定です。

Dependency Dashboard:依存関係の可視化

先程のPRをマージすると Renovate が動き出します。
そして早速、依存ライブラリを更新するPRを3つ作成してくれました。
1つのPRで1つのライブラリを更新するものになっています。

また、リポジトリの issue に「Dependency Dashboard」というものが作られました。

このダッシュボードはプロジェクトの依存関係やアップデート対象を一目で把握することができる代物です。
Openには Renovate が自動生成した更新PRのリンクがあり、Detected dependencies には go.mod 内の依存ライブラリが記載されています。

enabledManagers:パッケージマネージャーの制限

Renovate はパッケージマネージャーという概念に基づいて依存関係を検出・更新しています。
パッケージマネージャーは File MatchingDataSource という機能を持っていて、前者は設定した正規表現に合致する依存関係設定ファイルを見つけて依存関係を検出し、後者は抽出した依存関係に対して新しいバージョンを検索します。
具体的なパッケージマネージャーには gomod や npm, composer など様々なものがあり、ユーザはこれらを必要に応じて設定して Renovate が依存関係を適切に把握できるようにします。

先程PRが作成されたのは、gomod マネージャーがリポジトリ内で go.mod ファイルを見つけて依存関係を検出し、ライブラリの更新も見つかったため更新PRが作成されました。

デフォルトでは他のマネージャーも有効化されており、例えば次のような Dockerfile が含まれている場合、dockerfile マネージャーによって golang イメージのタグを最新版に更新するPRが作成されます。

FROM golang:1.23.3

WORKDIR /go/src

COPY go .
RUN GOOS=linux GOARCH=amd64 go build -o /go/main main.go
ENTRYPOINT ["/go/main"]

今回は go.mod のライブラリに限定して自動更新をかけたいため、enabledManagersgomod を指定することで、使用するパッケージマネージャーを限定します。

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:recommended"
  ],
  // 追加
  "enabledManagers": [
    "gomod"
  ]
}

postUpdateOptions:go mod tidy の実行

私がライブラリの更新作業を行うとき、まず go get <package>@version を実行してgo.modgo.sumを更新し、その後で go mod tidy を実行して不要になった依存関係を削除していました。

gomod マネージャーのデフォルトの挙動では go mod tidy が実行されず、go.modgo.sum に不要な依存関係が残ったままになってしまいます。
go mod tidy を実行するには、postUpdateOptionsgomodTidy を指定します。

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:recommended"
  ],
  "enabledManagers": [
    "gomod"
  ],
  // 追加
  "postUpdateOptions": [
    "gomodTidy"
  ]
}

ここまでの作業によって、手動で行っていた Go ライブラリの更新作業が Renovate によって自動化されました。

packageRules:マイナー・パッチ更新PRを集約

ここまでの設定では依存するライブラリ単位でPRが生成されます。
PR数が多くなると、CIリソースを多く消費してしまうことや、PRを人間がレビュー・マージする場合にヒューマンリソースを消費してしまうことが懸念されます。
セマンティックバージョニングに則っていれば、マイナー・パッチ更新は後方互換性が保たれていることを踏まえて、PRをまとめても良さそうです。

go.modの依存ライブラリでマイナー・パッチ更新PRを集約するには、次のようにpackageRules を記述します。

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:recommended"
  ],
  "enabledManagers": [
    "gomod"
  ],
  "postUpdateOptions": [
    "gomodTidy"
  ],
  // 追加
  "packageRules": [
    {
      // ①
      "matchManagers": [
        "gomod"
      ],
      // ②
      "matchDatasources": [
        "go"
      ],
      // ③
      "matchUpdateTypes": [
        "patch",
        "minor"
      ],
      // ④
      "groupName": "golang-modules-minor-patch-updates"
    }
  ]
}

packageRules はライブラリの更新PRをグループ化するためのルールです。このルールが一致するライブラリ更新は同一のPRにまとめられます。今回のルールは次の3つで構成されています。

  • パッケージマネージャーが gomod マネージャーであること(
  • DataSource が go であること(
    • gomod マネージャーが扱う Datasource には golang-versiongo があり、前者は go.modgo ディレクティブの更新を管理するものなので今回は対象外とし、後者を指定しています。
  • マイナー又はパッチアップデートであること(

上記が一致するPRはグループ化され、そのグループの名前が groupName で指定した値になります()。groupName はPRタイトルの一部として使われます。

ちなみに、メジャーバージョンの更新は上記ルールに当てはまらないため、ライブラリ単位でPRが作成されます。

上記設定を行うと、3つのPRに分かれていたものが1つのPRに集約されました。

よく使いそうな設定

頻出の設定をいくつか簡単に説明をします。
必要に応じて取り入れて、快適な Renovate Life を送りましょう。

prHourlyLimit

1時間あたりに作成されるPRの最大数を制限します。 デフォルトは20にすると制限は無しとなります。

Renovate がPRを一度に大量に作ると、CI リソースを滞留させてしまって困る場合などに、これを設定してPRの作成速度を落とすことができます。

{
  "prHourlyLimit": 10
}

label

PRにラベルを付与します。

{
  "labels": ["renovate"]
}

presetsを使って書くこともできます。

{
  "extends": [
    ":label(renovate)"
  ]
}

reviewers

PRのレビュワーを設定します。

{
  "reviewers": [
    "some-account"
  ]
}

schedule

Renovate にブランチの作成(≒ PRの作成)を許可する時間帯を cron 書式で定義します。 スケジュールのデフォルト値は「いつでも」で、cron で* * * * *を宣言するのと同じになります。

設定する際の注意点がいくつかあります。

  • Renovate は分単位の精度をサポートしていないため、分の値に * を使用する必要がある
  • また、定義する時間帯が短すぎると Renovate が実行されない可能性があるため、少なくとも3~4時間の時間枠を設けることが推奨
  • schedule を想定通り動かすには timezone の設定を行う(timezone, timezone preset)。

次のように設定すると、タイムゾーンが Asia/Tokyo で11時から15時の間にPRが作成されました。

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:recommended",
    ":timezone(Asia/Tokyo)"
  ],
  "schedule": ["* 11-15 * * *"]
}

さいごに

ホワイトプラスでは、ビジョンバリューに共感していただけるエンジニアを募集しています!
ネットクリーニングの「リネット」など、「生活領域×テクノロジー」で事業を展開しています。
弊社に興味がある方は、オウンドメディア「ホワプラSTYLE」をご覧ください。オンラインでのカジュアル面談も可能ですので、ぜひお気軽にお問い合わせください。

参考

Automated Dependency Updates for Go Modules docs.renovatebot.com