
前提
Pipeline 実行状態や Approval 状態、権限とか該当プロジェクトにおいて merge できる条件をクリアしているのに以下のいずれかのエラーが発生する
422 Unprocessable Entity(Branch cannot be merged)405 Method Not Allowed(405 Method Not Allowed)
原因
MR 作成直後は GitLab の内部処理が完了していない場合がある(らしい)
結論
Create MR のレスポンスもしくは、Get single MR のレスポンスに含まれる detailed_merge_status が mergeable になるまでリトライする1
コード
最小限のコードなのでエラーハンドリングなどは別途行う必要があります。
<?php try { // MRの作成 $createMergeRequest = (new \GuzzleHttp\Client()) ->post("{$_ENV['GITLAB_API_BASE_URL']}projects/{$_ENV['GITLAB_PROJECT_ID']}/merge_requests", [ 'headers' => [ 'PRIVATE-TOKEN' => $_ENV['GITLAB_BOT_TOKEN'], 'Content-Type' => 'application/x-www-form-urlencoded' ], 'form_params' => [ 'source_branch' => 'branch name', 'target_branch' => 'main', // 任意のmerge先 'title' => 'MRのタイトル', // MR作成時に行うその他任意のパラメータ定義 ] ]); $content = json_decode($createMergeRequest->getBody()->getContents()); // マージチェック通過後にマージする if (mergeable($content->iid)) { (new \GuzzleHttp\Client()) ->put("{$_ENV['GITLAB_API_BASE_URL']}projects/{$_ENV['GITLAB_PROJECT_ID']}/merge_requests/{$content->iid}/merge", [ 'headers' => [ 'PRIVATE-TOKEN' => $_ENV['GITLAB_BOT_TOKEN'], 'Content-Type' => 'application/x-www-form-urlencoded', ], 'form_params' => [ 'should_remove_source_branch' => true, // mergeの際に行う任意のパラメータ ], ]); } } catch (\Throwable $th) { echo "エラー: {$th->getMessage()}"; } /** * detailed_merge_status が mergeable になるまでリトライする * * @param int $iid * @return bool */ function mergeable(int $iid): bool { $start = time(); $maxWaitTime = 30; while (time() - $start < $maxWaitTime) { $getMergeRequest = (new \GuzzleHttp\Client()) ->get("{$_ENV['GITLAB_API_BASE_URL']}projects/{$_ENV['GITLAB_PROJECT_ID']}/merge_requests/{$iid}", [ 'headers' => [ 'PRIVATE-TOKEN' => $_ENV['GITLAB_BOT_TOKEN'], 'Content-Type' => 'application/json', ], ]); $content = json_decode($getMergeRequest->getBody()->getContents()); if ($content->detailed_merge_status === 'mergeable') { echo "mergeable になりました。\n"; return true; } // 次のリクエストまで3秒待機 echo "current status -> {$content->detailed_merge_status}\n"; sleep(3); } throw new RuntimeException('タイムアウト'); }
最後に
お前... まさか feature ブランチでの作業直後にセルフマージしようとしてないよな?
参考
-
GitLab の Version が 15.6 未満の場合は
merge_statusがcan_be_mergedになるまで↩