コンテンツにスキップ

ブランチ戦略(Gated GitHub Flow / develop ゲート)

目的

develop を CI ゲート(integration 相当)として扱い、main を出荷専用に固定する。短命な feature/* を大量に回せる運用に最適化し、monorepo の影響集合(affected)と app 単位の昇格を前提にする。

ブランチ種別と役割

  • feature/<issue番号-短い説明>: 変更提案の単位。短命運用。CI の最小検証のみ。
  • develop: integration 相当のゲート(default branch)。PR 経由のみで更新。人が直接 push しない。
  • main: production の出荷確定。CI 昇格のみで更新。人が直接 merge しない。
  • hotfix/<issue番号-短い説明>: 緊急修正の例外ルート。main 起点で develop に戻す。
  • release/<バージョンまたは日付>: QA 凍結や並行リリースが必要な場合のみ使用。

CI/自動化マトリクス(運用方針)

  • feature/*: lint/type/unit(nx affected)のみ。deploy しない。
  • Draft PR では原則 CI を起動せず、Ready for review への変更を full CI の起点とする。
  • develop: 静的/契約/統合/安全チェック + staging deploy-ready artifact 作成。staging deploy は手動起動。
  • main: production 自動 deploy + smoke/canary/監視 + rollback。
  • hotfix/*: production 直行 + smoke/canary/監視 + rollback。

PR 自動化と昇格フロー

  1. feature/* push で develop 宛 PR を自動作成/更新する。
  2. CI が green かつ irreversible でなければ develop へ auto-merge。
  3. develop で CI が green かつ条件一致のときのみ main 昇格 PR を自動作成し auto-merge。
  4. 条件外は自動昇格せず、理由を PR コメントに残す。

main 昇格の完全自動条件(ALL MUST)

  • develop の CI がすべて green。
  • irreversible change が 無い
  • 影響集合が 単一 app に閉じている。
  • deploy が idempotent で rollback 可能。
  • global 変更(lockfile, nx.json, CI 設定, ルート設定)が 含まれない

Irreversible change の判定

以下のいずれかに該当する場合は auto-merge/自動昇格を禁止する。

  • apps/vendure-server/src/migrations/**
  • packages/contract/**
  • packages/domain/**
  • apps/vendure-server/src/auth/**
  • apps/vendure-server/src/config/**
  • infra/**
  • observability/**
  • 破壊的 SQL / migration の検出(DROP TABLE / DROP COLUMN / ALTER COLUMN など)

ブランチ保護(運用ルール)

  • develop は PR 必須。必須チェックは ci/required-develop を正本とする。
  • PR event: smoke gate(lint / typecheck / unit / coverage / worker)のみ必須。
  • merge_group event(Mergify queue train): heavy gate(integration / CT / Cloudflare build)を追加で必須化。
  • main は PR 必須。必須チェックは ci/required-main を正本とする。
  • develop / main の直 push を禁止する。
  • main への PR は CI 作成のみ許可する。

hotfix フロー

  1. main から hotfix/* を作成。
  2. 修正後に CI 通過 → main へマージし production deploy。
  3. 同じ変更を develop に戻す。

develop → main の昇格フロー

  • develop への merge で CI (push develop) が post-merge build / typecheck と staging 用 Vendure image build を実行し、deploy-ready な commit を固定する。
  • staging 検証が必要なタイミングで just manual-deploy-staging または GitHub Actions の Deploy Staging を手動起動し、同一 image を flyctl deploy --image ... で staging へ deploy する。
  • その後 Staging Smoke StorefrontDeploy Staging 成功を受けて staging を検証する。
  • smoke が成功した develop 反映だけが Promote Main の対象になる。
  • Promote Main が promotion PR を作成し、ci/required-main を通った PR だけが main へ昇格する。
  • main への merge では staging で build 済みの同一 image を production へ promote し、Fly 側 remote build は通常使わない。

main → develop の自動 back-sync(衝突防止の不変条件)

  • 不変条件: develop は常に main の内容を包含する(develop ⊇ main)。 これが保たれている限り develop → main の Promote PR は衝突しない(3-way merge が no-op になる)。
  • main は CI 昇格だけでなく、hotfix(main 起点の緊急修正)と release-please の version / CHANGELOG bump によっても直接更新される。これらは main 固有コミットになるため、放置すると developmain の部分集合でなくなり、次の promote が package.json / CHANGELOG / hotfix ファイルで衝突する(#1014 / #1015 で実際に発生)。
  • これを防ぐため、main への push を契機に Sync Main to Develop.github/workflows/sync-main-to-develop.yml)が maindevelop へ merge commit で back-merge し、develop へ直接 push するdevelop は branch protection 無しのため bot が PR を介さず push でき、GitHub 上の手動マージ操作を要しない
  • merge commit を使うことで develop の graph が main の tip を ancestor に取り込み、次回 promote の merge-base が main tip まで前進する → promote PR の diff は「develop の新規コミットのみ」になり構造的に衝突しない。
  • back-merge が衝突した稀なケースのみ workflow が abort して issue を立てる。手動で git switch develop && git merge origin/main で解消し(application logic は develop 優先、release/version bump は main 採用)、develop を push する。
  • hotfix を main に入れたら、この自動 sync を待つ(または手動で develop へ back-merge する)。develop への反映を省略しない。

release ブランチ採否

  • QA 凍結期間が必要。
  • 並行リリースが複数走る。
  • 上記がない場合は develop → main の昇格を優先する。

リベースとマージの使い分け(運用方針)

AI エージェントを含む開発者が競合解決に忙殺されないよう、以下の運用を推奨する。

  • Squash before Sync: develop を同期(rebase/merge)する前に、自分のブランチのコミットを 1 つに統合(Squash)する。これにより、1 つの衝突箇所に対して何度も同じ修正を行う「リベース地獄」を物理的に回避する。
  • Merge の許容: リベースによる履歴の線形化よりも、開発のスループットを優先する。リベース作業が 15 分を超える、あるいは衝突が非常に複雑な場合は、迷わず develop を自分のブランチに merge して作業を前進させる。
  • 同期のタイミング: 1 つの Directive の途中で頻繁に同期する必要はない。PR 作成時や、他の機能との依存関係が発生したタイミングで同期を行えば十分である。

よくある失敗パターンと回避策

  • リベース地獄: 細かいコミットが多数ある状態で rebase を開始し、同じ箇所の衝突を何度も解消し続ける。
  • 回避策: 同期前に必ず Squash してコミットを 1 つにする。
  • develop 直 push でゲート崩壊 → branch protection で禁止。
  • feature 長命化 → auto-PR と小さな PR 単位を徹底。
  • main 直 PR を許可 → CI 昇格専用に固定。
  • global 変更の見落とし → sharedGlobals で全体影響化。

worktree ガイド(短縮版)

  • 並列作業のためのローカル分離として使用する。
  • 常用は 3〜5 個まで。
  • 依存更新は Renovate PR を優先し、手動での並列依存更新を避けて lockfile 競合を抑える。

例:

git worktree add ../<repo>-<topic> -b feature/<topic> develop

依存更新(Renovate)

  • 依存更新 Bot は Renovate に一本化し、対象は npmgithub-actions に限定する。
  • 実行タイミングは develop 向けに週1回(月曜 09:00 JST まで)とする。
  • patch / minor は種類別にグルーピングし、ci/required-develop が green の場合に auto-merge を許可する。
  • majorDependency Dashboard 承認後にのみ PR を作成し、dependencies-major ラベル付き PR は auto-merge 対象外とする。
  • lockfile 競合が増える場合は Renovate の prConcurrentLimit4 から 2 へ下げて調整する。

リリースタグ運用

ルール

  • タグは annotated tag を使用する(手動作成時)。
  • SSOT は各 package の package.jsonversion とし、タグは同一番号で付与する。
  • root package (ritsubi-vendure) の version / CHANGELOG / vX.Y.Zrelease-please が管理する。
  • Storefront / Vendure Server の version / CHANGELOG / package tag は Changesets が管理する。
  • Storefront / Vendure Server を変更する PR では、release artifact only な変更を除き changeset を追加する。
  • 手動で version とタグをズラさない。自動化を優先する。

タグ形式

  • ルート(全体リリース): vX.Y.Z
  • Storefront: storefront-vX.Y.Z
  • Vendure Server: vendure-server-vX.Y.Z