LIVESENSE ENGINEER BLOG

リブセンスエンジニアの活動や注目していることを発信しています

バージョニングの見直しとタグ・リリース作成の自動化

データプラットフォームグループ Livesense Brain チームの富士谷です。 機械学習基盤 Livesense Brain の開発・運用を行っています。

ここでは、Livesense Brain で開発するシステムのバージョニングの見直しと、 GitHub Actions を使ったタグ・リリース作成の自動化について紹介したいと思います。

はじめに

Livesense Brain では、開発するシステムのほとんどをコンテナ化しており、大きく「アプリケーション」と「コンポーネント」の2つに分けて開発しています。 「アプリケーション」は、例えば「マッハバイト向けのレコメンド」といった、特定の事業部向けにデータやサービスを提供するコンテナイメージを指します。 また、全社向けのA/Bテスト基盤(Brain Optimizer)も「アプリケーション」に位置づけています。

一方、「コンポーネント」は、複数の「アプリケーション」で共通して使える機能を切り出したコンテナイメージを指します。 例えば、レコメンドアルゴリズムをまとめたものや、自然言語処理の実装をまとめたものがあります。コンポーネントを開発した背景などは、こちらの資料をご確認ください。

事業横断組織でのMLシステム開発・運用と基盤設計 - Speaker Deck

アプリケーションやコンポーネントのリポジトリでは、master/mainにマージするかタグを作成したタイミングで、Cloud Buildを用いて、イメージがビルドされるようにしています。 また、GKEなどにデプロイする際に、利用するコンテナイメージのバージョンを指定するため、タグを付けて、バージョニングを行っています。

デプロイは以下のような流れで行っています。

  1. 各リポジトリでバージョン名のタグ・リリースを作成する
  2. manifestsを管理するリポジトリで、デプロイするコンテナイメージのバージョンを記載したPRを作りマージする

デプロイを集中管理する、という点について詳しくは、先日のblog記事をご確認ください。 made.livesense.co.jp

これまでの課題

これまで、アプリケーション、コンポーネントともに、セマンティックバージョニング(SemVer)を利用していました。SemVerは、後方互換性がある改変であるかがわかるため、複数のアプリケーションで利用されるコンポーネントには有用でした。 しかし、アプリケーションでは、その改変の影響を受けるものはコンポーネントに比べて少なく、後方互換性がない改変も多くなりがち(例えば、A/Bテストの開始・終了などmanifestsで管理するWorkflowなどの改変が必要なときには毎回メジャーバージョンを上げていた)で、SemVerのメリットをあまり享受できていませんでした。

さらに、リリース担当者が、前回のリリース以降のPRを確認し、メジャー・マイナー・パッチいずれのバージョンを上げるかを考えて、GitHub で手作業でタグ・リリースを作成しており、小さいながらも負担がありました。

まとめると、課題は以下のとおりです。

  • アプリケーションとSemVerの相性が悪い
  • SemVerはどのバージョンを上げるかリリースのときに考えるのが大変
  • 手動でタグ・リリースを作成するのが大変

そこで、今回、以下のような運用の変更と自動化に取り組み、手間の軽減を図りました。

  • アプリケーションはSemVerからCalVerに変更
  • コンポーネントはSemVerのまま、PRごとに上げるバージョンを明記
  • タグ・リリースを自動作成する GitHub Actions の導入

アプリケーションはSemVerからCalVerに変更

アプリケーションにおいては、後述するタグ・リリースの自動作成のため、Calendar Versioning(CalVer)を参考にしたバージョニングに変更しました。 CalVerの命名規則は様々ですが、「いつ作ったものかわかる」かつ「同日複数回のリリースも問題ない」ように、「vYYYYMMDD-コミットハッシュ7桁」(例: v20211202-abcdefg)という規則を採用しました。 これにより、人がどのバージョンを上げるべきかを考える必要がなくなり、自動化できるようになりました。 一方、コンポーネントについては、SemVerが有用であると考え、そのままにしました。

コンポーネントはSemVerのまま、PRごとに上げるバージョンを明記

SemVerの利用を続けるコンポーネントでは、後述のリリースの自動作成に用いるanothrNick/github-tag-actionの仕様に則って、PRごとに、PR作成者自らが、

  • メジャー(#major
  • マイナー(#minor
  • パッチ(#patch

のいずれに該当する改変であるかを、PRタイトルに明記するような運用にしました。 明示的に表現することで、後述する自動化にも繋がり、負担軽減にも繋がりますが、「このPRは後方互換性を損なうような変更ですが、#minor で大丈夫ですか?」のようなコミュニケーションが可能になるメリットもあります。

タグ・リリースを自動作成する GitHub Actions の導入

最後に、以下の2つを用いて、タグの付与、リリースの作成を自動化する GitHub Actions を各リポジトリで導入しました。

アプリケーションのリポジトリで用いたものは以下のとおりです。 これにより、mainへのマージで自動的に、「v20211202-abcdefg」のようなタグが付与され、さらにリリースが作成されます。

name: Bump version
on:
  push:
    branches:
      - main
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Get tag
        id: tag
        run: |
          echo "::set-output name=date::$(date +'%Y%m%d')"
          echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
      - name: Bump version and push tag
        uses: anothrNick/github-tag-action@1.36.0
        id: bump
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CUSTOM_TAG: v${{ steps.tag.outputs.date }}-${{ steps.tag.outputs.sha_short }}
      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          name: ${{ steps.bump.outputs.new_tag }}
          tag_name: ${{ steps.bump.outputs.new_tag }}

f:id:lvs-kf:20211206153445p:plain
GitHub Action 実行ログ

一方で、コンポーネントではSemVerを採用しているため、以下のような設定を用いました。 anothrNick/github-tag-action はSemVerが想定されているため、先程よりもややシンプルになります。 ちょっとした工夫として、DEFAULT_BUMP を none にしておくことで、誤って、PRタイトルに#minor などを付け忘れても、後から手作業で付けられるようにしています。

name: Bump version
on:
  push:
    branches:
      - main
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: '0'
      - name: Bump version and push tag
        uses: anothrNick/github-tag-action@1.36.0
        id: bump
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          WITH_V: true
          DEFAULT_BUMP: none
      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          name: ${{ steps.bump.outputs.new_tag }}
          tag_name: ${{ steps.bump.outputs.new_tag }}

おわりに

今回、バージョニングの見直しと、タグ・リリースの作成の自動化について説明しました。 実際やったことは、少し運用を変えて、ちょっとした設定を追加しただけですが、 タグ・リリースの作成は、繰り返し行うような作業であり、このようなものを自動化しておくと、負担が軽減する効果を実感できます。 チームやシステムごとに適切なバージョニングは様々だと思いますが、参考になれば幸いです。