From fbda0eda331adcdd23c9cb82565359aa7a7da501 Mon Sep 17 00:00:00 2001 From: javaxiss Date: Fri, 29 Dec 2023 16:36:31 +0100 Subject: [PATCH 1/3] feat: process detailed merge status attribute in gitlab 15.6 platform --- docs/usage/self-hosted-experimental.md | 8 ++++- lib/modules/platform/gitlab/index.spec.ts | 43 +++++++++++++++++++++++ lib/modules/platform/gitlab/index.ts | 26 ++++++++++++-- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/docs/usage/self-hosted-experimental.md b/docs/usage/self-hosted-experimental.md index 01a2993e414873..7ee6a8ee1f39df 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.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index 9a30d26c551e1b..7740a9c8944dc9 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -1824,6 +1824,49 @@ describe('modules/platform/gitlab/index', () => { ]); }); + it('should parse detailed_merge_status attribute on >= 15.6', async () => { + await initPlatform('15.6.0-ee'); + httpMock + .scope(gitlabApiHost) + .post('/api/v4/projects/undefined/merge_requests') + .reply(200, { + id: 1, + iid: 12345, + title: 'some title', + }) + .get('/api/v4/projects/undefined/merge_requests/12345') + .reply(200) + .get('/api/v4/projects/undefined/merge_requests/12345') + .reply(200) + .get('/api/v4/projects/undefined/merge_requests/12345') + .reply(200) + .put('/api/v4/projects/undefined/merge_requests/12345/merge') + .reply(200); + process.env.RENOVATE_X_GITLAB_AUTO_MERGEABLE_CHECK_ATTEMPS = '3'; + process.env.RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY = '250'; + const pr = await gitlab.createPr({ + sourceBranch: 'some-branch', + targetBranch: 'master', + prTitle: 'some-title', + prBody: 'the-body', + platformOptions: { + usePlatformAutomerge: true, + }, + }); + expect(pr).toEqual({ + id: 1, + iid: 12345, + number: 12345, + sourceBranch: 'some-branch', + title: 'some title', + }); + expect(timers.setTimeout.mock.calls).toMatchObject([ + [250], + [1000], + [2250], + ]); + }); + it('raises with squash enabled when repository squash option is default_on', async () => { await initPlatform('14.0.0'); diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index be38419752c8f2..3e33bc71b07b34 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.gte(defaults.version, '15.6.0')) { + logger.trace( + { 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); // exponential backoff } await gitlabApi.putJson( From 7229b4415b40cbf5199468aaef88fa2b6e15ef9e Mon Sep 17 00:00:00 2001 From: javaxiss Date: Tue, 2 Jan 2024 10:03:03 +0100 Subject: [PATCH 2/3] fix: change merge request delay default value in tests --- lib/modules/platform/gitlab/index.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index 7740a9c8944dc9..428def044c39f9 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -52,6 +52,7 @@ describe('modules/platform/gitlab/index', () => { delete process.env.GITLAB_IGNORE_REPO_URL; delete process.env.RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY; delete process.env.RENOVATE_X_GITLAB_AUTO_MERGEABLE_CHECK_ATTEMPS; + delete process.env.RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY; }); async function initFakePlatform(version: string) { @@ -1843,7 +1844,7 @@ describe('modules/platform/gitlab/index', () => { .put('/api/v4/projects/undefined/merge_requests/12345/merge') .reply(200); process.env.RENOVATE_X_GITLAB_AUTO_MERGEABLE_CHECK_ATTEMPS = '3'; - process.env.RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY = '250'; + process.env.RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY = '100'; const pr = await gitlab.createPr({ sourceBranch: 'some-branch', targetBranch: 'master', From 3062f07ad082b2b74dcbd819fbda356b086608f6 Mon Sep 17 00:00:00 2001 From: javaxiss Date: Wed, 3 Jan 2024 10:27:54 +0100 Subject: [PATCH 3/3] fix: unit test --- lib/modules/platform/gitlab/index.spec.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index 428def044c39f9..0127a04a8477b4 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -1861,11 +1861,7 @@ describe('modules/platform/gitlab/index', () => { sourceBranch: 'some-branch', title: 'some title', }); - expect(timers.setTimeout.mock.calls).toMatchObject([ - [250], - [1000], - [2250], - ]); + expect(timers.setTimeout.mock.calls).toMatchObject([[100], [400], [900]]); }); it('raises with squash enabled when repository squash option is default_on', async () => {