Remix ✕ Cloudflareで最適なGitのブランチ運用と開発の運用を考える

## 概要

Remix ✕ Cloudflareのプロダクトのコードを管理するためのGitのブランチ運用と開発時の運用を考えてみたので簡単にまとめる。

## 最適（だと思っている）Gitのブランチ運用

まずはブランチ構成図を書いてみる。

```mermaid
gitGraph
   commit id: "初期コミット"
   branch preview
   switch preview
   branch develop
   switch develop
   commit id: "feature/fixブランチ作成"
   switch main
   commit id: "releaseブランチ作成"
   branch release
   switch release
   switch develop
   branch feature
   switch feature
   commit id: "機能追加"
   switch develop
   merge feature id: "developにPRでマージ"
   switch release
   merge feature id: "releaseにPRでマージ"
   switch preview
   merge release id: "previewにPRでマージ"
   switch main
   merge release id: "リリース" tag: "release-YYYYMMDD-XX"
```

※fixブランチはfeatureブランチと同様に運用

各ブランチについて簡単にまとめてみる。

| ブランチ名 | 情報 | 備考 |
| --- | --- | --- |
| main | Cloudflareの本番環境にデプロイされるブランチ | 直接のcommit・pushはNG |
| preview | Cloudflareのプレビュー環境にデプロイされるブランチ | 直接のcommit・pushはNG |
| develop | 最も歴史が進んでいるブランチ | 直接のcommit・pushはNG |
| feature | 最新のdevelopブランチから作成<br>名称は`feat/修正・開発内容を端的に英語で設定` | 開発中のコードをデプロイ環境で確認したい場合は本ブランチのコードを一時的にプレビュー環境にデプロイする |
| fix | 最新のdevelopブランチから作成<br>名称は`fix/修正内容を端的に英語で設定` | 修正中のコードをデプロイ環境で確認したい場合は本ブランチのコードを一時的にプレビュー環境にデプロイする |
| release | 最新のdevelopブランチから作成<br>名称は`release/リリース日のYYYYMMDD-XX` | 「XX」は通し番号<br>直接のcommit・pushはNG |

## 最適（だと思っている）開発の運用

### 開発 → PRの作成

開発は最新のdevelopブランチからfeatureブランチを作成して実施する。
PR作成前に必ずデプロイ環境での動作確認を行う。
開発中コードをデプロイ環境で試したい場合はfeatureブランチで`npm run preview`を実行し一時的にプレビュー環境にデプロイを行う。
開発が完了したらdevelopブランチに向けてPRを作成し、レビューを受ける。
コードレビューが通ったらPRをマージする。PRをマージしても当該のfeatureブランチは削除しないで取っておく。
developブランチにマージされた段階で当該の機能はリリース可能状態になったと判断する。

### リリース準備

機能のリリースが決まったら、リリースブランチを作成する。
リリースブランチは最新のdevelopブランチから作成する。
リリース対象機能の開発を行ったfeatureブランチをリリースブランチに向けてPRを作成する。このPRでは細かいコードのレビューは行わない。リリース対象機能とリリース対象機能の開発を行ったfeatureブランチが一致しているかをPRで確認する。
問題なければfeatureブランチ → リリースブランチのPRをマージする。
PRをマージしても関連するfeatureブランチは削除しないで取っておく。

念の為このリリースブランチを`npm run preview`を実行し、プレビュー環境にデプロイして動作を確認しても良いかもしれない。

### リリース（プレビュー環境での確認）

リリースブランチの準備ができたらいよいよリリース作業開始となる。
リリースブランチ → previewブランチのPRを作成する。このPRでは細かいコードのレビューは行わない。リリース対象機能の開発を行った関連するfeatureブランチがマージされていることを確認する
問題なければリリースブランチ → previewブランチのPRをマージする。
PRをマージしても当該のリリースブランチや関連するfeatureブランチは削除しないで取っておく。
ローカルリポジトリにて最新のpreviewブランチを取得し、マイグレーションなどDBへの変更がある場合このタイミングで変更を加え、`npm install`を実行後`npm run preview`を実行してプレビュー環境のデプロイを行う。
デプロイ完了後、プレビュー環境にブラウザからアクセスして問題なく動作することを確認する。

### リリース（本番反映）

リリースブランチ → mainブランチのPRを作成する。このPRでは細かいコードのレビューは行わない。リリースブランチにpreviewブランチへのPRマージ後から差分が無いことをのみを確認する。
問題なければリリースブランチ → mainブランチのPRをマージする。
PRをマージしても当該のリリースブランチや関連するfeatureブランチは削除しないで取っておく。
ローカルリポジトリにて最新のmainブランチを取得し、マイグレーションなどDBへの変更がある場合このタイミングで変更を加え、`npm install`を実行後`npm run deploy`を実行して本番環境のデプロイを行う。
デプロイ完了後、できる範囲で本番環境にブラウザからアクセスして問題なく動作することを確認する。
問題なければmainブランチの最新の状態でGitのtagを`release-YYYYMMDD-XX`のフォーマットで作成してpushする。

## バグが発生したら（まだ未経験なので最適解はわかっていない暫定版 + DBへのカラム追加などの変更が無い場合のみ）

バグが発生した場合、応急対応と恒久対応に分けたほうが良さそう。

※CloudflareのD1（DB）にはロールバックの機能が存在する。ただし、提供しているプロダクトがエンドユーザーの作業起因のCRUDがある場合、安易にD1でロールバックを行うとデータが消失しかねない。DBに変更を加える系のリリースでバグが発生したら、後述する応急対応は実施せず恒久対応を急ぐほか無いかもしれない。そんな状況を見越してドメインレベルでメンテナンス画面を出すことのできる仕組みを作っておくべきかもしれない。

### 応急対応

CloudflareのPagesの機能を使って一つ前のリリース時のデプロイにドメインの向き先を変える。（ロールバックする）

### 恒久対応

developブランチからfixブランチを作成し、バグの根本的な修正を行いリリースする。
fixブランチをリリースする際は単独でリリースすることが望ましい。バグ修正はなるべくシンプルにしておく。更に問題が発生した場合の切り分けが楽になる。

## 追記

普通にGitフローを参考にした下記のほうが良いかも。

```mermaid
gitGraph
   commit id: "初期コミット"
   branch preview
   branch develop
   switch develop
   commit id: "feat/fixブランチ作成"
   branch "feat"
   switch "feat"
   commit id: "機能追加"
   switch develop
   merge "feat" id: "リリースが決まってからdevelopにPRでマージ"
   commit id: "releaseブランチ作成"
   branch release
   switch release
   commit id: "動作に無関係な修正（必要があれば）"
   switch preview
   merge release id: "previewにPRでマージ"
   switch main
   merge release id: "リリース" tag: "release-YYYYMMDD-XX"
   switch develop
   merge release id: "動作に無関係な修正の差分をマージ（必要があれば）"
```