AI自動開発の設定一式

GitLabの仕組み

研修のGitLabでは、人がIssueを書いてラベルで承認すると、AIが実装してMRを出します。人が手を動かすのは、書く、承認する、読んでマージする、の3か所だけです。

人が触る3か所

1

Issueを書く

型に沿って、背景、やること、受け入れ条件を書きます。受け入れ条件は、読んだ人によって結果が変わらない形にします。AIも同じ文を読むからです。

2

ラベルで承認する

ラベルai::approvedを付けた時点が、AIに任せてよいという承認です。付いていないIssueを、AIは拾いません。

3

MRを読んでマージする

差分を受け入れ条件と突き合わせ、mainに入れるかを人が決めます。マージのボタンは、パイプラインが通ったMRにしか出ません。

その間の実装、テスト、レビューの前さばきは、AIとパイプラインが受け持ちます。昼は10分おき、夜は22時のスケジュールで動き、流れはどちらも同じです。Issueを夕方までに承認しておけば、夜のうちにMRができ、朝の人はMRを読むだけで済みます。

1本のIssueがmainに入るまで

2026年10月2日の試走で、Issue #30が通った道です。書いた人をAさんとして追います。再生を押すと札が箱から箱へ移り、その場で動いた仕組みが吹き出しで話す作りです。下の段を押すと、その段へ飛べます。

手元のPC
Claude Desktop、フック、pre-commit
人
書く、承認する、読んでマージする
Issueとボード
型、受け入れ条件、ラベル
起動
スケジュールかNew pipeline
ai_pick
承認済みのIssueを拾う
Runner
EC2の上でジョブを動かす
main
保護。マージはMaintainerだけ
MRのパイプライン
lint、test、AIレビュー、ai_scope
MR
ai-cycle-botか人が作る
AIの実装
Claudeが実装してコミット
時刻なしIssueのラベルなしMRなしAIの費用なし
  1. Aさんが、型ai-taskでIssueを書きます。受け入れ条件は、テストのファイル名、確かめる呼び出しと結果、パイプラインが緑、変えるのはテスト1本だけ、の4行です。Aさんwarehouse_name('')が「不明」を返すことを、テストで固定したい。
  2. Aさんがラベルai::approvedを付けました。ここが人の承認で、付けるまでAIは何もしません。Aさん受け入れ条件まで書けたので、AIに任せます。
  3. 講師がmainで、変数AI_CYCLEをonにしてパイプラインを動かします。研修の当日は、スケジュールが10分おきに同じことをします。GitLabAIのサイクル用に、パイプライン#89を作りました。
  4. ai_pickが、承認済みで未着手のIssueを探します。見つけた3本にai::runningを付け、1本に1つのジョブを並べた子パイプラインを作りました。ai_pickのログ承認済みで未着手の Issue: 3 本
  5. Runnerが、子パイプラインの3つのジョブを同時に動かします。Runnerは研修用のEC2の上にあり、8本まで同時に動かせる設定です。Runnerimplement-issue-30、31、32を並べて動かします。
  6. ジョブはラベルを確かめ直してから、Claudeに実装させます。Claudeが使えるのは、ファイルの読み書きとphp、git add、git commitだけです。implement-issue-30のログターン 7 / 費用 0.13 ドル / 終わり方 success
  7. ジョブのスクリプトがpushしてMRを作り、Issueにコメントを付けます。Claudeにはpushの権限を渡していないので、ここはスクリプトだけの仕事です。ai-cycle-bot@AさんAIの実装サイクルがMRを出しました。
  8. MRのパイプラインが走ります。構文、ルール、テスト、AIレビューに加え、AIのMRでだけai_scopeも動きました。ai_scopeのログOK 触ってはいけない場所は変えていません。大きさも目安の中です。
  9. Aさんが差分を開き、受け入れ条件と突き合わせます。変わったファイルはtests/phpunit/WarehouseNameEmptyTest.phpの1本で、14行でした。Aさんテストが1本だけで、受け入れ条件のとおりです。
  10. 講師がマージします。MRの説明のCloses #30によって、Issueは自動で閉じました。GitLab!13をmainに入れ、Issue #30を閉じました。

試走の記録

10月2日に、書き方の違う3本のIssueを1回の起動で流しました。3本は同時に動き、どれも1分前後で終わっています。

Issue書き方結果時間ターンと費用
#30受け入れ条件を4行で書いた通るMR !13ができ、人が読んでマージ61秒7ターン、0.13ドル
#31受け入れ条件は「見やすくなっている」の1行だけ止まる実装せずに、質問を4つ返した63秒5ターン、0.07ドル
#32「決まっていないこと」に1行を書いた止まるClaudeを呼ぶ前に、ジョブが止めた48秒0ターン、0ドル

上限は1本あたり30ターンと25分です。9月30日の試走では、状態コードを1つにまとめる広めのIssueが、約20ターンと0.55ドルでコミットまで進みました。

パイプラインの3種類

MRのパイプライン

受講者やAIがpushしたとき、MRを作ったときに走ります。所要は1〜2分で、受講者のMRでは7つ、AIのMRでは8つのジョブが並びます。

lintlint-phpdevlint-phpvercheck-rulesai_scope(AIのMRだけ)
testtesttest-phpunit
reviewai_review
gateai_gate

サイクルのパイプライン

スケジュールか、mainで変数AI_CYCLE=onを付けたNew pipelineで走ります。コードの検査のジョブは動きません。

pickai_pick
implementai_run
子パイプラインimplement-issue-番号拾った本数だけ並ぶ

mainのパイプライン

マージのあとに走り、mainが緑のままかを確かめます。AIレビューは動きません。

lintlint-phpdevlint-phpvercheck-rules
testtesttest-phpunit

資料の案内