From d5aeb500049ac2899c25bd6ac0dc7dfb4ffaa148 Mon Sep 17 00:00:00 2001
From: Sergio Zharinov <zharinov@users.noreply.github.com>
Date: Sun, 17 May 2020 23:42:15 +0400
Subject: [PATCH] refactor(gitlab): Use nock for tests (#6267)

---
 .../__snapshots__/gl-got-wrapper.spec.ts.snap |   71 +
 .../gitlab/__snapshots__/index.spec.ts.snap   | 2302 ++++++++++++++++-
 lib/platform/gitlab/gl-got-wrapper.spec.ts    |   76 +-
 lib/platform/gitlab/index.spec.ts             | 1322 +++++-----
 4 files changed, 3006 insertions(+), 765 deletions(-)
 create mode 100644 lib/platform/gitlab/__snapshots__/gl-got-wrapper.spec.ts.snap

diff --git a/lib/platform/gitlab/__snapshots__/gl-got-wrapper.spec.ts.snap b/lib/platform/gitlab/__snapshots__/gl-got-wrapper.spec.ts.snap
new file mode 100644
index 0000000000..728ddbe5b3
--- /dev/null
+++ b/lib/platform/gitlab/__snapshots__/gl-got-wrapper.spec.ts.snap
@@ -0,0 +1,71 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`platform/gitlab/gl-got-wrapper attempts to paginate 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/some-url",
+  },
+]
+`;
+
+exports[`platform/gitlab/gl-got-wrapper paginates 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/some-url",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/some-url&page=2",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/some-url&page=3",
+  },
+]
+`;
+
+exports[`platform/gitlab/gl-got-wrapper posts 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "POST",
+    "url": "https://gitlab.com/api/v4/some-url",
+  },
+]
+`;
diff --git a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap
index 0f7f181e81..7fd9d13874 100644
--- a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap
+++ b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap
@@ -2,53 +2,236 @@
 
 exports[`platform/gitlab addAssignees(issueNo, assignees) should add the given assignees to the issue 1`] = `
 Array [
-  Array [
-    "projects/undefined/merge_requests/42?assignee_id=123",
-  ],
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/users?username=someuser",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 0,
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/42?assignee_id=123",
+  },
 ]
 `;
 
 exports[`platform/gitlab addAssignees(issueNo, assignees) should add the given assignees to the issue if supported 1`] = `
 Array [
-  Array [
-    "projects/undefined/merge_requests/42?assignee_id=123",
-  ],
-  Array [
-    "projects/undefined/merge_requests/42?assignee_ids[]=123&assignee_ids[]=124",
-  ],
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/users?username=someuser",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 0,
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/42?assignee_id=123",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/users?username=someotheruser",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 0,
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/42?assignee_ids[]=123&assignee_ids[]=124",
+  },
+]
+`;
+
+exports[`platform/gitlab addAssignees(issueNo, assignees) should swallow error 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/users?username=someuser",
+  },
 ]
 `;
 
 exports[`platform/gitlab addAssignees(issueNo, assignees) should warn if more than one assignee 1`] = `
 Array [
-  Array [
-    "projects/undefined/merge_requests/42?assignee_id=123",
-  ],
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/users?username=someuser",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 0,
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/42?assignee_id=123",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/users?username=someotheruser",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 0,
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/42?assignee_ids[]=123&assignee_ids[]=124",
+  },
+]
+`;
+
+exports[`platform/gitlab addReviewers(issueNo, reviewers) should add the given reviewers to the PR 1`] = `Array []`;
+
+exports[`platform/gitlab branchExists() getFileList() sends to gitFs 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
 ]
 `;
 
 exports[`platform/gitlab commitFiles() sends to gitFs 1`] = `
 Array [
-  Array [
-    "projects/some%2Frepo",
-  ],
-  Array [
-    "user",
-  ],
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
 ]
 `;
 
 exports[`platform/gitlab createPr(branchName, title, body) auto-accepts the MR when requested 1`] = `
 Array [
-  Array [
-    "projects/undefined/merge_requests/12345/merge",
-    Object {
-      "body": Object {
-        "merge_when_pipeline_succeeds": true,
-        "should_remove_source_branch": true,
-      },
+  Object {
+    "body": "{\\"source_branch\\":\\"some-branch\\",\\"remove_source_branch\\":true,\\"title\\":\\"some-title\\",\\"description\\":\\"the-body\\",\\"labels\\":\\"\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 117,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
     },
-  ],
+    "method": "POST",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests",
+  },
+  Object {
+    "body": "{\\"should_remove_source_branch\\":true,\\"merge_when_pipeline_succeeds\\":true}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 72,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/12345/merge",
+  },
 ]
 `;
 
@@ -65,19 +248,20 @@ Object {
 
 exports[`platform/gitlab createPr(branchName, title, body) returns the PR 2`] = `
 Array [
-  Array [
-    "projects/undefined/merge_requests",
-    Object {
-      "body": Object {
-        "description": "the-body",
-        "labels": null,
-        "remove_source_branch": true,
-        "source_branch": "some-branch",
-        "target_branch": undefined,
-        "title": "some-title",
-      },
+  Object {
+    "body": "{\\"source_branch\\":\\"some-branch\\",\\"remove_source_branch\\":true,\\"title\\":\\"some-title\\",\\"description\\":\\"the-body\\",\\"labels\\":null}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 119,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
     },
-  ],
+    "method": "POST",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests",
+  },
 ]
 `;
 
@@ -94,87 +278,1221 @@ Object {
 
 exports[`platform/gitlab createPr(branchName, title, body) uses default branch 2`] = `
 Array [
-  Array [
-    "projects/undefined/merge_requests",
-    Object {
-      "body": Object {
-        "description": "the-body",
-        "labels": "",
-        "remove_source_branch": true,
-        "source_branch": "some-branch",
-        "target_branch": undefined,
-        "title": "some-title",
-      },
+  Object {
+    "body": "{\\"source_branch\\":\\"some-branch\\",\\"remove_source_branch\\":true,\\"title\\":\\"some-title\\",\\"description\\":\\"the-body\\",\\"labels\\":\\"\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 117,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "POST",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests",
+  },
+]
+`;
+
+exports[`platform/gitlab deleteBranch() defaults to not closing associated PR 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab deleteBranch() sends to gitFs 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
     },
-  ],
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests?per_page=100&state=opened&source_branch=branch",
+  },
 ]
 `;
 
 exports[`platform/gitlab deleteLabel(issueNo, label) should delete the label 1`] = `
 Array [
-  Array [
-    "projects/undefined/merge_requests/42",
-    Object {
-      "body": Object {
-        "labels": "foo,renovate",
-      },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/42?include_diverged_commits_count=1",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/repository/branches/some-branch",
+  },
+  Object {
+    "body": "{\\"labels\\":\\"foo,renovate\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 25,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
     },
-  ],
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/42",
+  },
 ]
 `;
 
 exports[`platform/gitlab ensureComment add comment if not found 1`] = `
 Array [
-  Array [
-    "projects/some%2Frepo/merge_requests/42/notes",
-    Object {
-      "body": Object {
-        "body": "### some-subject
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes",
+  },
+  Object {
+    "body": "{\\"body\\":\\"### some-subject\\\\n\\\\nsome\\\\ncontent\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 44,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "POST",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes",
+  },
+]
+`;
+
+exports[`platform/gitlab ensureComment add updates comment if necessary 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes",
+  },
+  Object {
+    "body": "{\\"body\\":\\"### some-subject\\\\n\\\\nsome\\\\ncontent\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 44,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes/1234",
+  },
+]
+`;
+
+exports[`platform/gitlab ensureComment handles comment with no description 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes",
+  },
+]
+`;
+
+exports[`platform/gitlab ensureComment skips comment 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes",
+  },
+]
+`;
+
+exports[`platform/gitlab ensureCommentRemoval deletes comment by content if found 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "DELETE",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes/1234",
+  },
+]
+`;
+
+exports[`platform/gitlab ensureCommentRemoval deletes comment by topic if found 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "DELETE",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/42/notes/1234",
+  },
+]
+`;
+
+exports[`platform/gitlab ensureIssue() creates issue 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues?state=opened",
+  },
+  Object {
+    "body": "{\\"title\\":\\"new-title\\",\\"description\\":\\"new-content\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 49,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "POST",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues",
+  },
+]
+`;
+
+exports[`platform/gitlab ensureIssue() skips update if unchanged 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues?state=opened",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues/2",
+  },
+]
+`;
+
+exports[`platform/gitlab ensureIssue() updates issue 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues?state=opened",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues/2",
+  },
+  Object {
+    "body": "{\\"description\\":\\"newer-content\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 31,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues/2",
+  },
+]
+`;
+
+exports[`platform/gitlab ensureIssueClosing() closes issue 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues?state=opened",
+  },
+  Object {
+    "body": "{\\"state_event\\":\\"close\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 23,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues/2",
+  },
+]
+`;
+
+exports[`platform/gitlab findIssue() finds issue 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues?state=opened",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues/2",
+  },
+]
+`;
+
+exports[`platform/gitlab findIssue() returns null if no issue 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/issues?state=opened",
+  },
+]
+`;
+
+exports[`platform/gitlab findPr(branchName, prTitle, state) returns true if no title and all state 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests?per_page=100&author_id=undefined",
+  },
+]
+`;
+
+exports[`platform/gitlab findPr(branchName, prTitle, state) returns true if not open 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests?per_page=100&author_id=undefined",
+  },
+]
+`;
+
+exports[`platform/gitlab findPr(branchName, prTitle, state) returns true if open and with title 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests?per_page=100&author_id=undefined",
+  },
+]
+`;
+
+exports[`platform/gitlab findPr(branchName, prTitle, state) returns true with title 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests?per_page=100&author_id=undefined",
+  },
+]
+`;
+
+exports[`platform/gitlab getAllRenovateBranches() sends to gitFs 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchLastCommitTime() sends to gitFs 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchPr(branchName) should return null if no PR exists 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests?per_page=100&state=opened&source_branch=some-branch",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchPr(branchName) should return the PR object 1`] = `
+Object {
+  "additions": 1,
+  "base": Object {
+    "sha": "1234",
+  },
+  "body": undefined,
+  "branchName": "some-branch",
+  "commits": 1,
+  "deletions": 1,
+  "displayNumber": "Merge Request #91",
+  "iid": 91,
+  "isModified": true,
+  "isStale": false,
+  "number": 91,
+  "source_branch": "some-branch",
+  "state": "open",
+  "targetBranch": "master",
+  "target_branch": "master",
+}
+`;
+
+exports[`platform/gitlab getBranchPr(branchName) should return the PR object 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests?per_page=100&state=opened&source_branch=some-branch",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/91?include_diverged_commits_count=1",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/branches/some-branch",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchStatus(branchName, requiredStatusChecks) maps custom statuses to yellow 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchStatus(branchName, requiredStatusChecks) returns failure if any mandatory jobs fails 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchStatus(branchName, requiredStatusChecks) returns pending if no results 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchStatus(branchName, requiredStatusChecks) returns success if all are optional 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchStatus(branchName, requiredStatusChecks) returns success if all are success 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchStatus(branchName, requiredStatusChecks) returns success if optional jobs fail 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchStatus(branchName, requiredStatusChecks) throws repository-changed 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab getBranchStatusCheck returns null if no matching results 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
 
-some
-content",
-      },
+exports[`platform/gitlab getBranchStatusCheck returns null if no results 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
     },
-  ],
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
 ]
 `;
 
-exports[`platform/gitlab ensureComment add updates comment if necessary 1`] = `
+exports[`platform/gitlab getBranchStatusCheck returns status if name found 1`] = `
 Array [
-  Array [
-    "projects/some%2Frepo/merge_requests/42/notes/1234",
-    Object {
-      "body": Object {
-        "body": "### some-subject
-
-some
-content",
-      },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
     },
-  ],
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
 ]
 `;
 
-exports[`platform/gitlab getBranchPr(branchName) should return the PR object 1`] = `
-Object {
-  "additions": 1,
-  "base": Object {
-    "sha": "1234",
+exports[`platform/gitlab getFileList() sends to gitFs 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
   },
-  "body": undefined,
-  "branchName": "some-branch",
-  "commits": 1,
-  "deletions": 1,
-  "displayNumber": "Merge Request #91",
-  "iid": 91,
-  "isModified": true,
-  "isStale": false,
-  "number": 91,
-  "source_branch": "some-branch",
-  "state": "open",
-  "targetBranch": "master",
-  "target_branch": "master",
-}
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
 `;
 
 exports[`platform/gitlab getPr(prNo) returns the PR 1`] = `
@@ -199,6 +1517,33 @@ Object {
 }
 `;
 
+exports[`platform/gitlab getPr(prNo) returns the PR 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/12345?include_diverged_commits_count=1",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/repository/branches/some-branch",
+  },
+]
+`;
+
 exports[`platform/gitlab getPr(prNo) returns the PR with nonexisting branch 1`] = `
 Object {
   "body": "a merge request",
@@ -221,6 +1566,33 @@ Object {
 }
 `;
 
+exports[`platform/gitlab getPr(prNo) returns the PR with nonexisting branch 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/12345?include_diverged_commits_count=1",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/repository/branches/some-branch",
+  },
+]
+`;
+
 exports[`platform/gitlab getPr(prNo) returns the mergeable PR 1`] = `
 Object {
   "body": "a merge request",
@@ -241,6 +1613,66 @@ Object {
 }
 `;
 
+exports[`platform/gitlab getPr(prNo) returns the mergeable PR 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/merge_requests/12345?include_diverged_commits_count=1",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/branches/some-branch",
+  },
+]
+`;
+
 exports[`platform/gitlab getPrBody(input) returns updated pr body 1`] = `
 "https://github.com/foo/bar/issues/5 plus also [a link](https://github.com/foo/bar/issues/5
 
@@ -261,24 +1693,142 @@ Array [
 ]
 `;
 
-exports[`platform/gitlab getRepos should return an array of repos 1`] = `
+exports[`platform/gitlab getPrFiles() returns files 2`] = `
 Array [
-  Array [
-    "projects?membership=true&per_page=100&with_merge_requests_enabled=true",
-    Object {
-      "paginate": true,
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
     },
-  ],
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/123/changes",
+  },
 ]
 `;
 
-exports[`platform/gitlab getRepos should return an array of repos 2`] = `
+exports[`platform/gitlab getRepoForceRebase should return false 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab getRepoForceRebase should return true 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab getRepoStatus() exists 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab getRepos should return an array of repos 1`] = `
 Array [
   "a/b",
   "c/d",
 ]
 `;
 
+exports[`platform/gitlab getRepos should return an array of repos 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects?membership=true&per_page=100&with_merge_requests_enabled=true",
+  },
+]
+`;
+
+exports[`platform/gitlab getRepos should throw an error if it receives an error 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects?membership=true&per_page=100&with_merge_requests_enabled=true",
+  },
+]
+`;
+
 exports[`platform/gitlab initPlatform() should accept custom endpoint 1`] = `
 Object {
   "endpoint": "https://gitlab.renovatebot.com/",
@@ -286,6 +1836,22 @@ Object {
 }
 `;
 
+exports[`platform/gitlab initPlatform() should accept custom endpoint 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.renovatebot.com",
+      "private-token": "some-token",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.renovatebot.com/user",
+  },
+]
+`;
+
 exports[`platform/gitlab initPlatform() should default to gitlab.com 1`] = `
 Object {
   "endpoint": "https://gitlab.com/api/v4/",
@@ -293,35 +1859,529 @@ Object {
 }
 `;
 
+exports[`platform/gitlab initPlatform() should default to gitlab.com 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "some-token",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab initPlatform() should throw if auth fails 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "some-token",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
 exports[`platform/gitlab initRepo should escape all forward slashes in project names 1`] = `
 Array [
-  Array [
-    "projects/some%2Frepo%2Fproject",
-  ],
-  Array [
-    "user",
-  ],
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
 ]
 `;
 
 exports[`platform/gitlab initRepo should fall back if http_url_to_repo is empty 1`] = `
 Array [
-  Array [
-    "projects/some%2Frepo%2Fproject",
-  ],
-  Array [
-    "user",
-  ],
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab initRepo should throw an error if MRs are disabled 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+]
+`;
+
+exports[`platform/gitlab initRepo should throw an error if receiving an error 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+]
+`;
+
+exports[`platform/gitlab initRepo should throw an error if repository access is disabled 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+]
+`;
+
+exports[`platform/gitlab initRepo should throw an error if repository has empty_repo property 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+]
+`;
+
+exports[`platform/gitlab initRepo should throw an error if repository is a mirror 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+]
+`;
+
+exports[`platform/gitlab initRepo should throw an error if repository is archived 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+]
+`;
+
+exports[`platform/gitlab initRepo should throw an error if repository is empty 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+]
+`;
+
+exports[`platform/gitlab initRepo should throw error if disabled in renovate.json 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/files/renovate.json?ref=master",
+  },
+]
+`;
+
+exports[`platform/gitlab isBranchStale() sends to gitFs 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab mergeBranch() sends to gitFs 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab mergePr(pr) merges the PR 1`] = `
+Array [
+  Object {
+    "body": "{\\"should_remove_source_branch\\":true}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 36,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/1/merge",
+  },
 ]
 `;
 
 exports[`platform/gitlab setBaseBranch(branchName) sets the base branch 1`] = `
 Array [
-  Array [
-    "projects/some%2Frepo",
-  ],
-  Array [
-    "user",
-  ],
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab setBaseBranch(branchName) uses default base branch 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+]
+`;
+
+exports[`platform/gitlab setBranchStatus sets branch status green 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "body": "{\\"state\\":\\"success\\",\\"description\\":\\"some-description\\",\\"context\\":\\"some-context\\",\\"target_url\\":\\"some-url\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 101,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "POST",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/statuses/0d9c7726c3d628b7e28af234595cfd20febdbf8e",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
+
+exports[`platform/gitlab setBranchStatus sets branch status red 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "body": "{\\"state\\":\\"failed\\",\\"description\\":\\"some-description\\",\\"context\\":\\"some-context\\",\\"target_url\\":\\"some-url\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 100,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "POST",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/statuses/0d9c7726c3d628b7e28af234595cfd20febdbf8e",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
+
+exports[`platform/gitlab setBranchStatus sets branch status yellow 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/user",
+  },
+  Object {
+    "body": "{\\"state\\":\\"pending\\",\\"description\\":\\"some-description\\",\\"context\\":\\"some-context\\",\\"target_url\\":\\"some-url\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 101,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "POST",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/statuses/0d9c7726c3d628b7e28af234595cfd20febdbf8e",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses",
+  },
+]
+`;
+
+exports[`platform/gitlab updatePr(prNo, title, body) updates the PR 1`] = `
+Array [
+  Object {
+    "body": "{\\"title\\":\\"title\\",\\"description\\":\\"body\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "content-length": 38,
+      "content-type": "application/json",
+      "host": "gitlab.com",
+      "private-token": "abc123",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "PUT",
+    "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/1",
+  },
 ]
 `;
diff --git a/lib/platform/gitlab/gl-got-wrapper.spec.ts b/lib/platform/gitlab/gl-got-wrapper.spec.ts
index 5b715858b9..366277f3db 100644
--- a/lib/platform/gitlab/gl-got-wrapper.spec.ts
+++ b/lib/platform/gitlab/gl-got-wrapper.spec.ts
@@ -1,67 +1,65 @@
+import * as httpMock from '../../../test/httpMock';
 import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms';
-import _got from '../../util/got';
+import * as runCache from '../../util/cache/run';
 import * as hostRules from '../../util/host-rules';
 import { api } from './gl-got-wrapper';
 
-jest.mock('../../util/got');
-
-const got: any = _got;
-
 hostRules.add({
   hostType: PLATFORM_TYPE_GITLAB,
   token: 'abc123',
 });
 
+const gitlabApiHost = 'https://gitlab.com';
+
 describe('platform/gitlab/gl-got-wrapper', () => {
   const body = ['a', 'b'];
+  beforeEach(() => {
+    // (delay as any).mockImplementation(() => Promise.resolve());
+    httpMock.setup();
+  });
   afterEach(() => {
     jest.resetAllMocks();
+    httpMock.reset();
+    runCache.clear();
   });
   it('paginates', async () => {
-    got.mockReturnValueOnce({
-      headers: {
+    httpMock
+      .scope(gitlabApiHost)
+      .get('/api/v4/some-url')
+      .reply(200, ['a'], {
         link:
-          '<https://api.gitlab.com/search/code?q=addClass+user%3Amozilla&page=2>; rel="next", <https://api.gitlab.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last"',
-      },
-      body: ['a'],
-    });
-    got.mockReturnValueOnce({
-      headers: {
+          '<https://gitlab.com/api/v4/some-url&page=2>; rel="next", <https://gitlab.com/api/v4/some-url&page=3>; rel="last"',
+      })
+      .get('/api/v4/some-url&page=2')
+      .reply(200, ['b', 'c'], {
         link:
-          '<https://api.gitlab.com/search/code?q=addClass+user%3Amozilla&page=3>; rel="next", <https://api.gitlab.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last"',
-      },
-      body: ['b', 'c'],
-    });
-    got.mockReturnValueOnce({
-      headers: {},
-      body: ['d'],
-    });
-    const res = await api.get('some-url', { paginate: true });
+          '<https://gitlab.com/api/v4/some-url&page=3>; rel="next", <https://gitlab.com/api/v4/some-url&page=3>; rel="last"',
+      })
+      .get('/api/v4/some-url&page=3')
+      .reply(200, ['d']);
+    const res = await api.get('/some-url', { paginate: true });
     expect(res.body).toHaveLength(4);
-    expect(got).toHaveBeenCalledTimes(3);
+
+    const trace = httpMock.getTrace();
+    expect(trace).toHaveLength(3);
+    expect(trace).toMatchSnapshot();
   });
   it('attempts to paginate', async () => {
-    got.mockReturnValueOnce({
-      headers: {
-        link:
-          '<https://api.gitlab.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last"',
-      },
-      body: ['a'],
+    httpMock.scope(gitlabApiHost).get('/api/v4/some-url').reply(200, ['a'], {
+      link: '<https://gitlab.com/api/v4/some-url&page=3>; rel="last"',
     });
-    got.mockReturnValueOnce({
-      headers: {},
-      body: ['b'],
-    });
-    const res = await api.get('some-url', { paginate: true });
+    const res = await api.get('/some-url', { paginate: true });
     expect(res.body).toHaveLength(1);
-    expect(got).toHaveBeenCalledTimes(1);
+
+    const trace = httpMock.getTrace();
+    expect(trace).toHaveLength(1);
+    expect(trace).toMatchSnapshot();
   });
   it('posts', async () => {
-    got.mockImplementationOnce(() => ({
-      body,
-    }));
-    const res = await api.post('some-url');
+    httpMock.scope(gitlabApiHost).post('/api/v4/some-url').reply(200, body);
+    const res = await api.post('/some-url');
     expect(res.body).toEqual(body);
+    expect(httpMock.getTrace()).toMatchSnapshot();
   });
   it('sets baseUrl', () => {
     api.setBaseUrl('https://gitlab.renovatebot.com/api/v4/');
diff --git a/lib/platform/gitlab/index.spec.ts b/lib/platform/gitlab/index.spec.ts
index 6fe998e3d1..b683dd964a 100644
--- a/lib/platform/gitlab/index.spec.ts
+++ b/lib/platform/gitlab/index.spec.ts
@@ -1,5 +1,6 @@
-import { GotResponse, Platform } from '..';
-import { partial } from '../../../test/util';
+import nock from 'nock';
+import { Platform, RepoParams } from '..';
+import * as httpMock from '../../../test/httpMock';
 import {
   REPOSITORY_ARCHIVED,
   REPOSITORY_CHANGED,
@@ -12,20 +13,20 @@ import {
   PR_STATE_OPEN,
 } from '../../constants/pull-requests';
 import { BranchStatus } from '../../types';
+import * as runCache from '../../util/cache/run';
 import * as _hostRules from '../../util/host-rules';
 
+const gitlabApiHost = 'https://gitlab.com';
+
 describe('platform/gitlab', () => {
   let gitlab: Platform;
-  let api: jest.Mocked<typeof import('./gl-got-wrapper').api>;
   let hostRules: jest.Mocked<typeof _hostRules>;
   let GitStorage: jest.Mocked<typeof import('../git/storage')> & jest.Mock;
   beforeEach(async () => {
     // reset module
     jest.resetModules();
     jest.resetAllMocks();
-    jest.mock('./gl-got-wrapper');
     gitlab = await import('.');
-    api = require('./gl-got-wrapper').api;
     jest.mock('../../util/host-rules');
     hostRules = require('../../util/host-rules');
     jest.mock('../git/storage');
@@ -52,6 +53,9 @@ describe('platform/gitlab', () => {
     hostRules.find.mockReturnValue({
       token: 'abc123',
     });
+    runCache.clear();
+    httpMock.reset();
+    httpMock.setup();
   });
 
   afterEach(async () => {
@@ -64,103 +68,106 @@ describe('platform/gitlab', () => {
     });
     it(`should throw if auth fails`, async () => {
       // user
-      api.get.mockRejectedValueOnce(new Error('403'));
-      await expect(
-        gitlab.initPlatform({ token: 'some-token', endpoint: undefined })
-      ).rejects.toThrow();
+      httpMock.scope(gitlabApiHost).get('/api/v4/user').reply(403);
+      const res = gitlab.initPlatform({
+        token: 'some-token',
+        endpoint: undefined,
+      });
+      await expect(res).rejects.toThrow('Init: Authentication failure');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it(`should default to gitlab.com`, async () => {
-      // user
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            email: 'a@b.com',
-            name: 'Renovate Bot',
-          },
-        })
-      );
+      httpMock.scope(gitlabApiHost).get('/api/v4/user').reply(200, {
+        email: 'a@b.com',
+        name: 'Renovate Bot',
+      });
       expect(
-        await gitlab.initPlatform({ token: 'some-token', endpoint: undefined })
+        await gitlab.initPlatform({
+          token: 'some-token',
+          endpoint: undefined,
+        })
       ).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it(`should accept custom endpoint`, async () => {
-      // user
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            email: 'a@b.com',
-            name: 'Renovate Bot',
-          },
-        })
-      );
+      httpMock.scope('https://gitlab.renovatebot.com').get('/user').reply(200, {
+        email: 'a@b.com',
+        name: 'Renovate Bot',
+      });
       expect(
         await gitlab.initPlatform({
           endpoint: 'https://gitlab.renovatebot.com',
           token: 'some-token',
         })
       ).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
 
   describe('getRepos', () => {
-    function getRepos() {
-      // repo info
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              path_with_namespace: 'a/b',
-            },
-            {
-              path_with_namespace: 'c/d',
-            },
-          ],
-        })
-      );
-      return gitlab.getRepos();
-    }
     it('should throw an error if it receives an error', async () => {
-      api.get.mockRejectedValueOnce(new Error('getRepos error'));
+      httpMock
+        .scope(gitlabApiHost)
+        .get(
+          '/api/v4/projects?membership=true&per_page=100&with_merge_requests_enabled=true'
+        )
+        .replyWithError('getRepos error');
       await expect(gitlab.getRepos()).rejects.toThrow('getRepos error');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should return an array of repos', async () => {
-      const repos = await getRepos();
-      expect(api.get.mock.calls).toMatchSnapshot();
+      httpMock
+        .scope(gitlabApiHost)
+        .get(
+          '/api/v4/projects?membership=true&per_page=100&with_merge_requests_enabled=true'
+        )
+        .reply(200, [
+          {
+            path_with_namespace: 'a/b',
+          },
+          {
+            path_with_namespace: 'c/d',
+          },
+        ]);
+      const repos = await gitlab.getRepos();
       expect(repos).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
-  function initRepo(args?: any) {
-    // projects/${config.repository}
-    api.get.mockResolvedValueOnce(
-      partial<GotResponse>({
-        body: {
-          default_branch: 'master',
-          http_url_to_repo: 'https://gitlab.com/some/repo.git',
-        },
-      })
-    );
-    // getBranchCommit
-    // user
-    api.get.mockResolvedValueOnce(
-      partial<GotResponse>({
-        body: {
-          email: 'a@b.com',
-        },
-      })
-    );
-    if (args) {
-      return gitlab.initRepo(args);
-    }
-    return gitlab.initRepo({
+
+  async function initRepo(
+    repoParams: RepoParams = {
       repository: 'some/repo',
       localDir: '',
       optimizeForDisabled: false,
-    });
+    },
+    repoResp = null,
+    scope = httpMock.scope(gitlabApiHost)
+  ): Promise<nock.Scope> {
+    const repo = repoParams.repository;
+    const justRepo = repo.split('/').slice(0, 2).join('/');
+    scope
+      .get(`/api/v4/projects/${encodeURIComponent(repo)}`)
+      .reply(
+        200,
+        repoResp || {
+          default_branch: 'master',
+          http_url_to_repo: `https://gitlab.com/${justRepo}.git`,
+        }
+      )
+      .get('/api/v4/user')
+      .reply(200, {
+        email: 'a@b.com',
+      });
+    await gitlab.initRepo(repoParams);
+    return scope;
   }
+
   describe('getRepoStatus()', () => {
     it('exists', async () => {
       await initRepo();
       await gitlab.getRepoStatus();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('cleanRepo()', () => {
@@ -171,21 +178,19 @@ describe('platform/gitlab', () => {
 
   describe('initRepo', () => {
     it(`should throw error if disabled in renovate.json`, async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            default_branch: 'master',
-            http_url_to_repo: 'https://gitlab.com/some/repo.git',
-          },
-        })
-      );
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            content: Buffer.from('{"enabled": false}').toString('base64'),
-          },
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/some%2Frepo')
+        .reply(200, {
+          default_branch: 'master',
+          http_url_to_repo: 'https://gitlab.com/some/repo.git',
         })
-      );
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/files/renovate.json?ref=master'
+        )
+        .reply(200, {
+          content: Buffer.from('{"enabled": false}').toString('base64'),
+        });
       await expect(
         gitlab.initRepo({
           repository: 'some/repo',
@@ -193,16 +198,29 @@ describe('platform/gitlab', () => {
           optimizeForDisabled: true,
         })
       ).rejects.toThrow(REPOSITORY_DISABLED);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it(`should escape all forward slashes in project names`, async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: [] })
-      );
-      await initRepo({ repository: 'some/repo/project', token: 'some-token' });
-      expect(api.get.mock.calls).toMatchSnapshot();
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/some%2Frepo%2Fproject')
+        .reply(200, [])
+        .get('/api/v4/user')
+        .reply(200, {
+          email: 'a@b.com',
+        });
+      await gitlab.initRepo({
+        repository: 'some/repo/project',
+        localDir: '',
+        optimizeForDisabled: false,
+      });
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should throw an error if receiving an error', async () => {
-      api.get.mockRejectedValueOnce(new Error('always error'));
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/some%2Frepo')
+        .replyWithError('always error');
       await expect(
         gitlab.initRepo({
           repository: 'some/repo',
@@ -210,11 +228,13 @@ describe('platform/gitlab', () => {
           optimizeForDisabled: false,
         })
       ).rejects.toThrow('always error');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should throw an error if repository is archived', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: { archived: true } })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/some%2Frepo')
+        .reply(200, { archived: true });
       await expect(
         gitlab.initRepo({
           repository: 'some/repo',
@@ -222,11 +242,13 @@ describe('platform/gitlab', () => {
           optimizeForDisabled: false,
         })
       ).rejects.toThrow(REPOSITORY_ARCHIVED);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should throw an error if repository is a mirror', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: { mirror: true } })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/some%2Frepo')
+        .reply(200, { mirror: true });
       await expect(
         gitlab.initRepo({
           repository: 'some/repo',
@@ -234,13 +256,13 @@ describe('platform/gitlab', () => {
           optimizeForDisabled: false,
         })
       ).rejects.toThrow(REPOSITORY_MIRRORED);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should throw an error if repository access is disabled', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: { repository_access_level: 'disabled' },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/some%2Frepo')
+        .reply(200, { repository_access_level: 'disabled' });
       await expect(
         gitlab.initRepo({
           repository: 'some/repo',
@@ -248,13 +270,13 @@ describe('platform/gitlab', () => {
           optimizeForDisabled: false,
         })
       ).rejects.toThrow(REPOSITORY_DISABLED);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should throw an error if MRs are disabled', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: { merge_requests_access_level: 'disabled' },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/some%2Frepo')
+        .reply(200, { merge_requests_access_level: 'disabled' });
       await expect(
         gitlab.initRepo({
           repository: 'some/repo',
@@ -262,11 +284,13 @@ describe('platform/gitlab', () => {
           optimizeForDisabled: false,
         })
       ).rejects.toThrow(REPOSITORY_DISABLED);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should throw an error if repository has empty_repo property', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: { empty_repo: true } })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/some%2Frepo')
+        .reply(200, { empty_repo: true });
       await expect(
         gitlab.initRepo({
           repository: 'some/repo',
@@ -274,11 +298,13 @@ describe('platform/gitlab', () => {
           optimizeForDisabled: false,
         })
       ).rejects.toThrow(REPOSITORY_EMPTY);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should throw an error if repository is empty', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: { default_branch: null } })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/some%2Frepo')
+        .reply(200, { default_branch: null });
       await expect(
         gitlab.initRepo({
           repository: 'some/repo',
@@ -286,64 +312,108 @@ describe('platform/gitlab', () => {
           optimizeForDisabled: false,
         })
       ).rejects.toThrow(REPOSITORY_EMPTY);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should fall back if http_url_to_repo is empty', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            default_branch: 'master',
-            http_url_to_repo: null,
-          },
-        })
-      );
-      await initRepo({ repository: 'some/repo/project', token: 'some-token' });
-      expect(api.get.mock.calls).toMatchSnapshot();
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/user')
+        .reply(200, {})
+        .get('/api/v4/projects/some%2Frepo%2Fproject')
+        .reply(200, {
+          default_branch: 'master',
+          http_url_to_repo: null,
+        });
+      await gitlab.initRepo({
+        repository: 'some/repo/project',
+        localDir: '',
+        optimizeForDisabled: false,
+      });
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('getRepoForceRebase', () => {
     it('should return false', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            default_branch: 'master',
-            http_url_to_repo: null,
-            merge_method: 'merge',
-          },
-        })
+      await initRepo(
+        {
+          repository: 'some/repo/project',
+          localDir: '',
+          optimizeForDisabled: false,
+        },
+        {
+          default_branch: 'master',
+          http_url_to_repo: null,
+          merge_method: 'merge',
+        }
       );
-      await initRepo({ repository: 'some/repo/project', token: 'some-token' });
       expect(await gitlab.getRepoForceRebase()).toBe(false);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
 
     it('should return true', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            default_branch: 'master',
-            http_url_to_repo: null,
-            merge_method: 'ff',
-          },
-        })
+      await initRepo(
+        {
+          repository: 'some/repo/project',
+          localDir: '',
+          optimizeForDisabled: false,
+        },
+        {
+          default_branch: 'master',
+          http_url_to_repo: null,
+          merge_method: 'ff',
+        }
       );
-      await initRepo({ repository: 'some/repo/project', token: 'some-token' });
       expect(await gitlab.getRepoForceRebase()).toBe(true);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('setBaseBranch(branchName)', () => {
     it('sets the base branch', async () => {
-      await initRepo();
+      httpMock
+        .scope(gitlabApiHost)
+        .get(`/api/v4/projects/some%2Frepo`)
+        .reply(200, {
+          default_branch: 'master',
+          http_url_to_repo: `https://gitlab.com/some/repo.git`,
+        })
+        .get('/api/v4/user')
+        .reply(200, {
+          email: 'a@b.com',
+        });
+      await gitlab.initRepo({
+        repository: 'some/repo',
+        localDir: '',
+        optimizeForDisabled: false,
+      });
       await gitlab.setBaseBranch();
-      expect(api.get.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('uses default base branch', async () => {
-      await initRepo();
+      httpMock
+        .scope(gitlabApiHost)
+        .get(`/api/v4/projects/some%2Frepo`)
+        .reply(200, {
+          default_branch: 'master',
+          http_url_to_repo: `https://gitlab.com/some/repo.git`,
+        })
+        .get('/api/v4/user')
+        .reply(200, {
+          email: 'a@b.com',
+        });
+      await gitlab.initRepo({
+        repository: 'some/repo',
+        localDir: '',
+        optimizeForDisabled: false,
+      });
       await gitlab.setBaseBranch();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('getFileList()', () => {
     it('sends to gitFs', async () => {
       await initRepo();
       await gitlab.getFileList();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('branchExists()', () => {
@@ -351,6 +421,7 @@ describe('platform/gitlab', () => {
       it('sends to gitFs', async () => {
         await initRepo();
         await gitlab.branchExists('');
+        expect(httpMock.getTrace()).toMatchSnapshot();
       });
     });
   });
@@ -358,6 +429,7 @@ describe('platform/gitlab', () => {
     it('sends to gitFs', async () => {
       await initRepo();
       await gitlab.getAllRenovateBranches('');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
 
@@ -365,69 +437,66 @@ describe('platform/gitlab', () => {
     it('sends to gitFs', async () => {
       await initRepo();
       await gitlab.getBranchLastCommitTime('');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('isBranchStale()', () => {
     it('sends to gitFs', async () => {
       await initRepo();
       await gitlab.isBranchStale('');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('getBranchPr(branchName)', () => {
     it('should return null if no PR exists', async () => {
-      await initRepo();
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          // branchExists
-          body: [],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/merge_requests?per_page=100&state=opened&source_branch=some-branch'
+        )
+        .reply(200, []);
       const pr = await gitlab.getBranchPr('some-branch');
       expect(pr).toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should return the PR object', async () => {
-      await initRepo();
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              iid: 91,
-              source_branch: 'some-branch',
-              target_branch: 'master',
-              state: 'opened',
-            },
-          ],
-        })
-      );
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/merge_requests?per_page=100&state=opened&source_branch=some-branch'
+        )
+        .reply(200, [
+          {
             iid: 91,
-            state: 'opened',
-            additions: 1,
-            deletions: 1,
-            commits: 1,
             source_branch: 'some-branch',
             target_branch: 'master',
-            base: {
-              sha: '1234',
-            },
+            state: 'opened',
+          },
+        ])
+        .get(
+          '/api/v4/projects/some%2Frepo/merge_requests/91?include_diverged_commits_count=1'
+        )
+        .reply(200, {
+          iid: 91,
+          state: 'opened',
+          additions: 1,
+          deletions: 1,
+          commits: 1,
+          source_branch: 'some-branch',
+          target_branch: 'master',
+          base: {
+            sha: '1234',
           },
         })
-      );
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: [] })
-      );
-      // get branch commit
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: [{ status: 'success' }] })
-      );
-      // get commit statuses
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: 'foo' })
-      );
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, [])
+        .get('/api/v4/projects/some%2Frepo/repository/branches/some-branch')
+        .reply(200, [{ status: 'success' }]);
       const pr = await gitlab.getBranchPr('some-branch');
       expect(pr).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('getBranchStatus(branchName, requiredStatusChecks)', () => {
@@ -440,74 +509,80 @@ describe('platform/gitlab', () => {
       expect(res).toEqual(BranchStatus.red);
     });
     it('returns pending if no results', async () => {
-      await initRepo();
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, []);
       const res = await gitlab.getBranchStatus('somebranch', []);
       expect(res).toEqual(BranchStatus.yellow);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns success if all are success', async () => {
-      await initRepo();
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ status: 'success' }, { status: 'success' }],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, [{ status: 'success' }, { status: 'success' }]);
       const res = await gitlab.getBranchStatus('somebranch', []);
       expect(res).toEqual(BranchStatus.green);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns success if optional jobs fail', async () => {
-      await initRepo();
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            { status: 'success' },
-            { status: 'failed', allow_failure: true },
-          ],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, [
+          { status: 'success' },
+          { status: 'failed', allow_failure: true },
+        ]);
       const res = await gitlab.getBranchStatus('somebranch', []);
       expect(res).toEqual(BranchStatus.green);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns success if all are optional', async () => {
-      await initRepo();
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ status: 'failed', allow_failure: true }],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, [{ status: 'failed', allow_failure: true }]);
       const res = await gitlab.getBranchStatus('somebranch', []);
       expect(res).toEqual(BranchStatus.green);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns failure if any mandatory jobs fails', async () => {
-      await initRepo();
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            { status: 'success' },
-            { status: 'failed', allow_failure: true },
-            { status: 'failed' },
-          ],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, [
+          { status: 'success' },
+          { status: 'failed', allow_failure: true },
+          { status: 'failed' },
+        ]);
       const res = await gitlab.getBranchStatus('somebranch', []);
       expect(res).toEqual(BranchStatus.red);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('maps custom statuses to yellow', async () => {
-      await initRepo();
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ status: 'success' }, { status: 'foo' }],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, [{ status: 'success' }, { status: 'foo' }]);
       const res = await gitlab.getBranchStatus('somebranch', []);
       expect(res).toEqual(BranchStatus.yellow);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('throws repository-changed', async () => {
-      expect.assertions(1);
+      expect.assertions(2);
       GitStorage.mockImplementationOnce(() => ({
         initRepo: jest.fn(),
         branchExists: jest.fn(() => Promise.resolve(false)),
@@ -517,56 +592,72 @@ describe('platform/gitlab', () => {
       await expect(gitlab.getBranchStatus('somebranch', [])).rejects.toThrow(
         REPOSITORY_CHANGED
       );
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('getBranchStatusCheck', () => {
-    beforeEach(() => initRepo());
     it('returns null if no results', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, []);
       const res = await gitlab.getBranchStatusCheck(
         'somebranch',
         'some-context'
       );
       expect(res).toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns null if no matching results', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ name: 'context-1', status: 'pending' }],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, [{ name: 'context-1', status: 'pending' }]);
       const res = await gitlab.getBranchStatusCheck(
         'somebranch',
         'some-context'
       );
       expect(res).toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns status if name found', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            { name: 'context-1', status: 'pending' },
-            { name: 'some-context', status: 'success' },
-            { name: 'context-3', status: 'failed' },
-          ],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, [
+          { name: 'context-1', status: 'pending' },
+          { name: 'some-context', status: 'success' },
+          { name: 'context-3', status: 'failed' },
+        ]);
       const res = await gitlab.getBranchStatusCheck(
         'somebranch',
         'some-context'
       );
       expect(res).toEqual(BranchStatus.green);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('setBranchStatus', () => {
     it.each([BranchStatus.green, BranchStatus.yellow, BranchStatus.red])(
-      'sets branch status yellow',
+      'sets branch status %s',
       async (state) => {
-        await initRepo();
+        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',
@@ -574,7 +665,7 @@ describe('platform/gitlab', () => {
           state,
           url: 'some-url',
         });
-        expect(api.post).toHaveBeenCalledTimes(1);
+        expect(httpMock.getTrace()).toMatchSnapshot();
       }
     );
   });
@@ -582,385 +673,400 @@ describe('platform/gitlab', () => {
     it('sends to gitFs', async () => {
       await initRepo();
       await gitlab.mergeBranch('branch');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('deleteBranch()', () => {
     it('sends to gitFs', async () => {
-      await initRepo();
-
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              number: 1,
-              source_branch: 'branch-a',
-              title: 'branch a pr',
-              state: 'opened',
-            },
-          ],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/merge_requests?per_page=100&state=opened&source_branch=branch'
+        )
+        .reply(200, [
+          {
+            number: 1,
+            source_branch: 'branch-a',
+            title: 'branch a pr',
+            state: 'opened',
+          },
+        ]);
       await gitlab.deleteBranch('branch', true);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('defaults to not closing associated PR', async () => {
       await initRepo();
       await gitlab.deleteBranch('branch2');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('findIssue()', () => {
     it('returns null if no issue', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              iid: 1,
-              title: 'title-1',
-            },
-            {
-              iid: 2,
-              title: 'title-2',
-            },
-          ],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/undefined/issues?state=opened')
+        .reply(200, [
+          {
+            iid: 1,
+            title: 'title-1',
+          },
+          {
+            iid: 2,
+            title: 'title-2',
+          },
+        ]);
       const res = await gitlab.findIssue('title-3');
       expect(res).toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('finds issue', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              iid: 1,
-              title: 'title-1',
-            },
-            {
-              iid: 2,
-              title: 'title-2',
-            },
-          ],
-        })
-      );
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: { description: 'new-content' },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/undefined/issues?state=opened')
+        .reply(200, [
+          {
+            iid: 1,
+            title: 'title-1',
+          },
+          {
+            iid: 2,
+            title: 'title-2',
+          },
+        ])
+        .get('/api/v4/projects/undefined/issues/2')
+        .reply(200, { description: 'new-content' });
       const res = await gitlab.findIssue('title-2');
       expect(res).not.toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('ensureIssue()', () => {
     it('creates issue', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              iid: 1,
-              title: 'title-1',
-            },
-            {
-              iid: 2,
-              title: 'title-2',
-            },
-          ],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/undefined/issues?state=opened')
+        .reply(200, [
+          {
+            iid: 1,
+            title: 'title-1',
+          },
+          {
+            iid: 2,
+            title: 'title-2',
+          },
+        ])
+        .post('/api/v4/projects/undefined/issues')
+        .reply(200);
       const res = await gitlab.ensureIssue({
         title: 'new-title',
         body: 'new-content',
       });
       expect(res).toEqual('created');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('updates issue', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              iid: 1,
-              title: 'title-1',
-            },
-            {
-              iid: 2,
-              title: 'title-2',
-            },
-          ],
-        })
-      );
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: { description: 'new-content' },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/undefined/issues?state=opened')
+        .reply(200, [
+          {
+            iid: 1,
+            title: 'title-1',
+          },
+          {
+            iid: 2,
+            title: 'title-2',
+          },
+        ])
+        .get('/api/v4/projects/undefined/issues/2')
+        .reply(200, { description: 'new-content' })
+        .put('/api/v4/projects/undefined/issues/2')
+        .reply(200);
       const res = await gitlab.ensureIssue({
         title: 'title-2',
         body: 'newer-content',
       });
       expect(res).toEqual('updated');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('skips update if unchanged', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              number: 1,
-              title: 'title-1',
-            },
-            {
-              number: 2,
-              title: 'title-2',
-            },
-          ],
-        })
-      );
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: { description: 'newer-content' },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/undefined/issues?state=opened')
+        .reply(200, [
+          {
+            iid: 1,
+            title: 'title-1',
+          },
+          {
+            iid: 2,
+            title: 'title-2',
+          },
+        ])
+        .get('/api/v4/projects/undefined/issues/2')
+        .reply(200, { description: 'newer-content' });
       const res = await gitlab.ensureIssue({
         title: 'title-2',
         body: 'newer-content',
       });
       expect(res).toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('ensureIssueClosing()', () => {
     it('closes issue', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              number: 1,
-              title: 'title-1',
-            },
-            {
-              number: 2,
-              title: 'title-2',
-            },
-          ],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/undefined/issues?state=opened')
+        .reply(200, [
+          {
+            iid: 1,
+            title: 'title-1',
+          },
+          {
+            iid: 2,
+            title: 'title-2',
+          },
+        ])
+        .put('/api/v4/projects/undefined/issues/2')
+        .reply(200);
       await gitlab.ensureIssueClosing('title-2');
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('addAssignees(issueNo, assignees)', () => {
     it('should add the given assignees to the issue', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ id: 123 }],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/users?username=someuser')
+        .reply(200, [{ id: 123 }])
+        .put('/api/v4/projects/undefined/merge_requests/42?assignee_id=123')
+        .reply(200);
       await gitlab.addAssignees(42, ['someuser']);
-      expect(api.put.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should warn if more than one assignee', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ id: 123 }],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/users?username=someuser')
+        .reply(200, [{ id: 123 }])
+        .get('/api/v4/users?username=someotheruser')
+        .reply(200, [{ id: 124 }])
+        .put('/api/v4/projects/undefined/merge_requests/42?assignee_id=123')
+        .reply(200)
+        .put(
+          '/api/v4/projects/undefined/merge_requests/42?assignee_ids[]=123&assignee_ids[]=124'
+        )
+        .replyWithError('error');
       await gitlab.addAssignees(42, ['someuser', 'someotheruser']);
-      expect(api.put.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should swallow error', async () => {
-      api.get.mockResolvedValueOnce(partial<GotResponse>({}));
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/users?username=someuser')
+        .replyWithError('some error');
       await gitlab.addAssignees(42, ['someuser', 'someotheruser']);
-      expect(api.put).toHaveBeenCalledTimes(0);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('should add the given assignees to the issue if supported', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ id: 123 }],
-        })
-      );
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ id: 124 }],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/users?username=someuser')
+        .reply(200, [{ id: 123 }])
+        .get('/api/v4/users?username=someotheruser')
+        .reply(200, [{ id: 124 }])
+        .put('/api/v4/projects/undefined/merge_requests/42?assignee_id=123')
+        .reply(200)
+        .put(
+          '/api/v4/projects/undefined/merge_requests/42?assignee_ids[]=123&assignee_ids[]=124'
+        )
+        .reply(200);
       await gitlab.addAssignees(42, ['someuser', 'someotheruser']);
-      expect(api.put.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('addReviewers(issueNo, reviewers)', () => {
     it('should add the given reviewers to the PR', async () => {
+      // no-op
+      httpMock.scope(gitlabApiHost);
       await gitlab.addReviewers(42, ['someuser', 'someotheruser']);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('ensureComment', () => {
     it('add comment if not found', async () => {
-      await initRepo({ repository: 'some/repo', token: 'token' });
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: [] })
-      );
+      const scope = await initRepo();
+      scope
+        .get('/api/v4/projects/some%2Frepo/merge_requests/42/notes')
+        .reply(200, [])
+        .post('/api/v4/projects/some%2Frepo/merge_requests/42/notes')
+        .reply(200);
       await gitlab.ensureComment({
         number: 42,
         topic: 'some-subject',
         content: 'some\ncontent',
       });
-      expect(api.post).toHaveBeenCalledTimes(1);
-      expect(api.post.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('add updates comment if necessary', async () => {
-      await initRepo({ repository: 'some/repo', token: 'token' });
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ id: 1234, body: '### some-subject\n\nblablabla' }],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get('/api/v4/projects/some%2Frepo/merge_requests/42/notes')
+        .reply(200, [{ id: 1234, body: '### some-subject\n\nblablabla' }])
+        .put('/api/v4/projects/some%2Frepo/merge_requests/42/notes/1234')
+        .reply(200);
       await gitlab.ensureComment({
         number: 42,
         topic: 'some-subject',
         content: 'some\ncontent',
       });
-      expect(api.post).toHaveBeenCalledTimes(0);
-      expect(api.put).toHaveBeenCalledTimes(1);
-      expect(api.put.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('skips comment', async () => {
-      await initRepo({ repository: 'some/repo', token: 'token' });
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ id: 1234, body: '### some-subject\n\nsome\ncontent' }],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get('/api/v4/projects/some%2Frepo/merge_requests/42/notes')
+        .reply(200, [{ id: 1234, body: '### some-subject\n\nsome\ncontent' }]);
       await gitlab.ensureComment({
         number: 42,
         topic: 'some-subject',
         content: 'some\ncontent',
       });
-      expect(api.post).toHaveBeenCalledTimes(0);
-      expect(api.put).toHaveBeenCalledTimes(0);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('handles comment with no description', async () => {
-      await initRepo({ repository: 'some/repo', token: 'token' });
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ id: 1234, body: '!merge' }],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get('/api/v4/projects/some%2Frepo/merge_requests/42/notes')
+        .reply(200, [{ id: 1234, body: '!merge' }]);
       await gitlab.ensureComment({
         number: 42,
         topic: null,
         content: '!merge',
       });
-      expect(api.post).toHaveBeenCalledTimes(0);
-      expect(api.put).toHaveBeenCalledTimes(0);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('ensureCommentRemoval', () => {
     it('deletes comment by topic if found', async () => {
-      await initRepo({ repository: 'some/repo', token: 'token' });
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ id: 1234, body: '### some-subject\n\nblablabla' }],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get('/api/v4/projects/some%2Frepo/merge_requests/42/notes')
+        .reply(200, [{ id: 1234, body: '### some-subject\n\nblablabla' }])
+        .delete('/api/v4/projects/some%2Frepo/merge_requests/42/notes/1234')
+        .reply(200);
       await gitlab.ensureCommentRemoval({ number: 42, topic: 'some-subject' });
-      expect(api.delete).toHaveBeenCalledTimes(1);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('deletes comment by content if found', async () => {
-      await initRepo({ repository: 'some/repo', token: 'token' });
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [{ id: 1234, body: 'some-body\n' }],
-        })
-      );
+      const scope = await initRepo();
+      scope
+        .get('/api/v4/projects/some%2Frepo/merge_requests/42/notes')
+        .reply(200, [{ id: 1234, body: 'some-body\n' }])
+        .delete('/api/v4/projects/some%2Frepo/merge_requests/42/notes/1234')
+        .reply(200);
       await gitlab.ensureCommentRemoval({ number: 42, content: 'some-body' });
-      expect(api.delete).toHaveBeenCalledTimes(1);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('findPr(branchName, prTitle, state)', () => {
     it('returns true if no title and all state', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              iid: 1,
-              source_branch: 'branch-a',
-              title: 'branch a pr',
-              state: 'opened',
-            },
-          ],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get(
+          '/api/v4/projects/undefined/merge_requests?per_page=100&author_id=undefined'
+        )
+        .reply(200, [
+          {
+            iid: 1,
+            source_branch: 'branch-a',
+            title: 'branch a pr',
+            state: 'opened',
+          },
+        ]);
       const res = await gitlab.findPr({
         branchName: 'branch-a',
       });
       expect(res).toBeDefined();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns true if not open', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              iid: 1,
-              source_branch: 'branch-a',
-              title: 'branch a pr',
-              state: 'merged',
-            },
-          ],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get(
+          '/api/v4/projects/undefined/merge_requests?per_page=100&author_id=undefined'
+        )
+        .reply(200, [
+          {
+            iid: 1,
+            source_branch: 'branch-a',
+            title: 'branch a pr',
+            state: 'merged',
+          },
+        ]);
       const res = await gitlab.findPr({
         branchName: 'branch-a',
         state: PR_STATE_NOT_OPEN,
       });
       expect(res).toBeDefined();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
 
     it('returns true if open and with title', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              iid: 1,
-              source_branch: 'branch-a',
-              title: 'branch a pr',
-              state: 'opened',
-            },
-          ],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get(
+          '/api/v4/projects/undefined/merge_requests?per_page=100&author_id=undefined'
+        )
+        .reply(200, [
+          {
+            iid: 1,
+            source_branch: 'branch-a',
+            title: 'branch a pr',
+            state: 'opened',
+          },
+        ]);
       const res = await gitlab.findPr({
         branchName: 'branch-a',
         prTitle: 'branch a pr',
         state: PR_STATE_OPEN,
       });
       expect(res).toBeDefined();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
 
     it('returns true with title', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: [
-            {
-              iid: 1,
-              source_branch: 'branch-a',
-              title: 'branch a pr',
-              state: 'opened',
-            },
-          ],
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get(
+          '/api/v4/projects/undefined/merge_requests?per_page=100&author_id=undefined'
+        )
+        .reply(200, [
+          {
+            iid: 1,
+            source_branch: 'branch-a',
+            title: 'branch a pr',
+            state: 'opened',
+          },
+        ]);
       const res = await gitlab.findPr({
         branchName: 'branch-a',
         prTitle: 'branch a pr',
       });
       expect(res).toBeDefined();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('createPr(branchName, title, body)', () => {
     it('returns the PR', async () => {
-      api.post.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            id: 1,
-            iid: 12345,
-          },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .post('/api/v4/projects/undefined/merge_requests')
+        .reply(200, {
+          id: 1,
+          iid: 12345,
+        });
       const pr = await gitlab.createPr({
         branchName: 'some-branch',
         prTitle: 'some-title',
@@ -968,17 +1074,16 @@ describe('platform/gitlab', () => {
         labels: null,
       });
       expect(pr).toMatchSnapshot();
-      expect(api.post.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('uses default branch', async () => {
-      api.post.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            id: 1,
-            iid: 12345,
-          },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .post('/api/v4/projects/undefined/merge_requests')
+        .reply(200, {
+          id: 1,
+          iid: 12345,
+        });
       const pr = await gitlab.createPr({
         branchName: 'some-branch',
         prTitle: 'some-title',
@@ -987,17 +1092,18 @@ describe('platform/gitlab', () => {
         useDefaultBranch: true,
       });
       expect(pr).toMatchSnapshot();
-      expect(api.post.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('auto-accepts the MR when requested', async () => {
-      api.post.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            id: 1,
-            iid: 12345,
-          },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .post('/api/v4/projects/undefined/merge_requests')
+        .reply(200, {
+          id: 1,
+          iid: 12345,
+        })
+        .put('/api/v4/projects/undefined/merge_requests/12345/merge')
+        .reply(200);
       await gitlab.createPr({
         branchName: 'some-branch',
         prTitle: 'some-title',
@@ -1010,80 +1116,78 @@ describe('platform/gitlab', () => {
           gitLabAutomerge: true,
         },
       });
-      // expect(api.post.mock.calls).toMatchSnapshot();
-      expect(api.put.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('getPr(prNo)', () => {
     it('returns the PR', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            id: 1,
-            iid: 12345,
-            description: 'a merge request',
-            state: 'merged',
-            merge_status: 'cannot_be_merged',
-            diverged_commits_count: 5,
-            source_branch: 'some-branch',
-            target_branch: 'master',
-          },
-        })
-      );
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            commit: {},
-          },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get(
+          '/api/v4/projects/undefined/merge_requests/12345?include_diverged_commits_count=1'
+        )
+        .reply(200, {
+          id: 1,
+          iid: 12345,
+          description: 'a merge request',
+          state: 'merged',
+          merge_status: 'cannot_be_merged',
+          diverged_commits_count: 5,
+          source_branch: 'some-branch',
+          target_branch: 'master',
+        })
+        .get('/api/v4/projects/undefined/repository/branches/some-branch')
+        .reply(200, { commit: {} });
       const pr = await gitlab.getPr(12345);
       expect(pr).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns the mergeable PR', async () => {
-      await initRepo();
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            id: 1,
-            iid: 12345,
-            description: 'a merge request',
-            state: 'open',
-            diverged_commits_count: 5,
-            source_branch: 'some-branch',
-            target_branch: 'master',
-          },
-        })
-      );
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: [{ status: 'success' }] })
-      ); // get commit statuses
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({ body: { commit: null } })
-      ); // check last commit author
+      const scope = await initRepo();
+      scope
+        .get(
+          '/api/v4/projects/some%2Frepo/merge_requests/12345?include_diverged_commits_count=1'
+        )
+        .reply(200, {
+          id: 1,
+          iid: 12345,
+          description: 'a merge request',
+          state: 'open',
+          diverged_commits_count: 5,
+          source_branch: 'some-branch',
+          target_branch: 'master',
+        })
+        .get(
+          '/api/v4/projects/some%2Frepo/repository/commits/0d9c7726c3d628b7e28af234595cfd20febdbf8e/statuses'
+        )
+        .reply(200, [{ status: 'success' }])
+        .get('/api/v4/projects/some%2Frepo/repository/branches/some-branch')
+        .reply(200, { commit: null });
       const pr = await gitlab.getPr(12345);
       expect(pr).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
     it('returns the PR with nonexisting branch', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            id: 1,
-            iid: 12345,
-            description: 'a merge request',
-            state: 'open',
-            merge_status: 'cannot_be_merged',
-            diverged_commits_count: 2,
-            source_branch: 'some-branch',
-            target_branch: 'master',
-          },
-        })
-      );
-      api.get.mockRejectedValueOnce({
-        statusCode: 404,
-      });
+      httpMock
+        .scope(gitlabApiHost)
+        .get(
+          '/api/v4/projects/undefined/merge_requests/12345?include_diverged_commits_count=1'
+        )
+        .reply(200, {
+          id: 1,
+          iid: 12345,
+          description: 'a merge request',
+          state: 'open',
+          merge_status: 'cannot_be_merged',
+          diverged_commits_count: 2,
+          source_branch: 'some-branch',
+          target_branch: 'master',
+        })
+        .get('/api/v4/projects/undefined/repository/branches/some-branch')
+        .reply(404);
       const pr = await gitlab.getPr(12345);
       expect(pr).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('getPrFiles()', () => {
@@ -1092,33 +1196,41 @@ describe('platform/gitlab', () => {
       expect(prFiles).toEqual([]);
     });
     it('returns files', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            changes: [
-              { new_path: 'renovate.json' },
-              { new_path: 'not renovate.json' },
-            ],
-          },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get('/api/v4/projects/undefined/merge_requests/123/changes')
+        .reply(200, {
+          changes: [
+            { new_path: 'renovate.json' },
+            { new_path: 'not renovate.json' },
+          ],
+        });
       const prFiles = await gitlab.getPrFiles(123);
       expect(prFiles).toMatchSnapshot();
       expect(prFiles).toHaveLength(2);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('updatePr(prNo, title, body)', () => {
     jest.resetAllMocks();
     it('updates the PR', async () => {
+      httpMock
+        .scope(gitlabApiHost)
+        .put('/api/v4/projects/undefined/merge_requests/1')
+        .reply(200);
       await gitlab.updatePr(1, 'title', 'body');
-      expect(api.put.mock.calls.length).toEqual(1);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('mergePr(pr)', () => {
     jest.resetAllMocks();
     it('merges the PR', async () => {
+      httpMock
+        .scope(gitlabApiHost)
+        .put('/api/v4/projects/undefined/merge_requests/1/merge')
+        .reply(200);
       await gitlab.mergePr(1, undefined);
-      expect(api.put.mock.calls.length).toEqual(1);
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   const prBody = `https://github.com/foo/bar/issues/5 plus also [a link](https://github.com/foo/bar/issues/5
@@ -1151,7 +1263,7 @@ These updates have all been created already. Click a checkbox below to force a r
         files: [{ name: 'SomeFile', contents: 'Some Content' }],
         message: '',
       });
-      expect(api.get.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
   describe('getCommitMessages()', () => {
@@ -1168,29 +1280,29 @@ These updates have all been created already. Click a checkbox below to force a r
   });
   describe('deleteLabel(issueNo, label)', () => {
     it('should delete the label', async () => {
-      api.get.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            id: 1,
-            iid: 12345,
-            description: 'a merge request',
-            state: 'merged',
-            merge_status: 'cannot_be_merged',
-            diverged_commits_count: 5,
-            source_branch: 'some-branch',
-            labels: ['foo', 'renovate', 'rebase'],
-          },
-        })
-      );
-      api.put.mockResolvedValueOnce(
-        partial<GotResponse>({
-          body: {
-            commit: {},
-          },
-        })
-      );
+      httpMock
+        .scope(gitlabApiHost)
+        .get(
+          '/api/v4/projects/undefined/merge_requests/42?include_diverged_commits_count=1'
+        )
+        .reply(200, {
+          id: 1,
+          iid: 12345,
+          description: 'a merge request',
+          state: 'merged',
+          merge_status: 'cannot_be_merged',
+          diverged_commits_count: 5,
+          source_branch: 'some-branch',
+          labels: ['foo', 'renovate', 'rebase'],
+        })
+        .get('/api/v4/projects/undefined/repository/branches/some-branch')
+        .reply(200, {
+          commit: {},
+        })
+        .put('/api/v4/projects/undefined/merge_requests/42')
+        .reply(200);
       await gitlab.deleteLabel(42, 'rebase');
-      expect(api.put.mock.calls).toMatchSnapshot();
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
 });
-- 
GitLab