🐾

GitHub ActionsでDBマイグレーションを自動化する Part 1

2024/12/07に公開

この記事は、tacoms Advent Calendar 2024の7日目です!
他メンバーのAdvent Calendarはこちらからご覧ください!👇
https://qiita.com/advent-calendar/2024/tacoms

はじめに

みなさんこんにちは、10月に株式会社tacomsのSREとしてジョインしたSREの はぶちん(@modokkin) です!
AWS re:Inventで発表される最新のアップデートが目白押しでテンションが上がる季節ですが、皆さんお元気でお過ごしでしょうか。

さて、今回はGitHubActionsとGo製のsql-migrateを活用してMySQLのマイグレーションの課題に向き合ったので、取り組んだことを3回に分けて記事にしたいと思います。

Part1では、課題整理とマイグレーション適用までの流れについて解説します。

  • Part1 課題整理とマイグレーション適用までの流れ 👈️この記事
  • Part2 手動トリガーでDry runを実行できるようにする
  • Part3 PRへのDry run結果投稿とマイグレーション適用

既存のマイグレーションプロセスの課題

まず初めに改善前がどのような状況だったか整理してみます。

  • sql-migrateを活用する前提でマイグレーションファイルは用意されていたが、実行環境に課題があり使えない状態になっていた。
  • 業務知識の高い特定のエンジニアがDBにログインして、手動でDDLを実行していた。合わせてマイグレーションの管理テーブルを手作業で更新していた。
  • マイグレーション適用タイミングが仕組みで担保できておらず、機能リリース前にマイグレーションを実行することを人間が覚えておく必要があった。

これまでは開発メンバーも少なく、コミュニケーションでカバーできていたのですが、最近メンバーが倍増したこともあり、早急に解決したい状況でした。

GitHub Actionsを選択した理由

まず前提としてバックエンドサーバーのデプロイの流れとしては、コードのテストやビルドはGitHub Actionsで行い、デプロイはAWS CodePipelineを活用し、AWS Fargateのサービスを更新していました。
インフラリソースの構築はもともとAWS CloudFormationを利用していたのですが、最近terraformに載せ替えたところでした。

そこでまずは、CodePipelineでなんとかできないかと挑戦しようと考えたのですが、私自身が不慣れだったことと将来的にはGitHub Actionsへの移行の足音が聞こえ初めていたので、思い切ってGitHub Actionsで構築することにしました。
ただ、デプロイプロセス全体をGitHub Actionsに移行するのは長期化しそうだったので、まずはマイグレーションプロセスの見直しを優先するため、独立してマイグレーションのワークフローを実現することにしました。

承認プロセスを検討する

GitHub Actionsで特定のワークフローを実行する際に、承認プロセスを組み込むにはどうしたら良いでしょうか。
AI様に聞いてみると真っ先ににEnvironment機能の活用を提案してくれました。公式ドキュメントにあるようにこの機能を使えば、確かにワークフロー実行時に承認プロセスを組み込むことが可能です。
但し、この機能はEnterpriseプランじゃないと使えませんでした。
https://docs.github.com/ja/actions/writing-workflows/choosing-what-your-workflow-does/using-environments-for-deployment

他の方法を調べて見ると、Kayac様の記事で2つのワークフローを組み合わせて実現している方法を見つけました。目からウロコでこんな方法があるのかと天を仰ぎました。
https://techblog.kayac.com/actions-manual-approval-without-environments

そして、さらに同僚からCode Ownersを組み合わせればええんちゃうの?と提案があり検証してみるとたしかにやりたいことが実現できそうでした。

Code Ownersとは

Code Ownersは特定のファイルやディレクトリのオーナーを決める仕組みでブランチの保護ルールと組み合わせることで様々な制限をかけることが可能です。
今回はマイグレーションに関連するファイルを含むPullRequestが作成された時に db-admins を必須Reviewerとして指定し、これらのメンバーのApproveがなければマージできないように制限しました。具体的にCode Ownersとワークフローを組み合わせたかについては別の記事で解説します。

  1. .github/CODEOWNERSに以下のような内容を書いておき、デプロイ用ブランチにコミットする
/.github/CODEOWNERS @example-org/db-admins # このファイル自体
/.github/workflows/*sql-migrate* @example-org/db-admins # Actionsのマイグレーションワークフロー自体の設定ファイル
/mysql/ @example-org/db-admins # マイグレーションファイルのpath
/mysql/execution/* # 除外したい対象を最後の行に書くと後勝ちで除外できる
  1. ブランチの保護ルールの設定で Require review from Code Owners にチェックを入れる。

ブランチの保護ルール

マイグレーションの流れ

途中試行錯誤はあったのですが、結果的に以下の流れで運用してみることになりました。

  1. 開発者が開発ブランチでマイグレーションファイルを作成し、開発環境でテストする。
  2. 開発が完了したらStaging環境のデプロイ用ブランチ向けのPullRequestを作成し、db-adminsチームにレビューを依頼する。
  3. db-adminsチームによるレビューが完了したら、db-adminsチームのメンバーがStaging環境にマイグレーションを適用する。
  4. マイグレーションが無事完了したらStagingブランチにマージする。その後は本番リリースプロセスで同様のフローを通る。

ここでのポイントは、コードだけが先行してリリースしないように必ずマイグレーションの適用が完了してからPullRequestをマージすることです。
デプロイプロセスに組み込んだ場合は、デプロイの手前で必ずマイグレーション適用することができるのですが、今回のケースでは運用ルールでカバーすることとしました。

つづく

今回の記事はここまでです。今後の記事では以下のような内容について触れたいと思いますので、お楽しみに!

  • どのような順序で実装を進めたか。
  • PullRequestにDry runワークフロー結果をコメントする方法。
  • GitHub Actionsのトリガーに関するあれこれ。
  • sql-migrateをecspressoを活用して実行する方法。
tacomsテックブログ

Discussion