目次
はじめに
はじめまして、株式会社ブックリスタのプロダクト開発部に所属している伊藤です。
弊社開発のコミックアプリ、「コミックROLLY(運営:株式会社ソニー・ミュージックエンタテインメント)」のバックエンドエンジニアとして保守・開発を担当しています。
コミックROLLYは2023年8月1日にローンチしたアプリです。弊社のwebtoon制作スタジオである「booklistaSTUDIO」の作品をはじめ、さまざまなコミック作品を閲覧できます。ご興味ある方は是非下記のリンクからダウンロードいただけると嬉しいです。
この記事の目的
「コミックROLLY」のプロジェクトでは以下2点の課題を抱えていました。 - オープンソースパッケージを定期的にアップデート確認したい - パッケージアップデートのデプロイを機能リリースに干渉せず実行したい
この記事では課題にどう対応していったかをお話しさせていただきます。
コミックROLLYのシステムの構成について
まずコミックROLLYのシステム構成について説明します。
コミックROLLYのシステムは以下の3つで構成され、日々保守・開発しています。
- モバイルアプリ
- アプリに情報を渡すAPI
- アプリに出すコミック情報を管理するCMS
上記3つのシステムは使用言語、機能などオープンソースのものを使用しており、使用バージョンはyarnなどのパッケージマネージャーを通して管理しています。
パッケージ更新の悩み
上記の通り、オープンソースのソフトウェアを使用しているので、使用する機能は継続的にアップデートされて行きます。これらのアップデート反映を長期間放置すると、セキュリティの問題があったり重大なバグの修正を見落としたりするので、こちらもなるべく最新のアップデート状態を保つ必要があります。
ただし、コミックROLLYのプロジェクトがパッケージを随時アップデートしていくにあたっては以下2つの課題があります。
1つ目は「パッケージ更新の検知と内容確認が出来ない」ことです。
ローンチ前はパッケージマネージャーから直接アップデートで解決していました。ですがこの方法だとアップデート内容がどの程度影響するかがわかりません。ローンチ直前やローンチ以降アップデートの検知と変更・更新内容は確認してからアップデートするかを判断したいので、方法を再度検討する必要がありました。
2つ目は「機能リリースとパッケージアップデートリリースは同時に行えない」ことです。
コミックROLLYはソースをGitでバージョン管理しているので、パッケージのアップデートも同様にGitで管理したいです。ですが、普段の機能開発とパッケージアップデートを同じバージョンで管理すると、バグが発生したときに開発した機能自体の問題なのか、更新されたパッケージの問題なのかの切り分けが困難になります。
Renovate導入とブランチの分岐運用で解決
私たちは、上記の問題をRenovateの使用と、パッケージ更新用のブランチを用意することで解決しました。
Renovateとは
https://github.com/renovatebot/renovate
パッケージアップデートを自動で検出してくれるシステムです。GitHubなどのプラットフォームから使用できて、ボットがアップデートを検知、自動で更新用のプルリクエストを作成してくれます。 依存関係のあるパッケージも合わせてアップデート検知と更新をしてくれるので、悩みで提示した「①検知が必要なバージョンアップの数が多すぎる」はRenovateの使用で解決できます。
このRenovateで更新用プルリクエストのマージ先を指定できるので、パッケージ更新用のブランチを機能開発用のブランチと別で用意して管理することにしました。ブランチを分けることで、パッケージ更新のみのリリースのスケジュールを開発のリリースと別対応することが可能になり、悩みの「②機能リリースとパッケージアップデートリリースは同時に行えない」が解決します。
Renovateの設定と運用
以下に実際のパッケージ更新とリリースの解決方法の詳細を記載していきます。
①パッケージ更新検知の自動化
Renovateを使用してパッケージの更新の検知、パッケージ更新した状態のPR作成を自動で行うよう設定します。
私たちはGitHubでコード管理しているので、Renovateで用意されているGithub Actionsでの自動検知・更新のアプリを導入していきます。 登録対象のアプリは以下です。
https://github.com/apps/renovate
この設定時点では、すでに社内でRenovateを導入しているチームがあり、GitHubの組織アカウント単位で導入済みでした。なので組織アカウントの管理者に使用を要求して許可をいただくことですぐに使用可能になりました。
GitHubにRenovateのアプリを導入できたら、以下画像のように自動でRenovateの設定ファイル作成のプルリクエストが作成されるので、ここから各種設定をしていきます。
※https://github.com/marketplace/renovate から画像を引用しています。
設定値はプルリクエストの実施スケジュールやレビュワー、アサイニーの指定ができますが、コミックROLLYでは以下のように設定しています。
{ "extends": ["config:base", "schedule:nonOfficeHours"], "timezone": "Asia/Tokyo", "baseBranches": [{マージ元のブランチ名を設定}], "labels": ["renovate"], "automerge": false, "assignees": [{担当者のGitHubアカウント名を設定}], "assigneesSampleSize": 1, "prHourlyLimit": 5, "prConcurrentLimit": 100, "ignorePaths": [{renovateの自動更新対象から除外したいファイルのパスを設定}] }
この設定のプルリクエストをマージすると、以降はこちらが設定したスケジュールをもとに自動でパッケージ更新したプルリクエストを作成してくれます。 私たちのチームではassigneeに指定された人が主担当になるルールがあるのでassigneesを指定していますが、reviewersの指定も可能です。
②パッケージ更新用のブランチを用意する
Renovateの設定が終わったので、パッケージ更新用のブランチを設定していきます。
コミックROLLYではGitflowモデルを基準に以下のブランチで運用しています。
運用するブランチ名 | 役割 |
---|---|
feature | 機能追加用ブランチ 機能追加するためにdevelopブランチから切られる |
develop | 開発用ブランチ 機能の追加・改修が継続的にマージされる |
staging | リリース前確認用ブランチ Gitflowでいうreleaseブランチだが、随時確認できるようにプロダクト環境と同じ状態にして確認用環境のために常駐させる |
main | プロダクトリリースブランチ Gitflowでいうmasterブランチ |
パッケージ更新は機能開発と違うバージョンで管理したいので、stagingブランチから更新用ブランチ(名称:update)を作成します。
このブランチをRenovateでbaseBranches
に設定することで、パッケージ更新のマージ先がupdateブランチになり、機能開発とパッケージ更新の管理が別々に出来ます。
③パッケージ更新と機能改善のリリーススケジュールを分ける
ブランチを分けたことで関心が分離できたので、それぞれのブランチで更新・リリースが実行できます。
ただし、リリースを分けたことで、以下の問題が発生してしまいます。
- 機能開発で追加したパッケージが更新用ブランチにないので更新対象にならない
- パッケージ更新が一方で行われているので、機能開発側のパッケージが古いままになる
私たちのチームでは以下の画像のようにブランチ運用をして解決しています。
パッケージ更新のリリース
updateブランチにまとめられたパッケージ更新をリリース管理用ブランチ(stagingブランチ)にマージし動作検証を実施・完了後、mainブランチにマージしてリリースします。
リリース後はstagingブランチの内容をdevelopとupdateブランチにそれぞれマージすることで、updateブランチがdevelopと同期されます。
機能開発のリリース
developブランチにまとめられた開発機能をstagingブランチにマージ、検証後、mainにマージしてリリースします。
リリース後はstagingブランチの内容をdevelopとupdateブランチにそれぞれマージすることで、updateブランチがdevelopと同期されます。
上記のようにパッケージ更新・機能追加を別々にリリース、その内容をdevelop、updateブランチにそれぞれマージすることで先ほどの課題を解決できました。
まとめ
このようにパッケージ更新の自動検知と機能開発とパッケージ更新を分けることで、パッケージを最新の状態に保つことが出来ました。 同じような悩みを抱えている方の参考に少しでもなれば幸いです。