diff --git a/docs/usage/self-hosted-experimental.md b/docs/usage/self-hosted-experimental.md index 45d7c8fffc70037..6ed0025eaf728e9 100644 --- a/docs/usage/self-hosted-experimental.md +++ b/docs/usage/self-hosted-experimental.md @@ -96,7 +96,7 @@ If set, Renovate will terminate the whole process group of a terminated child pr ## `RENOVATE_X_GITLAB_AUTO_MERGEABLE_CHECK_ATTEMPS` If set to an positive integer, Renovate will use this as the number of attempts to check if a merge request on GitLab is mergable before trying to automerge. -The formula for the delay between attempts is `250 * attempt * attempt` milliseconds. +The formula for the delay between attempts is `RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY * attempt * attempt` milliseconds. Default value: `5` (attempts results in max. 13.75 seconds timeout). @@ -108,6 +108,12 @@ Can be useful for slow-running, self-hosted GitLab instances that don't react fa Default value: `1000` (milliseconds). +## `RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY` + +If set, Renovate will use this as a delay to proceed with an automerge. + +Default value: `250` (milliseconds). + ## `RENOVATE_X_HARD_EXIT` If set to any value, Renovate will use a "hard" `process.exit()` once all work is done, even if a sub-process is otherwise delaying Node.js from exiting. diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index be38419752c8f2b..be7c46eb12fd975 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -644,26 +644,46 @@ async function tryPrAutomerge( await ignoreApprovals(pr); } - const desiredStatus = 'can_be_merged'; + let desiredStatus = 'can_be_merged'; // The default value of 5 attempts results in max. 13.75 seconds timeout if no pipeline created. const retryTimes = parseInteger( process.env.RENOVATE_X_GITLAB_AUTO_MERGEABLE_CHECK_ATTEMPS, 5, ); + if (semver.gt(defaults.version, '15.6.0')) { + logger.debug( + { version: defaults.version }, + 'In GitLab 15.6 merge_status, using detailed_merge_status to check the merge request status', + ); + desiredStatus = 'mergeable'; + } + + const mergeDelay = parseInteger( + process.env.RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY, + 250, + ); + // Check for correct merge request status before setting `merge_when_pipeline_succeeds` to `true`. for (let attempt = 1; attempt <= retryTimes; attempt += 1) { const { body } = await gitlabApi.getJson<{ merge_status: string; + detailed_merge_status: string; pipeline: string; }>(`projects/${config.repository}/merge_requests/${pr}`, { memCache: false, }); // Only continue if the merge request can be merged and has a pipeline. - if (body.merge_status === desiredStatus && body.pipeline !== null) { + if ( + ((desiredStatus === 'mergeable' && + body.detailed_merge_status === desiredStatus) || + (desiredStatus === 'can_be_merged' && + body.merge_status === desiredStatus)) && + body.pipeline !== null + ) { break; } - await setTimeout(250 * attempt ** 2); // exponential backoff + await setTimeout(mergeDelay * attempt ** 2); } await gitlabApi.putJson(