チュートリアル : GitLabで実現する堅牢なコードレビューワークフロー
(トップページはこちら) - (プロジェクトで作業を整理する)
1. よくある課題
多くの開発チームが以下のような問題に直面しています。
- リリースブランチに未レビューのコードが直接プッシュされる
- レビュアーの選定が属人的で、適切な専門家にレビューが回らない
- マージリクエストの承認プロセスが曖昧で、誰が最終判断するのか不明確
- 新しいリリースブランチを作るたびに保護設定を手動で行う必要がある
本記事では、GitLabの機能を組み合わせて、これらの課題を体系的に解決する方法を紹介します。
2. 実現できること
このワークフローを構築すると、以下が自動化されます。
具体的な効果:
- レビュアー選定時間: 手動選定から自動割り当てへ
- レビュー品質: 専門知識を持つエンジニアが必ずレビュー
- セキュリティ: 保護されたブランチへの直接プッシュを完全防止
- スケーラビリティ: 新しいリリースブランチ(1.1.0、1.2.0など)も自動的に保護
3. GitLabエディションによる機能差
| 機能 | Free | Premium/Ultimate |
|---|---|---|
| CODEOWNERSファイル | ○(レビュー推奨のみ) | ○(レビュー必須化可能) |
| ブランチ保護 | ○ | ○ |
| 承認ルール | ○(基本) | ○(高度な設定) |
| CODEOWNERS承認の強制 | × | ○ |
| 承認数の指定 | × | ○ |
本記事の手順はFreeでも実施可能ですが、Premium/Ultimateでより強力な保護が実現できます。
4. 前提条件
- Maintainer以上のロール
- マネージャー、バックエンドエンジニア、フロントエンドエンジニアのリストとメールアドレス
- セマンティックバージョニングの理解
5. アーキテクチャ設計
5.1. なぜグループ構造が必要か
単一のプロジェクトにすべてのユーザーを追加する方式では、以下の問題が発生します。
- 役割ごとの権限管理が煩雑
- レビュアーの専門性が不明確
- 組織変更時の対応が困難
グループ構造を使うことで、役割ごとに権限を一元管理し、CODEOWNERSとの連携が容易になります。
5.2. 構築する構造
設計のポイント:
- サブグループの最大ロールをMaintainerに制限することで、過剰な権限付与を防止
- 同じユーザーが複数のサブグループに所属可能(例: マネージャー兼バックエンドエンジニア)
- プロジェクトは親グループ直下に配置し、すべてのサブグループからアクセス可能に
6. 構築手順
6.1. Engineeringグループの作成
目的: プロジェクトを所有する親グループを作成し、組織の基盤を構築します。
- 左サイドバーの上部にあるCreate new (➕) からNew groupを選択
- Create groupを選択
-
Group nameに
Engineeringを入力 -
Group URLに
engineeringを入力 - Visibility levelをPrivateに設定
- グループの用途を選択(システム管理者、チーム利用、コード保管など)
- Create groupを選択
6.2. サブグループの作成
目的: 役割ごとにユーザーを分類し、権限管理を簡素化します。
Managersサブグループの作成:
-
engineeringグループを検索して選択 - 右上のNew subgroupを選択
-
Subgroup nameに
Managersを入力 - Visibility levelをPrivateに設定
- Create subgroupを選択
親グループへの追加:
-
engineeringグループのManage > Membersを選択 - 右上のInvite a groupを選択
-
Engineering / Managersを選択 - ロールをMaintainerに設定
- Inviteを選択
重要: ここで設定するMaintainerは、サブグループメンバーが親グループのプロジェクトで継承できる最大ロールです。これにより、サブグループでOwnerロールを持つユーザーでも、プロジェクトではMaintainerまでに制限されます。
同様の手順でFrontendとBackendサブグループを作成します。
6.3. ユーザーの追加
目的: 各エンジニアを適切なサブグループに配置します。
ロール継承の仕組み:
| サブグループでのロール | 親グループで継承されるロール | 理由 |
|---|---|---|
| Guest | Guest | 最大ロール(Maintainer)以下 |
| Developer | Developer | 最大ロール(Maintainer)以下 |
| Maintainer | Maintainer | 最大ロールと同じ |
| Owner | Maintainer | 最大ロール(Maintainer)で制限 |
Frontendサブグループへの追加手順:
-
frontendグループを検索して選択 - Manage > Membersを選択
- Invite membersを選択
- メールアドレスを入力
- ロールを選択:
- 一般的な開発者: Developer
- コードレビューを行う開発者: Maintainer
- Inviteを選択
同様にBackendとManagersグループにもユーザーを追加します。
ベストプラクティス:
- レビュアーには最低でもDeveloperロールを付与
- 最終承認者(マネージャー)にはMaintainerロールを付与
- 1人のユーザーが複数のサブグループに所属することを許可
6.4. Excelsiorプロジェクトの作成
目的: フロントエンドとバックエンドの両方が関わるプロジェクトを、親グループ直下に配置します。
-
engineeringグループを検索して選択 - 左サイドバーのCreate new (➕) からIn this group > New project/repositoryを選択
- Create blank projectを選択
- プロジェクト詳細を入力:
-
Project name:
Excelsior - Visibility Level: Public(または組織のポリシーに従う)
- Initialize repository with a READMEを選択
-
Project name:
- Create projectを選択
7. CODEOWNERSファイルの設定
7.1. CODEOWNERSとは
CODEOWNERSファイルは、ファイルパターンごとに責任者(レビュアー)を定義するファイルです。マージリクエスト作成時に、変更されたファイルに基づいて自動的にレビュアーが割り当てられます。
仕組み:
7.2. CODEOWNERSファイルの作成
-
Excelsiorプロジェクトを選択 - ブランチ名の横にあるプラスアイコン (➕) からNew fileを選択
-
Filenameに
CODEOWNERSを入力 - 以下の内容を貼り付け:
# すべての変更はengineeringグループの誰かがレビュー
* @engineering
# このファイルの変更はマネージャーがレビュー
CODEOWNERS @engineering/managers
# フロントエンドファイルはFEエンジニアがレビュー
[Frontend] @engineering/frontend
*.scss
*.js
*.vue
*.jsx
# バックエンドファイルはBEエンジニアがレビュー
[Backend] @engineering/backend
*.rb
*.rake
config/
- コミットメッセージを入力してCommit changesを選択
7.3. ルールの優先順位
CODEOWNERSファイルは下から上に評価されます。つまり、ファイルの下部にあるルールが優先されます。
例:
* @engineering # ルール1: すべてのファイル
*.js @engineering/frontend # ルール2: JSファイル
app.js @engineering/managers # ルール3: 特定のファイル
app.jsを変更した場合、ルール3が最優先され、@engineering/managersが割り当てられます。
7.4. セクションの活用
[セクション名]を使うことで、マージリクエストのUIでレビュアーをグループ化できます。
[Frontend] @engineering/frontend
*.js
*.scss
[Backend] @engineering/backend
*.rb
これにより、マージリクエスト画面で「Frontend」「Backend」というセクションごとにレビュアーが表示されます。
8. 承認ルールの設定
8.1. 承認ルールとは
承認ルールは、マージリクエストをマージする前に必要な承認を定義します。CODEOWNERSがレビュアーを「推奨」するのに対し、承認ルールは承認を「強制」します(Premium/Ultimate)。
Free版とPremium/Ultimate版の違い:
| 項目 | Free | Premium/Ultimate |
|---|---|---|
| 承認ルールの作成 | ○ | ○ |
| 承認数の指定 | × | ○ |
| CODEOWNERS承認の強制 | × | ○ |
| ブランチごとのルール | × | ○ |
8.2. 承認ルールの作成手順
-
ExcelsiorプロジェクトのSettings > Merge requestsを選択 - Merge request approvalsセクションのApproval rulesまでスクロール
- Add approval ruleを選択
- ルール設定:
-
Rule name:
Enforce CODEOWNERS - Target branch: All protected branchesを選択
-
Approvals required:
1(Premium/Ultimateのみ) -
Approvers:
engineering/managersグループを追加
-
Rule name:
- Add approval ruleを選択
-
Approval settingsで以下を選択:
- Prevent editing approval rules in merge requests: 有効化
- Prevent approval by author: 有効化(推奨)
- Prevent approvals by users who add commits: 有効化(推奨)
- Save changesを選択
8.3. 承認ルールの動作
重要なポイント:
- Prevent editing approval rules in merge requests: マージリクエスト作成者が承認ルールを変更できないようにする
- Prevent approval by author: 自分のマージリクエストを自分で承認できないようにする
- Prevent approvals by users who add commits: コミットを追加したユーザーは承認できないようにする
9. ブランチ保護の設定
9.1. なぜワイルドカードが必要か
セマンティックバージョニングでは、リリースブランチが以下のように増えていきます。
1.0.01.1.01.2.02.0.0
各ブランチに個別に保護設定を行うのは非効率です。ワイルドカード(1.*)を使うことで、パターンに一致するすべてのブランチを一度に保護できます。
9.2. ワイルドカードブランチルールの作成
-
ExcelsiorプロジェクトのSettings > Repositoryを選択 - Branch rulesを展開
- Add branch rule > Branch name or patternを選択
- ドロップダウンリストに
1.*と入力し、**Create wildcard1.***を選択 - 保護設定を構成:
マージ権限:
- Allowed to mergeセクションでEditを選択
- Maintainersに設定
- Save changesを選択
プッシュ権限:
- Allowed to push and mergeセクションでEditを選択
- No oneに設定(直接プッシュを完全にブロック)
- Save changesを選択
フォースプッシュ:
- Allowed to force pushは無効のまま
CODEOWNERS承認(Premium/Ultimateのみ):
- Require approval from code ownersを有効化
- デフォルトブランチ(
mainまたはmaster)にも同じ設定を適用
9.3. 保護設定の意味
| 設定 | 値 | 効果 |
|---|---|---|
| Allowed to merge | Maintainers | Maintainer以上のロールを持つユーザーのみマージ可能 |
| Allowed to push and merge | No one | 誰も直接プッシュできない(マージリクエスト必須) |
| Allowed to force push | 無効 | 履歴の改ざんを防止 |
| Require approval from code owners | 有効 | CODEOWNERSで指定されたレビュアーの承認が必須 |
9.4. ワイルドカードのパターン例
| パターン | 一致する例 | 一致しない例 |
|---|---|---|
1.* |
1.0.0, 1.1.0, 1.x
|
2.0.0, main
|
release/* |
release/1.0, release/v2
|
hotfix/1.0 |
*-stable |
1.0-stable, main-stable
|
1.0-dev |
10. リリースブランチの作成
10.1. ブランチ作成手順
-
Excelsiorプロジェクトを選択 - Code > Branchesを選択
- 右上のNew branchを選択
- ブランチ名に
1.0.0を入力 -
Create from:
mainを選択 - Create branchを選択
10.2. 保護の確認
ブランチリストでの確認:
- Code > Branchesを選択
-
1.0.0ブランチに保護マーク(盾アイコン)が表示されることを確認
ブランチルール詳細での確認:
- Settings > Repository > Branch rulesを選択
-
1.*ルールに1.0.0が含まれていることを確認 - 保護設定の詳細を確認
11. ワークフローの実践
11.1. 開発フロー全体
11.2. 具体的な操作例
ステップ1: フィーチャーブランチの作成(田中さん)
git checkout main
git pull origin main
git checkout -b feature/new-ui-component
ステップ2: コードの変更
# app.jsとstyles.scssを編集
vim app.js
vim styles.scss
git add app.js styles.scss
git commit -m "新しいUIコンポーネントを追加"
git push origin feature/new-ui-component
ステップ3: マージリクエストの作成
GitLabのUIで以下を設定:
-
Source branch:
feature/new-ui-component -
Target branch:
1.0.0 - Title: 新しいUIコンポーネントを追加
- Description: ユーザーダッシュボードに新しいウィジェットを追加
マージリクエスト作成時、CODEOWNERSにより以下が自動的に設定されます:
-
Reviewers:
@engineering/frontend(佐藤さん、田中さんなど) -
Approval required:
@engineering/managers(鈴木さん、山田さんなど)
ステップ4: コードレビュー(佐藤さん)
佐藤さんがマージリクエストを確認:
- Changesタブでコードの差分を確認
- 気になる箇所にコメントを追加
- 問題がなければApproveボタンをクリック
ステップ5: 最終承認(鈴木さん)
承認ルールにより、マネージャーの承認が必要:
- 鈴木さんがマージリクエストを確認
- ビジネス要件を満たしているか確認
- Approveボタンをクリック
ステップ6: マージ(田中さん)
すべての承認が揃ったら:
- Mergeボタンが有効化される
- 田中さんがMergeをクリック
-
1.0.0ブランチに変更が反映される
11.3. 承認状態の確認
マージリクエスト画面で以下が表示されます:
Approval rules
✓ Enforce CODEOWNERS (1/1 required)
✓ 鈴木さん (engineering/managers)
Code Owners
✓ Frontend (1/1 required)
✓ 佐藤さん (engineering/frontend)
12. トラブルシューティング
12.1. CODEOWNERSが機能しない
症状: マージリクエストにレビュアーが自動割り当てされない
原因と解決策:
| 原因 | 確認方法 | 解決策 |
|---|---|---|
| CODEOWNERSファイルの配置場所が間違っている | リポジトリのルートに配置されているか確認 | ルートディレクトリに移動 |
| グループパスが間違っている |
@engineering/frontendのパスが正しいか確認 |
グループのURLパスを確認して修正 |
| ファイルパターンが一致していない | 変更したファイルがパターンに一致するか確認 | パターンを修正(例: *.jsを**/*.jsに) |
| CODEOWNERSファイルがターゲットブランチにない | ターゲットブランチ(1.0.0)にCODEOWNERSが存在するか確認 |
ターゲットブランチにマージまたはチェリーピック |
デバッグ方法:
- プロジェクトのSettings > Repository > Code Ownersを確認
- マージリクエストのChangesタブで、各ファイルにCode Ownerが表示されるか確認
12.2. 承認ルールが適用されない
症状: マージリクエストに承認が不要と表示される
原因と解決策:
| 原因 | 確認方法 | 解決策 |
|---|---|---|
| ターゲットブランチが保護されていない | Settings > Repository > Branch rulesを確認 | ブランチ保護を設定 |
| 承認ルールのターゲットブランチが一致していない | 承認ルールのTarget branchを確認 | All protected branchesに変更 |
| GitLab Freeで必須承認を設定しようとしている | GitLabのエディションを確認 | Premium/Ultimateにアップグレード、またはFreeの範囲で運用 |
12.3. ブランチ保護が機能しない
症状: 保護されたブランチに直接プッシュできてしまう
原因と解決策:
| 原因 | 確認方法 | 解決策 |
|---|---|---|
| ユーザーのロールが高すぎる | ユーザーのロールを確認 | Allowed to push and mergeをNo oneに設定 |
| ワイルドカードパターンが一致していない | ブランチ名がパターンに一致するか確認 | パターンを修正(例: 1.*を1.*.*に) |
| 保護設定が保存されていない | Branch rulesで設定を再確認 | 設定を再度保存 |
12.4. マージボタンが有効にならない
症状: すべての承認が揃っているのにマージできない
チェックリスト:
- すべての承認ルールが満たされているか
- パイプラインが成功しているか(設定している場合)
- コンフリクトが解消されているか
- ディスカッションがすべて解決されているか(設定している場合)
- ドラフトモードになっていないか
13. ベストプラクティス
13.1. グループ構造の設計
推奨:
- サブグループの最大ロールはMaintainerに制限
- 役割ごとにサブグループを分ける(職能別、プロダクト別など)
- 1つのサブグループのメンバー数は10〜20名程度に抑える
非推奨:
- すべてのユーザーを親グループに直接追加
- サブグループの最大ロールをOwnerに設定
- 細かすぎるサブグループ分割(管理コストが増大)
13.2. CODEOWNERSファイルの設計
推奨:
# デフォルトのレビュアーを最初に定義
* @engineering
# 特定のディレクトリごとに定義
/frontend/ @engineering/frontend
/backend/ @engineering/backend
/docs/ @engineering/managers
# 重要なファイルは最後に定義(優先度が高い)
CODEOWNERS @engineering/managers
package.json @engineering/managers
Gemfile @engineering/managers
非推奨:
# 曖昧なパターン
* @everyone
# 重複したルール
*.js @engineering/frontend
*.js @engineering/backend
# 存在しないグループ
*.rb @engineering/ruby-team
13.3. 承認ルールの設計
推奨:
- 承認数は最小限に(1〜2名)
- 承認者グループは明確に定義
- Prevent approval by authorを有効化
- Prevent approvals by users who add commitsを有効化
非推奨:
- 承認数を多くしすぎる(開発速度が低下)
- 個人を承認者に指定(属人化のリスク)
- 承認ルールの編集を許可
13.4. ブランチ保護の設計
推奨:
| ブランチタイプ | パターン | Allowed to merge | Allowed to push |
|---|---|---|---|
| 本番リリース | main |
Maintainers | No one |
| リリース候補 | 1.* |
Maintainers | No one |
| 開発ブランチ | develop |
Developers | No one |
| フィーチャー | feature/* |
保護なし | 保護なし |
非推奨:
- すべてのブランチを保護(開発の柔軟性が失われる)
- 保護ブランチへの直接プッシュを許可
- フォースプッシュを許可
14. 運用上の注意点
14.1. 緊急時の対応
ホットフィックスが必要な場合:
- 通常のワークフローに従う(承認プロセスを省略しない)
- レビュアーに緊急であることを明示
- 承認後、速やかにマージ
- 事後に詳細なレビューを実施
どうしても直接プッシュが必要な場合:
- Ownerロールを持つユーザーが一時的にブランチ保護を解除
- 変更をプッシュ
- 即座にブランチ保護を再設定
- 事後にマージリクエストを作成して記録を残す
14.2. 組織変更時の対応
メンバーの異動:
- サブグループのメンバーシップを更新するだけで、プロジェクトの権限も自動的に更新される
- CODEOWNERSファイルの変更は不要(グループベースで定義しているため)
チーム構造の変更:
- 新しいサブグループを作成
- 親グループに追加
- CODEOWNERSファイルを更新
- 承認ルールを更新
14.3. 定期的なメンテナンス
月次:
- 各サブグループのメンバーリストを確認
- 退職者や異動者のアクセス権を削除
四半期ごと:
- CODEOWNERSファイルの妥当性を確認
- 承認ルールが適切か確認
- ブランチ保護設定を見直し
年次:
- グループ構造全体を見直し
- 不要なサブグループを統廃合
- ワークフロー全体の効果を測定
15. 効果測定
15.1. 測定すべき指標
レビュープロセスの効率:
- レビュアー選定時間: 手動選定からの削減時間
- レビュー待ち時間: マージリクエスト作成から最初のレビューまでの時間
- マージまでの時間: マージリクエスト作成からマージまでの時間
品質指標:
- 本番環境でのバグ検出率: リリース後に発見されるバグの数
- レビューでのバグ検出率: レビュー段階で発見されるバグの数
- リリース後の緊急修正回数: ホットフィックスの頻度
セキュリティ指標:
- 未承認マージの件数: 承認なしでマージされた件数(ゼロが理想)
- 直接プッシュの件数: 保護されたブランチへの直接プッシュ(ゼロが理想)
- CODEOWNERSルール違反: 適切なレビュアーがレビューしなかった件数
15.2. 期待される効果
導入前後の比較例:
| 指標 | 導入前 | 導入後 | 改善率 |
|---|---|---|---|
| レビュアー選定時間 | 平均5分 | 0分(自動) | 100%削減 |
| レビュー待ち時間 | 平均4時間 | 平均1時間 | 75%削減 |
| 本番バグ検出率 | 月10件 | 月3件 | 70%削減 |
| 未承認マージ | 月5件 | 0件 | 100%削減 |
注意: 効果は組織の規模や文化によって異なります。
16. まとめ
このワークフローを構築することで、以下が実現されます。
自動化による効率化:
- レビュアーの自動割り当て: CODEOWNERSによる専門家の自動選定
- 承認プロセスの自動化: 承認ルールによる必須承認の強制
- ブランチ保護の自動適用: ワイルドカードによる新規ブランチの自動保護
品質とセキュリティの向上:
- 専門家によるレビュー: 適切な知識を持つエンジニアが必ずレビュー
- 直接プッシュの防止: すべての変更がレビューを経由
- 履歴の保護: フォースプッシュの禁止による履歴の改ざん防止
スケーラビリティ:
- グループ構造による権限管理: 組織変更に柔軟に対応
- ワイルドカードによるブランチ保護: 新しいリリースブランチも自動的に保護
- CODEOWNERSによる責任の明確化: チームの成長に合わせて拡張可能
運用コストの削減:
- 手動でのレビュアー選定が不要
- ブランチごとの保護設定が不要
- 承認プロセスの管理が自動化
GitLabのこれらの機能を組み合わせることで、チームの成長に合わせて拡張可能な、堅牢なコードレビューワークフローを構築できます。プロジェクトの規模や要件に応じて、グループ構造や承認ルールをカスタマイズすることで、さらに最適化されたワークフローを実現できます。