entry-header-eye-catch.html
entry-title-container.html

entry-header-author-info.html
Article by

GitLab を利用したプロジェクトに Scala Steward を導入して依存関係を継続的に更新する仕組みを作った話

はじめましての方ははじめまして。21新卒エンジニアの Javakky です。 今回は、リポジトリの依存関係を最新に保つための取り組みを始めたので、そのレポートになります。

背景

私の部署では Scala というプログラミング言語と sbt というビルドツールを利用して開発が行われています。突然ですが、当時の依存関係設定を抜粋してきたので見てみましょう。

f:id:pxvpxv:20220228115430p:plain
dependencies

DB 周りの依存関係だけでも見事に波線が出てしまっています。 もちろん、DB周りが特殊というわけではなく、多くの依存関係で最新ではない箇所がありました。

そんな中、ある脆弱性が話題になります。

www.jpcert.or.jp

当然弊社も他人事ではなく、急ぎ検証やライブラリのアップデートの対応を行いました。この件に関しては直接当該ライブラリを利用していなかったこと、間接的に依存したライブラリの更新でエラー等が発生しないことが幸いしましたが、各ライブラリに破壊的な変更があった場合には多くのリソースを消費することになっていたかもしれません。 そして、依存関係の更新を蔑ろにすると、小規模でも対応すべき脆弱性について見逃してしまっているかもしれません。

そこで、継続的に依存関係を構築する体制をツール・運用の両面から見直すことになりました。

Scala Steward の導入

まずは導入したツールについての説明です。

今回導入した Scala Steward は、 sbt プロジェクトに更新されていない依存関係を見つけた際に更新するマージリクエストを作成してくれる bot です。

もし、あなたのプロジェクトが GitHub のパブリックリポジトリにあれば、 repos-github.md にプロジェクトを追加するだけで利用することができます。

残念なことに弊社ではソースコードを GitLab で管理しているため、この方法は利用できませんでした。しかし安心して下さい! Scala Steward は docker イメージを提供しているため、 GitLab CI 上でも実行することができます。

github.com

CIの設定を行う

公式のドキュメントを参考に、以下のようにタスクを定義しました。

scalaSteward:
 only:
    refs:
      - schedules
    variables:
      - $TASK_NAME == "steward"
  image:
    name: fthomas/scala-steward:latest
    entrypoint: [""]
  variables:
    EMAIL: 'hogehoge@fuga.co.jp’ # ここに git の commiter にしたいメールアドレスを入れる
    LOGIN: 'scalasteward' # 任意の名前
  script:
    - ls -la $CI_PROJECT_DIR/
    - mkdir --parents "$CI_PROJECT_DIR/.sbt" "$CI_PROJECT_DIR/.ivy2"
    - ln -sfT "$CI_PROJECT_DIR/.sbt"  "$HOME/.sbt"
    - ln -sfT "$CI_PROJECT_DIR/.ivy2" "$HOME/.ivy2"
    - /opt/docker/bin/scala-steward --workspace "$CI_PROJECT_DIR/workspace" --process-timeout 30min --do-not-fork --repos-file "$CI_PROJECT_DIR/repos.md" --repo-config "$CI_PROJECT_DIR/.scala-steward.conf" --git-author-email "${EMAIL}" --vcs-type "gitlab" --vcs-api-host "${CI_API_V4_URL}" --vcs-login "${LOGIN}" --git-ask-pass "$CI_PROJECT_DIR/askpass.sh"
  cache:
    key: scala-steward
    paths:
      - .ivy2/cache
      - .sbt/boot/scala*
      - workspace/store

Access Token の生成方法

GitLab で MR を自動生成するには、アクセストークンを作成して渡す必要があります。

今回は1リポジトリが対象で、リポジトリのCIで動作させるため、 GitLabのアクセストークンの安全な選び方・使い方 にあるプロジェクトアクセストークンの使い方を参考にアクセストークンを生成しました。

また、プロジェクトのルートディレクトリに askpass.sh というファイルを作成してCIから読み込めるようにしました。

#!/usr/bin/env bash

echo "${SCALA_STEWARD_TOKEN}"

repos.md の作成

Scala Steward を動作させるには、CIを動かすリポジトリに repos.md というファイルを作成する必要があります。

- ${プロジェクト名}/${リポジトリ名}

schedules の設定

ここまでで、Scala Steward を実行するためのタスク定義が完了しました。ここからは、実際に定期実行するための設定をしていきます。

実行対象のリポジトリを GitLab ページで開き、左のタスクバーから CI/CD > Schedules を開きます。今回は新規スケジュール作成のため、New Schedule を選択しました。

Variables の設定について説明すると、 SCALA_STEWARD_TOKEN には先述したアクセストークンを、 TASK_NAME にはCI設定の時に決めた ‘steward’ をセットしました。

f:id:pxvpxv:20220228115531p:plain
schedule

生成されるMR

f:id:pxvpxv:20220228115600p:plain
mr

レビューの体制

さて、ここまでで依存関係の更新を自動で検出することができるようになりました 🎉 次は、私たちはどのようにこの MR をレビューしてマージしているのかについて説明していきます。

まず、担当者は弊チームのエンジニアが交代制で決めることになりました。 レビューについては、追加された全機能について影響がないかを目視で判断することは現実的でないため、以下2点を満たしていれば担当者がマージしてもよいということにしました。

  1. MRに記載されているリリースノートに、後方互換生を損なうような変更がないこと
  2. 自動テストにクリアしていること

まれに自動テストが失敗したり、追加の依存関係が必要になることがあるため、その場合には他のメンバーにレビューしてもらうことにしています。

生成頻度の設定については、公式のドキュメントを参考に毎日2個までのMRを生成するように設定しました。

updatePullRequests = "never"
updates.limit = 2

まとめ

Scala Steward を導入したことでリポジトリの依存関係を最新に保つ仕組みが完成しました。 sbt プロジェクトを利用している開発者のみなさんもぜひ試してみてください!

icon
javakky
決済周りの改善を中心に働いている2021年入社エンジニア。その名の通りJavaが好きなことで有名(?)で、最近はScalaを使える部署へ入ったらしい。