From 4ef1cd20ad417c5d6c60aff8c50b23b07e6c8df9 Mon Sep 17 00:00:00 2001
From: Mikko Piuhola <mikkopiu@users.noreply.github.com>
Date: Fri, 7 Jul 2023 14:26:35 +0300
Subject: [PATCH] feat(platform/gitlab): Allow custom delay for pipeline status
 via experimental variable (#23239)

---
 docs/usage/self-hosted-experimental.md    |  8 ++++
 lib/modules/platform/gitlab/index.spec.ts | 55 +++++++++++++++++++++++
 lib/modules/platform/gitlab/index.ts      |  6 ++-
 3 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/docs/usage/self-hosted-experimental.md b/docs/usage/self-hosted-experimental.md
index 010813cb66..5679da5915 100644
--- a/docs/usage/self-hosted-experimental.md
+++ b/docs/usage/self-hosted-experimental.md
@@ -124,6 +124,14 @@ If set, Renovate will rewrite GitHub Enterprise Server's pagination responses to
 !!! note
     For the GitHub Enterprise Server platform only.
 
+## `RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY`
+
+Adjust default time (in milliseconds) given to GitLab to create pipelines for a commit pushed by Renovate.
+
+Can be useful for slow-running, self-hosted GitLab instances that don't react fast enough for the default delay to help.
+
+Default value: `1000` (milliseconds).
+
 ## `OTEL_EXPORTER_OTLP_ENDPOINT`
 
 If set, Renovate will export OpenTelemetry data to the supplied endpoint.
diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts
index cd587598c4..462978f26c 100644
--- a/lib/modules/platform/gitlab/index.spec.ts
+++ b/lib/modules/platform/gitlab/index.spec.ts
@@ -1,4 +1,5 @@
 // TODO fix mocks
+import type * as _timers from 'timers/promises';
 import type { Platform, RepoParams } from '..';
 import * as httpMock from '../../../../test/http-mock';
 import {
@@ -22,6 +23,7 @@ describe('modules/platform/gitlab/index', () => {
   let hostRules: jest.Mocked<typeof _hostRules>;
   let git: jest.Mocked<typeof _git>;
   let logger: jest.Mocked<typeof _logger>;
+  let timers: jest.Mocked<typeof _timers>;
 
   beforeEach(async () => {
     // reset module
@@ -32,6 +34,7 @@ describe('modules/platform/gitlab/index', () => {
     logger = (await import('../../../logger')).logger as never;
     jest.mock('../../../util/host-rules');
     jest.mock('timers/promises');
+    timers = require('timers/promises');
     hostRules = require('../../../util/host-rules');
     jest.mock('../../../util/git');
     git = require('../../../util/git');
@@ -44,6 +47,7 @@ describe('modules/platform/gitlab/index', () => {
       token: '123test',
     });
     delete process.env.GITLAB_IGNORE_REPO_URL;
+    delete process.env.RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY;
   });
 
   async function initFakePlatform(version: string) {
@@ -827,6 +831,57 @@ describe('modules/platform/gitlab/index', () => {
         })
       ).toResolve();
     });
+
+    it('waits for 1000ms by default', async () => {
+      const scope = await initRepo();
+      scope
+        .post(
+          '/api/v4/projects/some%2Frepo/statuses/0d9c7726c3d628b7e28af234595cfd20febdbf8e'
+        )
+        .reply(200, {})
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, []);
+
+      await gitlab.setBranchStatus({
+        branchName: 'some-branch',
+        context: 'some-context',
+        description: 'some-description',
+        state: 'green',
+        url: 'some-url',
+      });
+
+      expect(timers.setTimeout.mock.calls).toHaveLength(1);
+      expect(timers.setTimeout.mock.calls[0][0]).toBe(1000);
+    });
+
+    it('waits for RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY ms when set', async () => {
+      const delay = 5000;
+      process.env.RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY = String(delay);
+
+      const scope = await initRepo();
+      scope
+        .post(
+          '/api/v4/projects/some%2Frepo/statuses/0d9c7726c3d628b7e28af234595cfd20febdbf8e'
+        )
+        .reply(200, {})
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, []);
+
+      await gitlab.setBranchStatus({
+        branchName: 'some-branch',
+        context: 'some-context',
+        description: 'some-description',
+        state: 'green',
+        url: 'some-url',
+      });
+
+      expect(timers.setTimeout.mock.calls).toHaveLength(1);
+      expect(timers.setTimeout.mock.calls[0][0]).toBe(delay);
+    });
   });
 
   describe('findIssue()', () => {
diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts
index d4f10275e8..523581a22e 100644
--- a/lib/modules/platform/gitlab/index.ts
+++ b/lib/modules/platform/gitlab/index.ts
@@ -866,7 +866,11 @@ export async function setBranchStatus({
   }
   try {
     // give gitlab some time to create pipelines for the sha
-    await setTimeout(1000);
+    await setTimeout(
+      process.env.RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY
+        ? parseInt(process.env.RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY, 10)
+        : 1000
+    );
 
     await gitlabApi.postJson(url, { body: options });
 
-- 
GitLab