Scope CI_MERGE_REQUEST_APPROVED preload to avoid jobs/request timeout
What does this MR do and why?
POST /api/v4/jobs/request can time out (Rack::Timeout::RequestTimeoutException, ~60s) while resolving the predefined CI_MERGE_REQUEST_APPROVED variable, instead of returning a job payloadn -affected jobs then hang until their timeout with no trace output. See #606211.
An interaction between two independent changes, amplified by MR size:
- Unbounded preload (2025): the EE approval-variable preloader unconditionally preloads
merge_request_diff->merge_request_diff_commits->commit_author/committer` over all commits in the MR diff. That data is only read when the project has "Prevent approval by users who add commits" (merge_requests_disable_committers_approval?) enabled , yet it's preloaded regardless of the setting or commit count. - Lazy resolution moved to the request path shifting that preload out of pipeline creation and into POST /api/v4/jobs/request, inside the 60s Rack window.
The fix
Behind feature flag ci_optimize_merge_request_approved_resolution (default disabled):
- Scope the commit preload to only run when merge_requests_disable_committers_approval? is enabled — the only case that reads committer identity. For every other project (the default), the expensive preload no longer fires.
- git_depth_value uses a targeted variables["GIT_DEPTH"] lookup instead of to_hash, so reading one variable no longer forces resolution of all lazy variables.
Both changes sit behind the same flag so they roll back together.
How to set up and validate locally
- Create an MR whose diff has a large number of commits. Then run a merge request pipeline.
- Register a job via POST /api/v4/jobs/request:
- Flag off: resolves
CI_MERGE_REQUEST_APPROVED, preloading all diff commits. This will be slow, times out on very large MRs. - Flag on (project with committer-approval off): preload skipped, request returns promptly.
Edited by Laura Montemayor