セルフホストGitLabでRenovateによる依存パッケージ自動更新環境を作った

インフラ

やりたかったこと

GitHubには Dependabot という、依存パッケージのバージョンを自動で上げてPRを出してくれる仕組みがあります。これと同じことを、セルフホスト版のGitLabでもやりたい、というのが今回の出発点でした。

結論から言うと、Renovate を使うことで簡単に実現できました。

Renovateとは

Dependabotと同様に、プロジェクト内の依存パッケージ・ライブラリを探し出し、新しいバージョンが出ていればマージリクエスト(MR)を自動で作成してくれるツールです。

  • プロジェクトの依存関係をスキャンして更新対象を検出する
  • GitHub上にリリースノートがあるパッケージは、その内容をMRの説明文に引っ張ってきてくれる
  • GitLabに対してMRを作成する

そして重要な点として、セルフホストのGitLabでも問題なく動作します

構築の流れ

1. Renovateを動かす環境(Runner)を用意する

Renovateを動かすためのDocker環境が必要になりますが、公式のDockerイメージが配布されているので、これをGitLab CIのジョブで指定するだけです。

あとは引数(環境変数)として、

  • GitLabを操作するためのトークン(MRの作成などに使う)
  • リリースノート取得のためのGitHubトークン

を渡してやれば、Renovateが動くRunnerが出来上がります。

.gitlab-ci.yml のイメージとしてはこんな形です。

renovate:
  image: renovate/renovate:latest
  script:
    - renovate
  variables:
    RENOVATE_PLATFORM: gitlab
    RENOVATE_ENDPOINT: https://gitlab.example.com/api/v4/
    RENOVATE_TOKEN: $RENOVATE_TOKEN        # GitLabのアクセストークン
    GITHUB_COM_TOKEN: $GITHUB_COM_TOKEN    # リリースノート取得用
    RENOVATE_AUTODISCOVER: "true"
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"

トークンはGitLabのシークレット変数(CI/CD Variables)として登録し、マスクしておきます。

2. Renovateの設定ファイルを書く

どのような条件でパッケージのバージョンを上げるかは、Renovateの設定ファイル(renovate.json)で細かく制御できます。設定項目は公式ドキュメントに網羅されているのでここでは詳しく触れませんが、最小構成はこの程度です。

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

3. パイプラインスケジュールを組む

GitLabのスケジューラーでRenovateのパイプラインを定期実行するようにします。

自分の場合は夜中から深夜にかけて動くように設定しました。こうしておくと、朝出社した時点でパッケージのバージョンアップのMRがプロジェクトに対して発行されている、という状態になります。

ハマりどころ

全体としては特に詰まるところはなかったのですが、2点だけ注意が必要でした。

npm:レンジ指定だと package-lock.json しか更新されない

npmモジュールを使っている場合、package.json のバージョン指定にキャレット(^)やチルダ(~)を使ってレンジで書いていると、Renovateが作るMRでは package-lock.json しか更新してくれません

これはRenovateの不具合ではなく、npmのバージョン管理(semver)の戦略に素直に乗っているだけです。新しいバージョンが既存のレンジを満たす限り、package.json を書き換える必要がないからです。その意味では正しい挙動なので、それ自体は問題ありません。

ただ自分の場合、Webアプリケーションとして package.json の値も固定しておきたかったので、ここで初めてレンジ指定をやめ、^ を削除してすべて固定バージョンにしました。

- "react": "^18.2.0"
+ "react": "18.2.0"

Renovate側の設定で rangeStrategypin にして固定させる方法もあるので、どちらのアプローチを取るかはプロジェクトの方針次第です。

{
  "packageRules": [
    {
      "matchManagers": ["npm"],
      "rangeStrategy": "pin"
    }
  ]
}

ポイント:レンジ指定のままだとロックファイルしか更新されない。 ここは事前に把握しておいたほうがよいところです。

C#/.NET:テストプロジェクトがデフォルトで除外される

RenovateはC#のプロジェクト(.csproj)に入っている依存関係も一緒に更新してくれます。

ただ、.NETの慣習としてテストコードは test / tests フォルダにまとめ、プロジェクト名も XXX.Test.csproj のようにすることが多いと思います。Renovateのデフォルト設定では、こうしたテストフォルダ配下は更新対象から除外される(ignorePaths のデフォルト値にテストディレクトリが含まれている)ようになっています。

そのため、テストプロジェクトの依存関係も更新したい場合は、ignorePaths を明示的に指定してデフォルトを上書きしてやる必要があります。

{
  "ignorePaths": [
    "**/node_modules/**",
    "**/bin/**",
    "**/obj/**"
  ]
}

デフォルト任せにせず、対象とするフォルダ/対象外とするフォルダを明示的に書いておくほうが事故が少ないと思います。

まとめ

  • セルフホストGitLabでも、Renovateを使えばDependabot相当の依存パッケージ自動更新環境が簡単に作れる
  • 公式Dockerイメージ + GitLab/GitHubのトークン + パイプラインスケジュールという構成で完結する
  • 深夜に実行しておけば、朝にはMRが並んでいる状態を作れる
  • npmのレンジ指定と、.NETのテストプロジェクト除外の2点だけは挙動を把握しておくとよい

導入コストの割にリターンが大きいので、セルフホストGitLabを運用している方にはおすすめです。

タイトルとURLをコピーしました