🚀

mikanのバックエンドのリリースフローを見直しました

2024/01/23に公開

はじめに

株式会社mikan バックエンドエンジニアのgamiです。
最近、mikanのバックエンドチームのリリースフローを見直したので記事にしてみました。
まだ運用開始したばかりで参考になる情報は少ないかもしれませんが、今後の改善点なども含めて紹介していきます。

これまでのリリースフロー

mikanのバックエンドでは様々なシステムが動いていますが、バックエンドチームでは主にmikan-apiとmikan-bffをメンテナンスしています。

この2つのシステムでは、2022年3月からGitLab Flowライクな運用をしていました。
mikanのバックエンドは開発環境、staging環境、本番環境の3つの環境があり、それに対応するmain、staging、productionの3ブランチがあります。

ブランチ運用の図

普段の開発ではmainからfeatureブランチを切り、featureブランチで開発を行います。
mainにマージすると、開発環境に自動デプロイされます。
開発環境のAPIは主にモバイルアプリを開発するチームから利用され、開発ビルドで参照されます。

エンジニア以外の社内向けにはstaging環境があり、こちらはstagingブランチにマージすると自動デプロイされます。
staging環境ではQAチームによる回帰テストや、必要であれば社内の他チームによる動作確認などが行われます。

staging環境で問題がなければ、本番環境へのリリースのためにproductionブランチにマージします。
こちらはマージと同時にtagが打たれ、Draft状態のGitHub Releaseが作成されます。

GitHub ReleaseをPublishすると、本番環境に自動デプロイされます。

作成されたリリース

リリース頻度

当時はリリース頻度に関しては特に決まりはなく、各プロジェクトの必要性に応じて担当者がよしなにリリースをしていました。
しかし、1ヶ月近く本番デプロイがされないとstagingとproductionの差分が膨大になるなど、不具合のリスクも高まるようになり、2022年10月頃からは週に1度のリリースをするようになりました。

Daily Deployments metrics
少し見づらいですが1週間おきにデプロイしており、hotfixがあると棒グラフの間隔が狭くなります

課題

上記の運用を2年ほど続けてきましたが、いくつか課題がありました。

コミットが貯まった時に不具合リスクが高い

よしなにリリースをしていた頃から比べると軽減されはしたものの、週1回のリリースにしてもコミットがたくさん積まれて差分が大きくなると不具合リスクが高まります。
差分が大きいことによるレビューの見落としや、仮に不具合が発生したときの原因特定が難しいなどの問題がありました。

また、マイグレーションの必要有無や、システム間のリリース順の依存関係なども考慮する必要があり、差分が大きいと見落としが発生しやすくなります。

2人体制なので、一人休むとリリースができずにコミットが溜まる

現在、mikanのバックエンドチームは2人体制です。
水曜から火曜までを開発の1サイクルとしており、サイクルの最終日にstagingデプロイ、翌日に本番リリースという形で運用しています。
staging環境も本番環境も、リリースにはブランチへのマージが必要、つまりPRのレビューが必要なため、一人が休むとリリースができずにコミットが溜まってしまいます。

直近では年末年始の休暇が良い例ですが、二人がそれぞれ休みを取るとリリースタイミングを逃してしまいます。
さらに年明け最初のリリースに関しては、12月最後のQAでバックエンドの不具合が発覚し、リリースを取りやめた分もあったので約1ヶ月分のコミットが溜まってしまいました。

大量の変更

hotfixの同期忘れ

リリースフローの中で、productionブランチからhotfixブランチを切って本番環境にデプロイすることがあります。
このとき、hotfixブランチにマージしたコミットをmainやstagingブランチにもマージする必要があります。
これを忘れると、本番環境と開発環境の差分が生まれてしまい、デグレの原因になることもあります。

大量の差分を何度も見ないといけない

上述したように、リリースフローの中でstagingやproductionブランチにマージする必要があるのですが、差分が大きくなる傾向があります。
このためレビューにはどうしても時間がかかってしまいます。

これからのリリースフロー

ここまでを踏まえると、リリースする際の差分が大きくなりすぎることが直近の課題であると考えました。
そこで、差分をなるべく小さくするために、まずはリリース頻度を上げることを検討しました。
それを実現するための変更点は以下の通りです。

  1. stagingブランチとproductionブランチを廃止
  2. 新たにreleaseブランチを作成し、releaseブランチへのマージでstaging環境にデプロイする
  3. リリースする際はGitHub Actionsを実行し、GitHub Releaseを作成してPublishする
  4. リリースはなるべく毎日行う

リリースフローの変更内容を一言で言えば、リリースフローのステップを1段階減らし、リリースの頻度を上げることにしました。
3.のGitHub Actionsに関して補足すると、次のワークフローを実行しています。

name: Create Release

on:
  workflow_dispatch:

jobs:
  create_release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Bump version and push tag
        id: tag_version
        uses: mathieudutour/github-tag-action@v6.1
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          release_branches: release
          default_bump: 'minor'
      - name: Create Release Note
        run: |
          curl \
          -X POST \
          -H "Accept: application/vnd.github.v3+json" \
          -H "authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
          https://api.github.com/repos/${{ github.repository }}/releases \
          -d '{"draft": true, "tag_name": "${{ steps.tag_version.outputs.new_tag }}", "generate_release_notes": true}'

これまでのリリースフローでも上記のワークフローを利用していましたが、トリガーが異なっています。(以前はproductionへのPRがマージされたら動くようになっていました。)
今回はworkflow_dispatchにしているので手動で実行する必要がありますが、GitHubのUIやCLIから実行できるようになっており柔軟性は上がっています。
この部分は今後も改善の余地があると思っています。

なお、重点的にQAしてもらいたい機能がある場合は、staging環境の状態をQAチームの回帰テストフローに乗せる必要があります。
QAチームの回帰テストフローは週1回なので、QAしてもらいたい機能はそのタイミングでstagingにデプロイすることになります。
毎日リリースすると回帰テストされずに本番にデプロイされてしまう機会のほうが多くなってしまうため、それらに関してはmainへのマージをせずにtopicブランチなどへのマージで留めておく必要があります。

回帰テストとリリースフロー
回帰テストされずにリリースされるコミットが生まれる

今後について

今回のリリースフローの変更によって、リリースの頻度を上げることでコミットが溜まりにくくなるアプローチを取りました。
しかし、まだ新しいリリースフローの運用を始めたばかりで、今後もさらに改善点が出てくると思います。
現時点で見えている課題は以下のとおりです。

staging環境へのマージを自動化

現状ではstaging環境へのデプロイは手動で行っています。
つまり、mainブランチからreleaseブランチへのPRを作成し、レビューをしてマージする必要があります。
開発ブランチからmainブランチへのマージの際に一度レビューはしているはずなので、基本的にはreleaseブランチへのマージは自動的に行っても良いと考えています。
こちらに関しては、NTTコミュニケーションズさんの開発者ブログの内容[1]が参考になりそうなので、取り入れてみたいと思っています。

QAをすり抜けた変更が不具合の原因になる可能性

上述したように、重点的に見てもらいたい機能以外は頻繁にリリースされることになります。
「これは回帰テストしてもらうべきだ」という判断がバックエンドチーム内部で完結してしまうケースが多くなるはずなので、課題になりそうです。
ユニットテストは書いていますがシナリオテストはまだまだ薄いので、シナリオテストの拡充などでカバーできないかなどは検討していきたいです。

おわりに

mikanのバックエンドチームのリリースフローの変更について紹介しました。
しばらく運用してみて、改善点などが見えてきたらまた記事にしたいと思います。

また、現在mikanではエンジニアを積極的に募集しています。
EdTech領域での開発に興味がある方は、ぜひご検討ください!
https://mikan.link/posts-1/eM9VdG5p

mikanに関するその他の情報はこちらもご覧ください。
https://mikan.link/careers

脚注
  1. リリース頻度を毎週から毎日にしてみた - NTT Communications Engineers' Blog ↩︎

mikan blog

Discussion