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?

チュートリアル : GitLabで実現する堅牢なコードレビューワークフロー

Posted at

チュートリアル : 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グループの作成

目的: プロジェクトを所有する親グループを作成し、組織の基盤を構築します。

  1. 左サイドバーの上部にあるCreate new (➕) からNew groupを選択
  2. Create groupを選択
  3. Group nameEngineeringを入力
  4. Group URLengineeringを入力
  5. Visibility levelPrivateに設定
  6. グループの用途を選択(システム管理者、チーム利用、コード保管など)
  7. Create groupを選択

6.2. サブグループの作成

目的: 役割ごとにユーザーを分類し、権限管理を簡素化します。

Managersサブグループの作成:

  1. engineeringグループを検索して選択
  2. 右上のNew subgroupを選択
  3. Subgroup nameManagersを入力
  4. Visibility levelPrivateに設定
  5. Create subgroupを選択

親グループへの追加:

  1. engineeringグループのManage > Membersを選択
  2. 右上のInvite a groupを選択
  3. Engineering / Managersを選択
  4. ロールをMaintainerに設定
  5. Inviteを選択

重要: ここで設定するMaintainerは、サブグループメンバーが親グループのプロジェクトで継承できる最大ロールです。これにより、サブグループでOwnerロールを持つユーザーでも、プロジェクトではMaintainerまでに制限されます。

同様の手順でFrontendBackendサブグループを作成します。

6.3. ユーザーの追加

目的: 各エンジニアを適切なサブグループに配置します。

ロール継承の仕組み:

サブグループでのロール 親グループで継承されるロール 理由
Guest Guest 最大ロール(Maintainer)以下
Developer Developer 最大ロール(Maintainer)以下
Maintainer Maintainer 最大ロールと同じ
Owner Maintainer 最大ロール(Maintainer)で制限

Frontendサブグループへの追加手順:

  1. frontendグループを検索して選択
  2. Manage > Membersを選択
  3. Invite membersを選択
  4. メールアドレスを入力
  5. ロールを選択:
    • 一般的な開発者: Developer
    • コードレビューを行う開発者: Maintainer
  6. Inviteを選択

同様にBackendManagersグループにもユーザーを追加します。

ベストプラクティス:

  • レビュアーには最低でもDeveloperロールを付与
  • 最終承認者(マネージャー)にはMaintainerロールを付与
  • 1人のユーザーが複数のサブグループに所属することを許可

6.4. Excelsiorプロジェクトの作成

目的: フロントエンドとバックエンドの両方が関わるプロジェクトを、親グループ直下に配置します。

  1. engineeringグループを検索して選択
  2. 左サイドバーのCreate new (➕) からIn this group > New project/repositoryを選択
  3. Create blank projectを選択
  4. プロジェクト詳細を入力:
    • Project name: Excelsior
    • Visibility Level: Public(または組織のポリシーに従う)
    • Initialize repository with a READMEを選択
  5. Create projectを選択

7. CODEOWNERSファイルの設定

7.1. CODEOWNERSとは

CODEOWNERSファイルは、ファイルパターンごとに責任者(レビュアー)を定義するファイルです。マージリクエスト作成時に、変更されたファイルに基づいて自動的にレビュアーが割り当てられます。

仕組み:

7.2. CODEOWNERSファイルの作成

  1. Excelsiorプロジェクトを選択
  2. ブランチ名の横にあるプラスアイコン (➕) からNew fileを選択
  3. FilenameCODEOWNERSを入力
  4. 以下の内容を貼り付け:
# すべての変更はengineeringグループの誰かがレビュー
* @engineering

# このファイルの変更はマネージャーがレビュー
CODEOWNERS @engineering/managers

# フロントエンドファイルはFEエンジニアがレビュー
[Frontend] @engineering/frontend
*.scss
*.js
*.vue
*.jsx

# バックエンドファイルはBEエンジニアがレビュー
[Backend] @engineering/backend
*.rb
*.rake
config/
  1. コミットメッセージを入力して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. 承認ルールの作成手順

  1. ExcelsiorプロジェクトのSettings > Merge requestsを選択
  2. Merge request approvalsセクションのApproval rulesまでスクロール
  3. Add approval ruleを選択
  4. ルール設定:
    • Rule name: Enforce CODEOWNERS
    • Target branch: All protected branchesを選択
    • Approvals required: 1(Premium/Ultimateのみ)
    • Approvers: engineering/managersグループを追加
  5. Add approval ruleを選択
  6. Approval settingsで以下を選択:
    • Prevent editing approval rules in merge requests: 有効化
    • Prevent approval by author: 有効化(推奨)
    • Prevent approvals by users who add commits: 有効化(推奨)
  7. 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.0
  • 1.1.0
  • 1.2.0
  • 2.0.0

各ブランチに個別に保護設定を行うのは非効率です。ワイルドカード(1.*)を使うことで、パターンに一致するすべてのブランチを一度に保護できます。

9.2. ワイルドカードブランチルールの作成

  1. ExcelsiorプロジェクトのSettings > Repositoryを選択
  2. Branch rulesを展開
  3. Add branch rule > Branch name or patternを選択
  4. ドロップダウンリストに1.*と入力し、**Create wildcard 1.***を選択
  5. 保護設定を構成:

マージ権限:

  • 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を有効化
  1. デフォルトブランチ(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. ブランチ作成手順

  1. Excelsiorプロジェクトを選択
  2. Code > Branchesを選択
  3. 右上のNew branchを選択
  4. ブランチ名に1.0.0を入力
  5. Create from: mainを選択
  6. Create branchを選択

10.2. 保護の確認

ブランチリストでの確認:

  1. Code > Branchesを選択
  2. 1.0.0ブランチに保護マーク(盾アイコン)が表示されることを確認

ブランチルール詳細での確認:

  1. Settings > Repository > Branch rulesを選択
  2. 1.*ルールに1.0.0が含まれていることを確認
  3. 保護設定の詳細を確認

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: コードレビュー(佐藤さん)

佐藤さんがマージリクエストを確認:

  1. Changesタブでコードの差分を確認
  2. 気になる箇所にコメントを追加
  3. 問題がなければApproveボタンをクリック

ステップ5: 最終承認(鈴木さん)

承認ルールにより、マネージャーの承認が必要:

  1. 鈴木さんがマージリクエストを確認
  2. ビジネス要件を満たしているか確認
  3. Approveボタンをクリック

ステップ6: マージ(田中さん)

すべての承認が揃ったら:

  1. Mergeボタンが有効化される
  2. 田中さんがMergeをクリック
  3. 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が存在するか確認 ターゲットブランチにマージまたはチェリーピック

デバッグ方法:

  1. プロジェクトのSettings > Repository > Code Ownersを確認
  2. マージリクエストの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 mergeNo 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. 緊急時の対応

ホットフィックスが必要な場合:

  1. 通常のワークフローに従う(承認プロセスを省略しない)
  2. レビュアーに緊急であることを明示
  3. 承認後、速やかにマージ
  4. 事後に詳細なレビューを実施

どうしても直接プッシュが必要な場合:

  1. Ownerロールを持つユーザーが一時的にブランチ保護を解除
  2. 変更をプッシュ
  3. 即座にブランチ保護を再設定
  4. 事後にマージリクエストを作成して記録を残す

14.2. 組織変更時の対応

メンバーの異動:

  • サブグループのメンバーシップを更新するだけで、プロジェクトの権限も自動的に更新される
  • CODEOWNERSファイルの変更は不要(グループベースで定義しているため)

チーム構造の変更:

  1. 新しいサブグループを作成
  2. 親グループに追加
  3. CODEOWNERSファイルを更新
  4. 承認ルールを更新

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のこれらの機能を組み合わせることで、チームの成長に合わせて拡張可能な、堅牢なコードレビューワークフローを構築できます。プロジェクトの規模や要件に応じて、グループ構造や承認ルールをカスタマイズすることで、さらに最適化されたワークフローを実現できます。

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?