0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

#188 CGFにおける自動化の設計指針 〜 フェールセーフとしての考え方と優先順位

0
Posted at

はじめに

前回記事では弊社の実運用をベースに、CGF の運用フローを具体的な観点で整理していきました。


CGF は、

  • 運用は「最小限のルールで回せる」
  • 設計は「人に判断の余地がある」
  • 履歴の健全性を維持しやすい

という特徴を持つブランチ戦略です。


ここで重要なのは、CGF は「人の判断に依存する戦略」ではなく、
「人が判断する余地を持つように設計している戦略」である、という点です。


シリーズ過去記事でも述べているように、この特性は利点である一方、そのまま留意点にもなりえます。


要所の判断を人に委ねる余地が大きいということは、運用の仕方によっては

  • 判断基準が人によってブレる
  • 特定のメンバーに判断が集中する
  • 運用が属人化する

というリスクを内包しているからです。


これについては同記事内で、

恒久的なフェールセーフについては、「人に依存するルール」ではなく「仕組み化」で解決するべきだと考えています。

と位置付けていました。


本記事では、この点について更に掘り下げ
「CGF を前提とした運用において、どのような領域をどのように "仕組み化"(自動化)していくのが良いか」を整理していきます。


今回は、CGF で運用するにあたって

  • どこを自動化するべきか
  • どこまでを人に委ねるべきか

といった設計の指針について焦点を当てていきます。

  • どのツールを使って
  • どのように実装するか

といった具体的な手順まで取り上げると論点がまとまらないため、あまり深くは踏み込みません。


CGF の柔軟性を維持しつつ属人化を抑えた運用設計を考える上で、ひとつの指針として参考になれば幸いです。


シリーズ記事

  1. チーム特性から考える Git ブランチ戦略の選定
  2. Git ブランチ戦略選定で意識すべき4つのトレードオフ
  3. Git ブランチ戦略「Clean-history GitFlow」の紹介
  4. CGF 実践編 〜 要件確定から本番までの運用整理

1. フェールセーフとしての自動化とは何か

本記事における「自動化」は、一般的にイメージされるような「作業効率化」を主目的にはしていません。


もちろん、自動化によって作業時間が短縮されたり、手動作業が減る、といった副次的な効果はあります。


しかし、ここでの自動化の目的はあくまでも
「人の判断を前提とした運用において、発生しうる事故を防ぐための仕組み作り」であり、
フェールセーフとして機能するものです。


そのため、観点としては「ミスが起こることを前提」に、
それを防ぐ/影響を抑える 設計であることが肝要です。

1-1. フェールセーフの分類と適用の考え方

CGF は「厳守するべき運用ルール」が少ないため、

  • 「うちのプロジェクトの方針として」
  • 「メンバーのスキル的に、とりあえず今はここまでをルールとして」

といったニーズに対しても、戦略から逸脱せずに適用することができます。


特に、「チームの成熟度に応じた制限」や「暫定ルール」「例外もある程度許容したい」など

  • 後から変更される可能性がある
  • ルール自体に幅がある

といったものについては、一時的なフェールセーフとして運用ルールを設ける方が、
柔軟に調整できるため可変的で扱いやすいです。


一方、「そのルールに柔軟性は必要ない(ない方が良い)」といったものは
恒久的なフェールセーフとして仕組み化した方が、運用における事故の発生リスクを格段に抑えることができます。


運用ルールで吸収

  • 人の行動を制約することでリスクを下げるアプローチ
    • 例)レビューは必ず2人以上で行う、PR 作成後の rebase は原則禁止など
  • メリット
    • 比較的導入しやすく、チームの状況に応じて柔軟に調整できる
    • 例外を許容できる
  • デメリット
    • 守られない可能性がある
    • 判断基準が人に依存する
    • 属人化の余地が残る

仕組み化(自動化)で吸収

  • 「そもそも間違った状態にならない」ように制御する
    • 例)条件を満たさないPRは「マージできない」、指定以外の操作が「そもそも実行できない」など
  • メリット
    • 判断のブレが発生しない
    • 人に依存しない
    • 再現性が担保される
  • デメリット
    • ルール変更が手間
    • 例外を許容できない

1-2. 自動化の対象になる条件

上記からもわかる通り、すべての作業を自動化すれば良い、というものでもありません。


自動化にはそもそもコストがかかりますし、過度な自動化は柔軟性を損なう可能性もあります。
そのため「どこを自動化するか」は設計の問題になります。

  1. 判断の再現性が必要なもの
    • 人によって判断が変わると困るもの
    • 同じ条件であれば、常に同じ結果になるべきもの
    • 例)マージ方法の選択、検証環境の構築手順など
  2. ミスの影響が大きいもの
    • 一度のミスが大きな影響につながるもの
    • 後からの修正コストが高いもの
    • 例)本番環境へのリリース、develop ブランチへのマージ種別など
  3. 実行頻度が高いもの
    • 日常的に繰り返される操作
    • 人が手動で行うとミスが蓄積しやすいもの
    • 例)PR作成時・レビュー依頼時のチェックなど

これらの条件に当てはまる領域は、
「人の注意力や経験に依存させるべきではない」ポイントであり、
仕組みによって支える価値が高いと考えています。


「どこを自動化するか」は個別の手法ではなく、運用設計として捉えるべき視点です。

2. 「フェールセーフとしての自動化」における一般的な観点

前章で、「フェールセーフとして機能する自動化」には設計が必要であるということを確認しました。


では、その「設計」はどのような観点で考えれば良いのでしょうか。


ここでは、フェールセーフとしての自動化を考える上での一般的な観点を4つに整理し、
以降で扱う「CGF における具体的な設計指針」につなげていきたいと思います。

観点 目的 目指す状態 担保されない場合に
起こる問題
状態の再現
(環境・データ)
状態を揃える ・環境やデータの状態が人に依存しない
・検証結果が毎回同じ前提で得ることができる
・バグが再現できない
・検証結果の正しさが判断できない
操作の制御
(ブランチ・PR)
人的ミスを未然に防ぐ 「注意すれば防げるミス」を人に依存しない

例)
・誤った手順でのマージ
・想定外のブランチ操作
・必要な条件を満たさない変更が取り込まれる
・運用の不安定化
・リカバリに時間を使う
・意図しない形での例外の許容
認識ズレの防止
(可視化・共有)
コミュニケーションコストや手戻りの削減

※ 直接操作を制御するものではないが、認識齟齬による事故を防ぐための補助的手段
状態や前提条件を可視化し、チーム内での認識ズレを防ぐ

例)
・「今どの状態なのか」が一目でわかる
・どの変更がどこに反映されているのかが追える
・誰が何を前提に作業しているかが共有される
・状態や前提の勘違いによる誤操作
・過剰なコミュニケーションコスト負荷
品質担保
(テスト・検証)
・変更による不具合混入の検知・防止
・品質基準の一定化
・テストの自動実行
・静的解析や型チェックの自動化
・リリース前の検証プロセスの自動化
・見落としによる不具合混入
・レビューの抜け漏れ

繰り返しになりますが、これら4つの観点は「すべてを必ず自動化しなければならないもの」ではありません。


自動化はあくまで手段であり、

  • どの観点を重視するか
  • どこまで仕組みで担保するか
  • どこを人に委ねるか

といったバランスの取り方こそが設計になります。


すべて自動化したことで、却って柔軟性が失われたり、運用コストが増加する可能性もあります。
反対に、自動化が不足していることで、人に依存した不安定な運用になることもあります。


重要なのは、「何をどこまで自動化するか」を意図的に選択できることです。

3. CGF において優先するべき自動化の観点

確認した4つの観点を踏まえ、CGF における自動化の優先順位を見ていきます。


まずは前提として、CGF の特徴を改めて整理しておきましょう。

  • 履歴の健全性を重視する
  • 検証環境はリセットされることを前提とする
  • 人に判断の余地がある運用である

ここから、CGF における自動化の優先順位をある程度明確化することができます。


結論から言うと、優先するべき観点は以下の2つです。

  • 状態の再現(環境・データ)
  • 操作の制御(ブランチ・PR)

では、何故この2つが重要なのか、もう少し詳しく見ていきましょう。

3-1. 優先的に自動化したい観点

状態の再現(環境・データ)

状態の再現性が担保されない場合、検証そのものの信頼性が崩れます。

  • 同じ変更であっても結果が変わる
  • バグが再現できない
  • → 「直ったかどうか」「期待動作かどうか」の判断ができない

これは単なる不便さの問題ではなく、
検証というプロセス自体が成立しなくなることを意味します。

操作の制御(ブランチ・PR)

操作の制御がされていない場合、人為的なミスがそのまま履歴に反映されます。

  • マージ方法・順序の誤り
  • 想定していないブランチ操作
  • 条件を満たしていない変更の取り込み
  • → 履歴の健全性を直接的に損なう要因

CGF は履歴の健全性を重視した戦略であるため、
ここが崩れると運用全体が不安定になります。


これらはどちらも「CGF の前提そのものを支える領域」であり、
優先的に「仕組みとして」フェールセーフを設けるべき対象です。

3-2. その他の観点と位置付け

認識ズレの防止(可視化・共有)

直接的に「事故を防ぐ」ものではなく、あくまでも補助的な役割となるため、優先度は低いです。

品質担保(テスト・検証)

品質担保は重要な観点であり、自動化しておいて損はない部分ですが

  • チームの成熟度
  • プロジェクトの特性
  • テスト戦略

といった要因にも依存しており、CGF 運用特有の設計論とは異なるため
本記事では「CGF 運用において必須とは言えない領域」という立ち位置にしています。

これらは、他の要素との兼ね合いがあり、「発展的に検討する領域」であるとして
「CGF 運用であれば自動化を推奨」と一概には言えない観点、と位置付けています。

自動化の導入にはコストがかかるため、まずは優先度の高い領域から対応し、
チーム状況やプロジェクト特性に応じて、段階的に整備していくのが良いかと思います。

4. CGF で優先したい領域:状態の再現

では具体的に、「状態の再現(環境・データ)」について見ていきましょう。


この観点について、まず押さえておきたいのは
「CGF では常に production の状態が正であり、検証環境はリセットされることが前提」という点です。


検証環境は、この「正」となる状態を基準として、
必要な変更を加えた状態を再現するためのものです。

reset は単なる初期化ではなく、
「production を基準に、検証に必要な状態を毎回同じ手順で再構築するプロセス」
として捉える必要があります。

これを踏まえると、

  • 状態を積み上げていくことを前提にしない
  • 必要な状態は、その都度作り直す

となります。
つまり、「過去からの積み上げ」で状態を再現するのではなく、

  • ある時点の状態を再構築できること
  • 同じデータを何度でも再現できる状態にすること

が重要になります。


この再現性が担保されていない場合、

  • 同じ手順で検証しているはずなのに、結果が変わる
    • 例)過去操作時の差分が残っており、基準点がズレているため前回と状態が揃っていなかった
  • バグが再現できない
  • 修正の妥当性が判断できない

といった問題が発生し、検証そのものの信頼性が崩れてしまいます。

4-1. テストデータ管理

このとき、最も課題になりやすいのがテストデータの扱いです。


reset 前提の運用では、

  • 手動投入したデータ
  • 過去の操作によって蓄積されたデータ

といったものに依存することができません。
そのため、検証に必要なデータはすべて「再現可能な形」で定義されている必要があります。


その際、検証に必要なデータは大きく分けて

  • production を基準とした初期データ(基準データ)
  • 検証のために追加されるデータ(検証用データ)

のように考えると整理しやすくなります。


また、検証用データについても、

  • 機能検証レベルの軽量なデータであれば seeder で管理
  • 大量データが必要な場合はアプリケーションコードから切り離して管理

といった形で使い分けるのが現実的かと思います。

seederの利用

seeder を利用することで、以下のようなことが可能になります

  • コマンドによる自動投入
  • 初期データや検証用データをコードとして管理
  • バージョン管理

これにより、

  • 誰が実行しても同じデータが投入される
  • 「どの状態で検証しているか」を明示できる

といった再現性が担保されます。

大量データの別管理

すべてのデータを seeder で管理しようとすると、
データ量や生成コストの観点で現実的でなくなるケースもあります。


こうした、パフォーマンス検証や実データに近い検証が必要な場合、

  • ダンプデータとして外部管理
  • 必要に応じて取得・投入する仕組み

といった形で、アプリケーションコードとは分離して扱うのが良いと考えています。


なお、ダンプデータに関してですが、
大量データや実データに近い状態での検証が必要であるとして、
本番環境のデータをベースにすることもあるかと思います。


その際は、

  • 個人情報・個人識別子のマスキング
  • 機密情報の除去

などで「安全に、かつ再利用可能な形」に加工する必要があります。


これらの処理も手動で行うのではなく、
「データ生成〜適用」までを一連の処理として自動化することで、
再現性と安全性を両立することができます。

4-2. 検証環境の再現性

CGF において重要なのは「検証状態の再現」で、具体的には

  1. 最新の production の状態にリセットする
  2. 検証対象の変更を適用する
  3. 必要なデータを投入する

という一連の流れを、
毎回同じ手順で実行できるようにすることです。

  • コマンド実行で状態を再構築できる
  • CI/CD で自動的に検証環境を更新する

といった形で、状態再現のフロー自体を自動化することで

  • 手順の抜け漏れ
  • 適用順序のミス
  • 状態の不一致

といった手動実行時のミスを防ぐことができます。


このように、状態そのものだけでなく、「状態を再現する手順」も含めて仕組み化することで、
CGF における再現性の担保につながります。

4-3. migration の位置付け

migration についても同様に、production を基準点として必要な対応を積み上げていくことになります。


そのため、各環境ごとの migration の歴史や差異を意識する必要はなく、
production 適用時に

  • 適用順序の整合性がとれていること
  • 既存データへの影響が考慮されていること(drop, rename など)
  • rollback の可否

といった、一般的な考慮事項が担保できているかが重要になります。


つまり、migration については「CGF 特有の設計対象」というよりも、
既存のベストプラクティスを前提として成立する領域、と位置付けることができます。

5. CGF で優先したい領域:操作の制御

続いて、「操作の制御(CI/CD・ブランチ操作)」について、具体的に見ていきましょう。


まず、押さえておきたいのは

  • 人は必ず操作を間違える
  • 注意やレビューだけでは防ぎきれない

ということです。


とはいえ、すべての操作を制御する必要はありません。
先にも述べている通り、「履歴に影響するかどうか」が判断軸として重要な観点になります。


特に、以下のような操作は制御対象になりやすい項目です。

  • マージ種別
  • 特定ブランチへの直接 push

これらに共通しているのは、「一度ミスをするとやり直しが効きにくい」という点です。


操作の制御には、いくつかのアプローチがあります。
それぞれ制御の強さや柔軟性が異なるため、対象に応じて使い分けることが重要です。

アプローチ①:実行条件を制御する

  • 必須チェック
  • 承認数
  • CI通過

といった条件を満たさない限り、マージなどの操作が実行できないようにする方法です。


これは Github の branch protection や CI(Actions)など
標準機能内で完結できることも多く、プロジェクトでも広く採用されているかと思います。


設定ルール・チェック項目の具体例としては、

  • production / develop ブランチへの直接 push 禁止
  • ブランチ名がプロジェクトルールに則っているか
  • マージ先ブランチが正しいか
  • PR テンプレートの必須項目が埋まっているか
  • 最新のベースブランチが取り込まれているか
    • 例)PR にベースブランチの最新コミットが反映されている状態かをチェック

などが挙げられます。


また、Github の merge queue などを活用することで、
マージ順序の制御や整合性の担保を実現することも可能です。

アプローチ②:操作自体を限定する

条件で弾くのではなく、「許可された操作以外ができない」ようにする方法です。
「そもそも選択肢を与えない」という考え方とも言えますね。


基本的(※)に、CGF では以下のように、フローによってマージ種別を使い分けます。
※ ブランチごとのマージ種別の使い分けや PR 運用の選択については過去記事参照

PR のマージ先 マージ種別
feature -> develop squash
develop -> production merge commit

このとき、マージ種別を人が選択できる状態にしておくと
誤った選択によって履歴が崩れるリスクが生まれるため、設計として固定しておいた方が安全です。


具体的な手段としては、UIレベルでの制御などが挙げられます。


たとえば、Chrome 拡張などを自作すれば、

  • PRの対象ブランチを自動で判別し、誤ったマージ方法が選択されている場合はボタンを非活性化する

など、操作そのものを制限することも可能です。

アプローチ③:操作を自動化する

最後は、「そもそも一連の操作に人を介入させない」ようにする方法です。
強制力が一番高い制御であり、人為的なミスが入り込む余地を極力排した形になります。


具体的には、トリガーをもとに処理を自動実行するような形式です。
人が操作するのは、「トリガーとなる操作のみ」とすることができます。


例としては、PR ラベルをトリガーとする自動処理などが挙げられます。


マージ時もラベル付与経由で行うようにすれば、

  1. マージ元とマージ先のブランチ種別を自動で判別
  2. ブランチ種別に応じたマージ方法で自動マージ

といった制御も可能です。

※ 「状態の再現」観点ではありますが、
ラベル付与で Actions を実行する方法という側面で考えると
検証環境についても、

  1. 検証用ブランチを最新 production までリセット
  2. 検証したいブランチをマージ
  3. 最新 production が持つ共通のテストデータを反映

までを自動化することも検討できます。

このように、手順をスクリプト化して人の操作を介さないようにすることで

  • 手順の抜け漏れ
  • 操作ミス
  • 意図しない判断のブレ

といった問題を根本的に防ぐことができます。


操作の制御において大切なのは、人が気をつけてミスを減らすのではなく
「ミスが起きない構造」を整えることだと考えています。


そのためにも、これらのアプローチを適切に組み合わせ

  • 条件で防ぐべきもの
  • 操作自体を制限するべきもの
  • 一連の流れで自動化するべきもの

を切り分けながら設計し、
「人に判断させる必要がないもの」を仕組みによって担保することが求められます。

おわりに

今回は、「フェールセーフとしての自動化」という観点から、
CGF における自動化の考え方と設計の指針について整理していきました。


本記事で取り上げた自動化は、単なる「作業効率化のための手段」ではなく、
発生しうるミスを防ぎ、影響を最小化するための「安全装置」としての役割を持つものです。


CGF は人に判断の余地がある戦略であるため、
自動化によるフェールセーフを設けることで、より安定した運用を実現できます。


本記事で、整理した4つの観点(状態の再現、操作の制御、可視化、品質担保)を

  • 優先的に対応したい領域
  • 状況に応じて発展的に検討する領域

に分けたように、すべてを自動化する必要はありません。


まとめて一気に自動化させていく必要もありません。
プロジェクトのフェーズに合わせて、プラグイン的に徐々に導入していくことを推奨しています。


重要なのは「何を自動化するか」だけではなく、
「どこまで自動化するか」を設計することです。


すべてを仕組みで縛ることが正解というわけではなく、
人に委ねるべき判断と、仕組みで担保するべき領域を切り分けることが、
CGF を安定して運用する上での本質だと考えています。


以上です。最後まで閲覧いただきありがとうございます。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?