diff --git a/.eslintrc.js b/.eslintrc.js
index 8bfe82c0ddfb20218fdda96fe4e399d9e22304a6..8e2b877031139d09d9e9dd16a59b05e5220ecb13 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -32,6 +32,13 @@ module.exports = {
     'promise/no-promise-in-callback': 'warn',
     'promise/no-callback-in-promise': 'warn',
     'promise/avoid-new': 'warn',
+
+    '@typescript-eslint/explicit-member-accessibility': 0,
+    '@typescript-eslint/explicit-function-return-type': 0,
+    '@typescript-eslint/interface-name-prefix': 0,
+    '@typescript-eslint/no-explicit-any': 0,
+    '@typescript-eslint/no-non-null-assertion': 0,
+    'no-underscore-dangle': 0,
   },
   settings: {
     'import/resolver': {
diff --git a/lib/platform/bitbucket-server/bb-got-wrapper.js b/lib/platform/bitbucket-server/bb-got-wrapper.ts
similarity index 56%
rename from lib/platform/bitbucket-server/bb-got-wrapper.js
rename to lib/platform/bitbucket-server/bb-got-wrapper.ts
index f4b9bd44e748734f5f87c221c700848ed9c3ac8e..066de5393cbeb7f6bfdd2089167aaf4e1a03facd 100644
--- a/lib/platform/bitbucket-server/bb-got-wrapper.js
+++ b/lib/platform/bitbucket-server/bb-got-wrapper.ts
@@ -1,15 +1,18 @@
-const got = require('got');
-const URL = require('url');
-const hostRules = require('../../util/host-rules');
+import got from 'got';
+import URL from 'url';
+import * as hostRules from '../../util/host-rules';
+import { IGotApiOptions, IGotApi } from '../common';
 
-let cache = {};
+let cache: Renovate.IDict<got.Response<any>> = {};
 
 const platform = 'bitbucket-server';
-let endpoint;
+let endpoint: string;
 
-async function get(path, options) {
+async function get(path: string, options: IGotApiOptions & got.GotJSONOptions) {
   const host = URL.parse(path).host || URL.parse(endpoint).host;
-  const opts = {
+  const opts: IGotApiOptions &
+    hostRules.IPlatformConfig &
+    got.GotJSONOptions = {
     // TODO: Move to configurable host rules, or use utils/got
     timeout: 60 * 1000,
     json: true,
@@ -18,7 +21,9 @@ async function get(path, options) {
     ...options,
   };
   const url = URL.resolve(endpoint, path);
-  const method = (opts.method || 'get').toLowerCase();
+  const method = (
+    opts.method || /* istanbul ignore next */ 'get'
+  ).toLowerCase();
   const useCache = opts.useCache;
   if (method === 'get' && useCache !== false && cache[path]) {
     logger.trace({ path }, 'Returning cached result');
@@ -27,7 +32,10 @@ async function get(path, options) {
   opts.headers = {
     'user-agent': 'https://github.com/renovatebot/renovate',
     'X-Atlassian-Token': 'no-check',
-    authorization: opts.token ? `Basic ${opts.token}` : undefined,
+
+    authorization: opts.token
+      ? /* istanbul ignore next */ `Basic ${opts.token}`
+      : undefined,
     ...opts.headers,
   };
 
@@ -41,17 +49,19 @@ async function get(path, options) {
 
 const helpers = ['get', 'post', 'put', 'patch', 'head', 'delete'];
 
+export const api: IGotApi = {} as any;
+
 for (const x of helpers) {
-  get[x] = (url, opts) =>
+  (api as any)[x] = (url: string, opts: any) =>
     get(url, Object.assign({}, opts, { method: x.toUpperCase() }));
 }
 
-get.reset = function reset() {
+api.reset = function reset() {
   cache = {};
 };
 
-get.setEndpoint = e => {
+api.setEndpoint = (e: string) => {
   endpoint = e;
 };
 
-module.exports = get;
+export default api;
diff --git a/lib/platform/bitbucket-server/index.js b/lib/platform/bitbucket-server/index.ts
similarity index 79%
rename from lib/platform/bitbucket-server/index.js
rename to lib/platform/bitbucket-server/index.ts
index a159d51a347a5c354768a288d2cb2737a97be023..8adea7fc0cf5f375550268ed0fa51878139dd288 100644
--- a/lib/platform/bitbucket-server/index.js
+++ b/lib/platform/bitbucket-server/index.ts
@@ -1,71 +1,42 @@
-const url = require('url');
-const delay = require('delay');
+import url from 'url';
+import delay from 'delay';
 
-const api = require('./bb-got-wrapper');
-const utils = require('./utils');
-const hostRules = require('../../util/host-rules');
-const GitStorage = require('../git/storage');
+import api from './bb-got-wrapper';
+import * as utils from './utils';
+import * as hostRules from '../../util/host-rules';
+import GitStorage from '../git/storage';
 
 const platform = 'bitbucket-server';
 
-let config = {};
+interface BbsConfig {
+  baseBranch: string;
+  bbUseDefaultReviewers: boolean;
+  defaultBranch: string;
+  fileList: any[];
+  mergeMethod: string;
+  owner: string;
+  prList: any[];
+  projectKey: string;
+  repository: string;
+  repositorySlug: string;
+  storage: GitStorage;
+}
 
-const defaults = {
-  platform: 'bitbucket-server',
-};
+let config: BbsConfig = {} as any;
 
-module.exports = {
-  initPlatform,
-  getRepos,
-  cleanRepo,
-  initRepo,
-  getRepoStatus,
-  getRepoForceRebase,
-  setBaseBranch,
-  setBranchPrefix,
-  // Search
-  getFileList,
-  // Branch
-  branchExists,
-  getAllRenovateBranches,
-  isBranchStale,
-  getBranchPr,
-  getBranchStatus,
-  getBranchStatusCheck,
-  setBranchStatus,
-  deleteBranch,
-  mergeBranch,
-  getBranchLastCommitTime,
-  // issue
-  findIssue,
-  ensureIssue,
-  ensureIssueClosing,
-  addAssignees,
-  addReviewers,
-  deleteLabel,
-  getIssueList,
-  // Comments
-  ensureComment,
-  ensureCommentRemoval,
-  // PR
-  getPrList,
-  findPr,
-  createPr,
-  getPr,
-  getPrFiles,
-  updatePr,
-  mergePr,
-  getPrBody,
-  // file
-  commitFilesToBranch,
-  getFile,
-  // commits
-  getCommitMessages,
-  // vulnerability alerts
-  getVulnerabilityAlerts,
+const defaults: any = {
+  platform: 'bitbucket-server',
 };
 
-function initPlatform({ endpoint, username, password }) {
+export function initPlatform({
+  endpoint,
+  username,
+  password,
+}: {
+  endpoint: string;
+  username: string;
+  password: string;
+}) {
   if (!endpoint) {
     throw new Error('Init: You must configure a Bitbucket Server endpoint');
   }
@@ -84,13 +55,16 @@ function initPlatform({ endpoint, username, password }) {
 }
 
 // Get all repositories that the user has access to
-async function getRepos() {
+export async function getRepos() {
   logger.info('Autodiscovering Bitbucket Server repositories');
   try {
     const repos = await utils.accumulateValues(
       `./rest/api/1.0/repos?permission=REPO_WRITE&state=AVAILABLE`
     );
-    const result = repos.map(r => `${r.project.key.toLowerCase()}/${r.slug}`);
+    const result = repos.map(
+      (r: { project: { key: string }; slug: string }) =>
+        `${r.project.key.toLowerCase()}/${r.slug}`
+    );
     logger.debug({ result }, 'result of getRepos()');
     return result;
   } catch (err) /* istanbul ignore next */ {
@@ -99,23 +73,30 @@ async function getRepos() {
   }
 }
 
-function cleanRepo() {
+export function cleanRepo() {
   logger.debug(`cleanRepo()`);
   if (config.storage) {
     config.storage.cleanRepo();
   }
   api.reset();
-  config = {};
+  config = {} as any;
 }
 
 // Initialize GitLab by getting base branch
-async function initRepo({
+export async function initRepo({
   repository,
   endpoint,
   gitPrivateKey,
   gitFs,
   localDir,
   bbUseDefaultReviewers,
+}: {
+  repository: string;
+  endpoint: string;
+  gitPrivateKey?: string;
+  gitFs?: string;
+  localDir: string;
+  bbUseDefaultReviewers?: boolean;
 }) {
   logger.debug(
     `initRepo("${JSON.stringify(
@@ -128,7 +109,7 @@ async function initRepo({
   api.reset();
 
   const [projectKey, repositorySlug] = repository.split('/');
-  config = { projectKey, repositorySlug, gitPrivateKey };
+  config = { projectKey, repositorySlug, gitPrivateKey, repository } as any;
 
   /* istanbul ignore else */
   if (bbUseDefaultReviewers !== false) {
@@ -137,11 +118,13 @@ async function initRepo({
   }
 
   // Always gitFs
-  const { host, pathname } = url.parse(opts.endpoint);
+  const { host, pathname } = url.parse(opts!.endpoint!);
   const gitUrl = GitStorage.getUrl({
-    gitFs: opts.endpoint.split(':')[0],
-    auth: `${opts.username}:${opts.password}`,
-    host: `${host}${pathname}${pathname.endsWith('/') ? '' : '/'}scm`,
+    gitFs: opts!.endpoint!.split(':')[0] as any,
+    auth: `${opts!.username}:${opts!.password}`,
+    host: `${host}${pathname}${
+      pathname!.endsWith('/') ? '' : /* istanbul ignore next */ '/'
+    }scm`,
     repository,
   });
 
@@ -152,7 +135,7 @@ async function initRepo({
     url: gitUrl,
   });
 
-  const platformConfig = {};
+  const platformConfig: any = {};
 
   try {
     const info = (await api.get(
@@ -189,7 +172,7 @@ async function initRepo({
   return platformConfig;
 }
 
-function getRepoForceRebase() {
+export function getRepoForceRebase() {
   logger.debug(`getRepoForceRebase()`);
   // TODO if applicable
   // This function should return true only if the user has enabled a setting on the repo that enforces PRs to be kept up to date with master
@@ -198,20 +181,20 @@ function getRepoForceRebase() {
   return false;
 }
 
-async function setBaseBranch(branchName = config.defaultBranch) {
+export async function setBaseBranch(branchName: string = config.defaultBranch) {
   config.baseBranch = branchName;
   await config.storage.setBaseBranch(branchName);
 }
 
 // istanbul ignore next
-function setBranchPrefix(branchPrefix) {
+export function setBranchPrefix(branchPrefix: string) {
   return config.storage.setBranchPrefix(branchPrefix);
 }
 
 // Search
 
 // Get full file list
-function getFileList(branchName = config.baseBranch) {
+export function getFileList(branchName: string = config.baseBranch) {
   logger.debug(`getFileList(${branchName})`);
   return config.storage.getFileList(branchName);
 }
@@ -219,33 +202,33 @@ function getFileList(branchName = config.baseBranch) {
 // Branch
 
 // Returns true if branch exists, otherwise false
-function branchExists(branchName) {
+export function branchExists(branchName: string) {
   logger.debug(`branchExists(${branchName})`);
   return config.storage.branchExists(branchName);
 }
 
 // Returns the Pull Request for a branch. Null if not exists.
-async function getBranchPr(branchName, refreshCache) {
+export async function getBranchPr(branchName: string, refreshCache?: boolean) {
   logger.debug(`getBranchPr(${branchName})`);
-  const existingPr = await findPr(branchName, null, 'open');
+  const existingPr = await findPr(branchName, undefined, 'open');
   return existingPr ? getPr(existingPr.number, refreshCache) : null;
 }
 
-function getAllRenovateBranches(branchPrefix) {
+export function getAllRenovateBranches(branchPrefix: string) {
   logger.debug('getAllRenovateBranches');
   return config.storage.getAllRenovateBranches(branchPrefix);
 }
 
-function isBranchStale(branchName) {
+export function isBranchStale(branchName: string) {
   logger.debug(`isBranchStale(${branchName})`);
   return config.storage.isBranchStale(branchName);
 }
 
-async function commitFilesToBranch(
-  branchName,
-  files,
-  message,
-  parentBranch = config.baseBranch
+export async function commitFilesToBranch(
+  branchName: string,
+  files: any[],
+  message: string,
+  parentBranch: string = config.baseBranch
 ) {
   logger.debug(
     `commitFilesToBranch(${JSON.stringify(
@@ -267,12 +250,12 @@ async function commitFilesToBranch(
   await getBranchPr(branchName, true);
 }
 
-function getFile(filePath, branchName) {
+export function getFile(filePath: string, branchName: string) {
   logger.debug(`getFile(${filePath}, ${branchName})`);
   return config.storage.getFile(filePath, branchName);
 }
 
-async function deleteBranch(branchName, closePr = false) {
+export async function deleteBranch(branchName: string, closePr = false) {
   logger.debug(`deleteBranch(${branchName}, closePr=${closePr})`);
   // TODO: coverage
   // istanbul ignore next
@@ -292,25 +275,28 @@ async function deleteBranch(branchName, closePr = false) {
   return config.storage.deleteBranch(branchName);
 }
 
-function mergeBranch(branchName) {
+export function mergeBranch(branchName: string) {
   logger.debug(`mergeBranch(${branchName})`);
   return config.storage.mergeBranch(branchName);
 }
 
-function getBranchLastCommitTime(branchName) {
+export function getBranchLastCommitTime(branchName: string) {
   logger.debug(`getBranchLastCommitTime(${branchName})`);
   return config.storage.getBranchLastCommitTime(branchName);
 }
 
 // istanbul ignore next
-function getRepoStatus() {
+export function getRepoStatus() {
   return config.storage.getRepoStatus();
 }
 
 // Returns the combined status for a branch.
 // umbrella for status checks
 // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-build-rest.html#idp2
-async function getBranchStatus(branchName, requiredStatusChecks) {
+export async function getBranchStatus(
+  branchName: string,
+  requiredStatusChecks?: string[] | boolean | null
+) {
   logger.debug(
     `getBranchStatus(${branchName}, requiredStatusChecks=${!!requiredStatusChecks})`
   );
@@ -344,7 +330,10 @@ async function getBranchStatus(branchName, requiredStatusChecks) {
 }
 
 // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-build-rest.html#idp2
-async function getBranchStatusCheck(branchName, context) {
+export async function getBranchStatusCheck(
+  branchName: string,
+  context: string
+) {
   logger.debug(`getBranchStatusCheck(${branchName}, context=${context})`);
 
   const branchCommit = await config.storage.getBranchCommit(branchName);
@@ -373,12 +362,12 @@ async function getBranchStatusCheck(branchName, context) {
   return null;
 }
 
-async function setBranchStatus(
-  branchName,
-  context,
-  description,
-  state,
-  targetUrl
+export async function setBranchStatus(
+  branchName: string,
+  context: string,
+  description: string,
+  state: string | null,
+  targetUrl?: string
 ) {
   logger.debug(`setBranchStatus(${branchName})`);
 
@@ -391,7 +380,7 @@ async function setBranchStatus(
   const branchCommit = await config.storage.getBranchCommit(branchName);
 
   try {
-    const body = {
+    const body: any = {
       key: context,
       description,
       url: targetUrl || 'https://renovatebot.com',
@@ -427,7 +416,7 @@ async function setBranchStatus(
 // }
 
 // istanbul ignore next
-function findIssue(title) {
+export function findIssue(title: string) {
   logger.debug(`findIssue(${title})`);
   // TODO: Needs implementation
   // This is used by Renovate when creating its own issues, e.g. for deprecated package warnings, config error notifications, or "masterIssue"
@@ -436,7 +425,7 @@ function findIssue(title) {
 }
 
 // istanbul ignore next
-function ensureIssue(title, body) {
+export function ensureIssue(title: string, body: string) {
   logger.debug(`ensureIssue(${title}, body={${body}})`);
   // TODO: Needs implementation
   // This is used by Renovate when creating its own issues, e.g. for deprecated package warnings, config error notifications, or "masterIssue"
@@ -445,14 +434,14 @@ function ensureIssue(title, body) {
 }
 
 // istanbul ignore next
-function getIssueList() {
+export function getIssueList() {
   logger.debug(`getIssueList()`);
   // TODO: Needs implementation
   return [];
 }
 
 // istanbul ignore next
-function ensureIssueClosing(title) {
+export function ensureIssueClosing(title: string) {
   logger.debug(`ensureIssueClosing(${title})`);
   // TODO: Needs implementation
   // This is used by Renovate when creating its own issues, e.g. for deprecated package warnings, config error notifications, or "masterIssue"
@@ -460,14 +449,14 @@ function ensureIssueClosing(title) {
 }
 
 // eslint-disable-next-line no-unused-vars
-function addAssignees(iid, assignees) {
+export function addAssignees(iid: number, assignees: string[]) {
   logger.debug(`addAssignees(${iid}, ${assignees})`);
   // TODO: Needs implementation
   // Currently Renovate does "Create PR" and then "Add assignee" as a two-step process, with this being the second step.
   // BB Server doesnt support assignees
 }
 
-async function addReviewers(prNo, reviewers) {
+export async function addReviewers(prNo: number, reviewers: string[]) {
   logger.debug(`Adding reviewers ${reviewers} to #${prNo}`);
 
   try {
@@ -505,13 +494,13 @@ async function addReviewers(prNo, reviewers) {
 }
 
 // eslint-disable-next-line no-unused-vars
-function deleteLabel(issueNo, label) {
+export function deleteLabel(issueNo: number, label: string) {
   logger.debug(`deleteLabel(${issueNo}, ${label})`);
   // TODO: Needs implementation
   // Only used for the "request Renovate to rebase a PR using a label" feature
 }
 
-async function getComments(prNo) {
+async function getComments(prNo: number) {
   // GET /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/activities
   let comments = await utils.accumulateValues(
     `./rest/api/1.0/projects/${config.projectKey}/repos/${
@@ -520,15 +509,18 @@ async function getComments(prNo) {
   );
 
   comments = comments
-    .filter(a => a.action === 'COMMENTED' && a.commentAction === 'ADDED')
-    .map(a => a.comment);
+    .filter(
+      (a: { action: string; commentAction: string }) =>
+        a.action === 'COMMENTED' && a.commentAction === 'ADDED'
+    )
+    .map((a: { comment: string }) => a.comment);
 
   logger.debug(`Found ${comments.length} comments`);
 
   return comments;
 }
 
-async function addComment(prNo, text) {
+async function addComment(prNo: number, text: string) {
   // POST /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments
   await api.post(
     `./rest/api/1.0/projects/${config.projectKey}/repos/${
@@ -540,7 +532,7 @@ async function addComment(prNo, text) {
   );
 }
 
-async function getCommentVersion(prNo, commentId) {
+async function getCommentVersion(prNo: number, commentId: number) {
   // GET /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
   const { version } = (await api.get(
     `./rest/api/1.0/projects/${config.projectKey}/repos/${
@@ -551,7 +543,7 @@ async function getCommentVersion(prNo, commentId) {
   return version;
 }
 
-async function editComment(prNo, commentId, text) {
+async function editComment(prNo: number, commentId: number, text: string) {
   const version = await getCommentVersion(prNo, commentId);
 
   // PUT /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
@@ -565,7 +557,7 @@ async function editComment(prNo, commentId, text) {
   );
 }
 
-async function deleteComment(prNo, commentId) {
+async function deleteComment(prNo: number, commentId: number) {
   const version = await getCommentVersion(prNo, commentId);
 
   // DELETE /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId}
@@ -576,16 +568,20 @@ async function deleteComment(prNo, commentId) {
   );
 }
 
-async function ensureComment(prNo, topic, content) {
+export async function ensureComment(
+  prNo: number,
+  topic: string | null,
+  content: string
+) {
   try {
     const comments = await getComments(prNo);
-    let body;
-    let commentId;
-    let commentNeedsUpdating;
+    let body: string;
+    let commentId: number | undefined;
+    let commentNeedsUpdating: boolean | undefined;
     if (topic) {
       logger.debug(`Ensuring comment "${topic}" in #${prNo}`);
       body = `### ${topic}\n\n${content}`;
-      comments.forEach(comment => {
+      comments.forEach((comment: { text: string; id: number }) => {
         if (comment.text.startsWith(`### ${topic}\n\n`)) {
           commentId = comment.id;
           commentNeedsUpdating = comment.text !== body;
@@ -594,7 +590,7 @@ async function ensureComment(prNo, topic, content) {
     } else {
       logger.debug(`Ensuring content-only comment in #${prNo}`);
       body = `${content}`;
-      comments.forEach(comment => {
+      comments.forEach((comment: { text: string; id: number }) => {
         if (comment.text === body) {
           commentId = comment.id;
           commentNeedsUpdating = false;
@@ -617,13 +613,12 @@ async function ensureComment(prNo, topic, content) {
   }
 }
 
-// eslint-disable-next-line no-unused-vars
-async function ensureCommentRemoval(prNo, topic) {
+export async function ensureCommentRemoval(prNo: number, topic: string) {
   try {
     logger.debug(`Ensuring comment "${topic}" in #${prNo} is removed`);
     const comments = await getComments(prNo);
     let commentId;
-    comments.forEach(comment => {
+    comments.forEach((comment: { text: string; id: any }) => {
       if (comment.text.startsWith(`### ${topic}\n\n`)) {
         commentId = comment.id;
       }
@@ -638,7 +633,8 @@ async function ensureCommentRemoval(prNo, topic) {
 
 // TODO: coverage
 // istanbul ignore next
-async function getPrList() {
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export async function getPrList(_args?: any) {
   logger.debug(`getPrList()`);
   if (!config.prList) {
     const values = await utils.accumulateValues(
@@ -657,7 +653,7 @@ async function getPrList() {
 
 // TODO: coverage
 // istanbul ignore next
-function matchesState(state, desiredState) {
+function matchesState(state: string, desiredState: string) {
   if (desiredState === 'all') {
     return true;
   }
@@ -669,14 +665,23 @@ function matchesState(state, desiredState) {
 
 // TODO: coverage
 // istanbul ignore next
-const isRelevantPr = (branchName, prTitle, state) => p =>
+const isRelevantPr = (
+  branchName: string,
+  prTitle: string | null | undefined,
+  state: string
+) => (p: { branchName: string; title: string; state: string }) =>
   p.branchName === branchName &&
   (!prTitle || p.title === prTitle) &&
   matchesState(p.state, state);
 
 // TODO: coverage
 // istanbul ignore next
-async function findPr(branchName, prTitle, state = 'all', refreshCache) {
+export async function findPr(
+  branchName: string,
+  prTitle?: string,
+  state = 'all',
+  refreshCache?: boolean
+) {
   logger.debug(`findPr(${branchName}, "${prTitle}", "${state}")`);
   const prList = await getPrList({ refreshCache });
   const pr = prList.find(isRelevantPr(branchName, prTitle, state));
@@ -690,12 +695,12 @@ async function findPr(branchName, prTitle, state = 'all', refreshCache) {
 
 // Pull Request
 
-async function createPr(
-  branchName,
-  title,
-  description,
-  labels,
-  useDefaultBranch
+export async function createPr(
+  branchName: string,
+  title: string,
+  description: string,
+  _labels?: string[] | null,
+  useDefaultBranch?: boolean
 ) {
   logger.debug(`createPr(${branchName}, title=${title})`);
   const base = useDefaultBranch ? config.defaultBranch : config.baseBranch;
@@ -716,7 +721,9 @@ async function createPr(
       }/reviewers?sourceRefId=refs/heads/${branchName}&targetRefId=refs/heads/${base}&sourceRepoId=${id}&targetRepoId=${id}`
     )).body;
 
-    reviewers = defReviewers.map(u => ({ user: { name: u.name } }));
+    reviewers = defReviewers.map((u: { name: string }) => ({
+      user: { name: u.name },
+    }));
   }
 
   const body = {
@@ -770,7 +777,7 @@ async function createPr(
 }
 
 // Gets details for a PR
-async function getPr(prNo, refreshCache) {
+export async function getPr(prNo: number, refreshCache?: boolean) {
   logger.debug(`getPr(${prNo})`);
   if (!prNo) {
     return null;
@@ -783,10 +790,12 @@ async function getPr(prNo, refreshCache) {
     { useCache: !refreshCache }
   );
 
-  const pr = {
+  const pr: any = {
     displayNumber: `Pull Request #${res.body.id}`,
     ...utils.prInfo(res.body),
-    reviewers: res.body.reviewers.map(r => r.user.name),
+    reviewers: res.body.reviewers.map(
+      (r: { user: { name: any } }) => r.user.name
+    ),
   };
 
   if (pr.state === 'open') {
@@ -845,7 +854,7 @@ async function getPr(prNo, refreshCache) {
 
 // Return a list of all modified files in a PR
 // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html
-async function getPrFiles(prNo) {
+export async function getPrFiles(prNo: number) {
   logger.debug(`getPrFiles(${prNo})`);
   if (!prNo) {
     return [];
@@ -857,10 +866,14 @@ async function getPrFiles(prNo) {
       config.repositorySlug
     }/pull-requests/${prNo}/changes?withComments=false`
   );
-  return values.map(f => f.path.toString);
+  return values.map((f: { path: string }) => f.path.toString);
 }
 
-async function updatePr(prNo, title, description) {
+export async function updatePr(
+  prNo: number,
+  title: string,
+  description: string
+) {
   logger.debug(`updatePr(${prNo}, title=${title})`);
 
   try {
@@ -878,7 +891,7 @@ async function updatePr(prNo, title, description) {
           title,
           description,
           version: pr.version,
-          reviewers: pr.reviewers.map(name => ({ user: { name } })),
+          reviewers: pr.reviewers.map((name: string) => ({ user: { name } })),
         },
       }
     );
@@ -896,7 +909,7 @@ async function updatePr(prNo, title, description) {
 }
 
 // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html#idp261
-async function mergePr(prNo, branchName) {
+export async function mergePr(prNo: number, branchName: string) {
   logger.debug(`mergePr(${prNo}, ${branchName})`);
   // Used for "automerge" feature
   try {
@@ -927,8 +940,8 @@ async function mergePr(prNo, branchName) {
   return true;
 }
 
-function getPrBody(input) {
-  logger.debug(`getPrBody(${(input || '').split('\n')[0]})`);
+export function getPrBody(input: string) {
+  logger.debug(`getPrBody(${input.split('\n')[0]})`);
   // Remove any HTML we use
   return input
     .replace(/<\/?summary>/g, '**')
@@ -937,12 +950,12 @@ function getPrBody(input) {
     .substring(0, 30000);
 }
 
-function getCommitMessages() {
+export function getCommitMessages() {
   logger.debug(`getCommitMessages()`);
   return config.storage.getCommitMessages();
 }
 
-function getVulnerabilityAlerts() {
+export function getVulnerabilityAlerts() {
   logger.debug(`getVulnerabilityAlerts()`);
   return [];
 }
diff --git a/lib/platform/bitbucket-server/utils.js b/lib/platform/bitbucket-server/utils.ts
similarity index 60%
rename from lib/platform/bitbucket-server/utils.js
rename to lib/platform/bitbucket-server/utils.ts
index 44423b33d7998668e6323c2fbe2d69ff0bc4a26d..dc6eab449a1105ef4d012eee0b7338bb65d2ceb6 100644
--- a/lib/platform/bitbucket-server/utils.js
+++ b/lib/platform/bitbucket-server/utils.ts
@@ -1,26 +1,28 @@
 // SEE for the reference https://github.com/renovatebot/renovate/blob/c3e9e572b225085448d94aa121c7ec81c14d3955/lib/platform/bitbucket/utils.js
-const url = require('url');
-const api = require('./bb-got-wrapper');
+import url from 'url';
+import api from './bb-got-wrapper';
 
 // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html#idp250
-const prStateMapping = {
+const prStateMapping: any = {
   MERGED: 'merged',
   DECLINED: 'closed',
   OPEN: 'open',
 };
 
-const prInfo = pr => ({
-  version: pr.version,
-  number: pr.id,
-  body: pr.description,
-  branchName: pr.fromRef.displayId,
-  title: pr.title,
-  state: prStateMapping[pr.state],
-  createdAt: pr.createdDate,
-  canRebase: false,
-});
-
-const addMaxLength = (inputUrl, limit = 100) => {
+export function prInfo(pr: any) {
+  return {
+    version: pr.version,
+    number: pr.id,
+    body: pr.description,
+    branchName: pr.fromRef.displayId,
+    title: pr.title,
+    state: prStateMapping[pr.state],
+    createdAt: pr.createdDate,
+    canRebase: false,
+  };
+}
+
+const addMaxLength = (inputUrl: string, limit = 100) => {
   const { search, ...parsedUrl } = url.parse(inputUrl, true); // eslint-disable-line @typescript-eslint/no-unused-vars
   const maxedUrl = url.format({
     ...parsedUrl,
@@ -29,13 +31,19 @@ const addMaxLength = (inputUrl, limit = 100) => {
   return maxedUrl;
 };
 
-const accumulateValues = async (reqUrl, method = 'get', options, limit) => {
-  let accumulator = [];
+export async function accumulateValues(
+  reqUrl: string,
+  method = 'get',
+  options?: any,
+  limit?: number
+) {
+  let accumulator: any = [];
   let nextUrl = addMaxLength(reqUrl, limit);
   const lowerCaseMethod = method.toLocaleLowerCase();
 
   while (typeof nextUrl !== 'undefined') {
-    const { body } = await api[lowerCaseMethod](nextUrl, options);
+    // TODO: fix typing
+    const { body } = await (api as any)[lowerCaseMethod](nextUrl, options);
     accumulator = [...accumulator, ...body.values];
     if (body.isLastPage !== false) break;
 
@@ -50,13 +58,4 @@ const accumulateValues = async (reqUrl, method = 'get', options, limit) => {
   }
 
   return accumulator;
-};
-
-module.exports = {
-  // buildStates,
-  prInfo,
-  accumulateValues,
-  // files: filesEndpoint,
-  // isConflicted,
-  // commitForm,
-};
+}
diff --git a/lib/platform/common.ts b/lib/platform/common.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8e09c24be2b487ec20c3c82a2cfb6b21e5107bd9
--- /dev/null
+++ b/lib/platform/common.ts
@@ -0,0 +1,37 @@
+import got from 'got';
+
+export interface IGotApiOptions {
+  useCache?: boolean;
+  body?: any;
+}
+
+export interface IGotApi {
+  get<T extends object = any>(
+    url: string,
+    options?: IGotApiOptions
+  ): Promise<got.Response<T>>;
+  post<T extends object = any>(
+    url: string,
+    options?: IGotApiOptions
+  ): Promise<got.Response<T>>;
+  put<T extends object = any>(
+    url: string,
+    options?: IGotApiOptions
+  ): Promise<got.Response<T>>;
+  patch<T extends object = any>(
+    url: string,
+    options?: IGotApiOptions
+  ): Promise<got.Response<T>>;
+  head<T extends object = any>(
+    url: string,
+    options?: IGotApiOptions
+  ): Promise<got.Response<T>>;
+  delete<T extends object = any>(
+    url: string,
+    options?: IGotApiOptions
+  ): Promise<got.Response<T>>;
+
+  reset(): void;
+
+  setEndpoint(endpoint: string): void;
+}
diff --git a/lib/platform/git/storage.ts b/lib/platform/git/storage.ts
index 3b9149fc806ec4b5430929c83ae4ca8720aef6b2..986b00d7648ec2ebcacff8dbd206f7be078868e3 100644
--- a/lib/platform/git/storage.ts
+++ b/lib/platform/git/storage.ts
@@ -5,6 +5,7 @@ import Git from 'simple-git/promise';
 import URL from 'url';
 
 declare module 'fs-extra' {
+  // eslint-disable-next-line import/prefer-default-export
   export function exists(pathLike: string): Promise<boolean>;
 }
 
@@ -24,7 +25,9 @@ interface ILocalConfig extends IStorageConfig {
 
 class Storage {
   private _config: ILocalConfig = {} as any;
+
   private _git: Git.SimpleGit | undefined;
+
   private _cwd: string | undefined;
 
   private async _resetToBranch(branchName: string) {
@@ -50,14 +53,16 @@ class Storage {
   async initRepo(args: IStorageConfig) {
     debugger;
     this.cleanRepo();
-    let config: ILocalConfig = (this._config = { ...args } as any);
-    let cwd = (this._cwd = config.localDir);
+    // eslint-disable-next-line no-multi-assign
+    const config: ILocalConfig = (this._config = { ...args } as any);
+    // eslint-disable-next-line no-multi-assign
+    const cwd = (this._cwd = config.localDir);
     this._config.branchExists = {};
     logger.info('Initialising git repository into ' + cwd);
     const gitHead = join(cwd, '.git/HEAD');
     let clone = true;
 
-    //TODO: move to private class scope
+    // TODO: move to private class scope
     async function determineBaseBranch(git: Git.SimpleGit) {
       // see https://stackoverflow.com/a/44750379/1438522
       try {
@@ -423,6 +428,7 @@ class Storage {
     }
   }
 
+  // eslint-disable-next-line class-methods-use-this
   cleanRepo() {}
 
   static getUrl({
diff --git a/lib/types.d.ts b/lib/types.d.ts
index 4df000bb6b8c5b636aec79bef5d316c952876b5f..e681ad47649dd9ad464e8d7369d721cc6792ce2c 100644
--- a/lib/types.d.ts
+++ b/lib/types.d.ts
@@ -11,8 +11,13 @@ declare namespace Renovate {
 
     setMeta(obj: any): void;
   }
+
+  interface IDict<T> {
+    [key: string]: T;
+  }
 }
 
+// eslint-disable-next-line no-var, vars-on-top
 declare var logger: Renovate.ILogger;
 
 declare interface Error {
diff --git a/lib/util/host-rules.ts b/lib/util/host-rules.ts
index 1438ae6f74d7ff6650a3555591e044cef3136dbb..9b8d6abbee05c48abba0ca9eb7decf09f369f182 100644
--- a/lib/util/host-rules.ts
+++ b/lib/util/host-rules.ts
@@ -1,10 +1,20 @@
 import URL from 'url';
 
-//TODO: add known properties
-interface IPlatformConfig {
+export const defaults: IDict<IPlatformConfig> = {
+  bitbucket: { name: 'Bitbucket', endpoint: 'https://api.bitbucket.org/' },
+  'bitbucket-server': { name: 'Bitbucket Server' },
+  github: { name: 'GitHub', endpoint: 'https://api.github.com/' },
+  gitlab: { name: 'GitLab', endpoint: 'https://gitlab.com/api/v4/' },
+  azure: { name: 'Azure DevOps' },
+};
+
+// TODO: add known properties
+export interface IPlatformConfig {
   [prop: string]: any;
   name?: string;
   endpoint?: string;
+
+  token?: string;
 }
 interface IDict<T> {
   [key: string]: T;
diff --git a/package.json b/package.json
index ec53076b6d4f702f79d63f78234856f50d5815ff..cbfa59e86576ca04f51ad8bca58baaca5382d516 100644
--- a/package.json
+++ b/package.json
@@ -154,9 +154,10 @@
     "@types/bunyan": "1.8.6",
     "@types/convert-hrtime": "2.0.0",
     "@types/fs-extra": "7.0.0",
+    "@types/got": "9.4.4",
     "@types/jest": "24.0.13",
     "@types/node": "11.13.11",
-    "@types/tmp": "0.1.0",
+    "@types/tmp": "0.0.33",
     "@typescript-eslint/eslint-plugin": "1.9.0",
     "@typescript-eslint/parser": "1.9.0",
     "babel-plugin-transform-object-rest-spread": "7.0.0-beta.3",
diff --git a/test/platform/bitbucket-server/__snapshots__/index.spec.js.snap b/test/platform/bitbucket-server/__snapshots__/index.spec.ts.snap
similarity index 99%
rename from test/platform/bitbucket-server/__snapshots__/index.spec.js.snap
rename to test/platform/bitbucket-server/__snapshots__/index.spec.ts.snap
index 5a01392c476ca178d2dc22df7a97bdfa192fed19..9ce523c66f9aef822d790186d28ce7a1d887f36e 100644
--- a/test/platform/bitbucket-server/__snapshots__/index.spec.js.snap
+++ b/test/platform/bitbucket-server/__snapshots__/index.spec.ts.snap
@@ -922,14 +922,6 @@ Object {
 }
 `;
 
-exports[`platform/bitbucket-server endpoint with no path initRepo() no author 1`] = `
-Object {
-  "isFork": false,
-  "privateRepo": undefined,
-  "repoFullName": "repo",
-}
-`;
-
 exports[`platform/bitbucket-server endpoint with no path initRepo() works 1`] = `
 Object {
   "isFork": false,
@@ -2300,14 +2292,6 @@ Object {
 }
 `;
 
-exports[`platform/bitbucket-server endpoint with path initRepo() no author 1`] = `
-Object {
-  "isFork": false,
-  "privateRepo": undefined,
-  "repoFullName": "repo",
-}
-`;
-
 exports[`platform/bitbucket-server endpoint with path initRepo() works 1`] = `
 Object {
   "isFork": false,
diff --git a/test/platform/bitbucket-server/index.spec.js b/test/platform/bitbucket-server/index.spec.ts
similarity index 89%
rename from test/platform/bitbucket-server/index.spec.js
rename to test/platform/bitbucket-server/index.spec.ts
index 8c4bf7cd7e07f9202d0634d4c1c3e6622f3d7678..30cbb322b787a4c373a6b2daa81b302007d1f773 100644
--- a/test/platform/bitbucket-server/index.spec.js
+++ b/test/platform/bitbucket-server/index.spec.ts
@@ -1,17 +1,23 @@
-const responses = require('./_fixtures/responses');
+import responses from './_fixtures/responses';
+import { IGotApi } from '../../../lib/platform/common';
+import Storage from '../../../lib/platform/git/storage';
+
+type BbsApi = typeof import('../../../lib/platform/bitbucket-server');
 
 describe('platform/bitbucket-server', () => {
   Object.entries(responses).forEach(([scenarioName, mockResponses]) => {
     describe(scenarioName, () => {
-      let bitbucket;
-      let api;
-      let hostRules;
-      let GitStorage;
+      let bitbucket: typeof import('../../../lib/platform/bitbucket-server');
+      let api: jest.Mocked<IGotApi>;
+      let hostRules: jest.Mocked<typeof import('../../../lib/util/host-rules')>;
+      let GitStorage: jest.Mock<Storage> & {
+        getUrl: jest.MockInstance<any, any>;
+      };
       beforeEach(() => {
         // reset module
         jest.resetModules();
         jest.mock('delay');
-        jest.mock('got', () => (url, options) => {
+        jest.mock('got', () => (url: string, options: { method: string }) => {
           const { method } = options;
           const body = mockResponses[url] && mockResponses[url][method];
           if (!body) {
@@ -25,32 +31,36 @@ describe('platform/bitbucket-server', () => {
         jest.mock('../../../lib/platform/git/storage');
         jest.mock('../../../lib/util/host-rules');
         hostRules = require('../../../lib/util/host-rules');
-        api = require('../../../lib/platform/bitbucket-server/bb-got-wrapper');
+        api = require('../../../lib/platform/bitbucket-server/bb-got-wrapper')
+          .api;
         jest.spyOn(api, 'get');
         jest.spyOn(api, 'post');
         jest.spyOn(api, 'put');
         jest.spyOn(api, 'delete');
         bitbucket = require('../../../lib/platform/bitbucket-server');
         GitStorage = require('../../../lib/platform/git/storage');
-        GitStorage.mockImplementation(() => ({
-          initRepo: jest.fn(),
-          cleanRepo: jest.fn(),
-          getFileList: jest.fn(),
-          branchExists: jest.fn(() => true),
-          isBranchStale: jest.fn(() => false),
-          setBaseBranch: jest.fn(),
-          getBranchLastCommitTime: jest.fn(),
-          getAllRenovateBranches: jest.fn(),
-          getCommitMessages: jest.fn(),
-          getFile: jest.fn(),
-          commitFilesToBranch: jest.fn(),
-          mergeBranch: jest.fn(),
-          deleteBranch: jest.fn(),
-          getRepoStatus: jest.fn(),
-          getBranchCommit: jest.fn(
-            () => '0d9c7726c3d628b7e28af234595cfd20febdbf8e'
-          ),
-        }));
+        GitStorage.mockImplementation(
+          () =>
+            ({
+              initRepo: jest.fn(),
+              cleanRepo: jest.fn(),
+              getFileList: jest.fn(),
+              branchExists: jest.fn(() => true),
+              isBranchStale: jest.fn(() => false),
+              setBaseBranch: jest.fn(),
+              getBranchLastCommitTime: jest.fn(),
+              getAllRenovateBranches: jest.fn(),
+              getCommitMessages: jest.fn(),
+              getFile: jest.fn(),
+              commitFilesToBranch: jest.fn(),
+              mergeBranch: jest.fn(),
+              deleteBranch: jest.fn(),
+              getRepoStatus: jest.fn(),
+              getBranchCommit: jest.fn(
+                () => '0d9c7726c3d628b7e28af234595cfd20febdbf8e'
+              ),
+            } as any)
+        );
         const endpoint =
           scenarioName === 'endpoint with path'
             ? 'https://stash.renovatebot.com/vcs/'
@@ -75,19 +85,18 @@ describe('platform/bitbucket-server', () => {
       function initRepo() {
         return bitbucket.initRepo({
           repository: 'SOME/repo',
-          gitAuthor: 'bot@renovateapp.com',
-        });
+        } as any);
       }
 
       describe('init function', () => {
         it('should throw if no endpoint', () => {
           expect(() => {
-            bitbucket.initPlatform({});
+            bitbucket.initPlatform({} as any);
           }).toThrow();
         });
         it('should throw if no username/password', () => {
           expect(() => {
-            bitbucket.initPlatform({ endpoint: 'endpoint' });
+            bitbucket.initPlatform({ endpoint: 'endpoint' } as any);
           }).toThrow();
         });
         it('should init', () => {
@@ -116,20 +125,12 @@ describe('platform/bitbucket-server', () => {
           expect(res).toMatchSnapshot();
         });
 
-        it('no author', async () => {
-          expect.assertions(1);
-          const res = await bitbucket.initRepo({
-            repository: 'SOME/repo',
-          });
-          expect(res).toMatchSnapshot();
-        });
-
         it('sends the host as the endpoint option', async () => {
           expect.assertions(2);
           GitStorage.getUrl.mockClear();
           await bitbucket.initRepo({
             repository: 'SOME/repo',
-          });
+          } as any);
           expect(GitStorage.getUrl).toHaveBeenCalledTimes(1);
           expect(GitStorage.getUrl.mock.calls[0][0]).toHaveProperty(
             'host',
@@ -167,7 +168,7 @@ describe('platform/bitbucket-server', () => {
         describe('getFileList()', () => {
           it('sends to gitFs', async () => {
             await initRepo();
-            await bitbucket.branchExists();
+            await bitbucket.branchExists(undefined as any);
           });
         });
       });
@@ -175,7 +176,7 @@ describe('platform/bitbucket-server', () => {
       describe('isBranchStale()', () => {
         it('sends to gitFs', async () => {
           await initRepo();
-          await bitbucket.isBranchStale();
+          await bitbucket.isBranchStale(undefined as any);
         });
       });
 
@@ -197,7 +198,7 @@ describe('platform/bitbucket-server', () => {
         it('sends to gitFs', async () => {
           expect.assertions(1);
           await initRepo();
-          await bitbucket.commitFilesToBranch('some-branch', [{}]);
+          await bitbucket.commitFilesToBranch('some-branch', [{}], 'message');
           expect(api.get.mock.calls).toMatchSnapshot();
         });
       });
@@ -205,21 +206,21 @@ describe('platform/bitbucket-server', () => {
       describe('getFile()', () => {
         it('sends to gitFs', async () => {
           await initRepo();
-          await bitbucket.getFile();
+          await bitbucket.getFile('', '');
         });
       });
 
       describe('getAllRenovateBranches()', () => {
         it('sends to gitFs', async () => {
           await initRepo();
-          await bitbucket.getAllRenovateBranches();
+          await bitbucket.getAllRenovateBranches('');
         });
       });
 
       describe('getBranchLastCommitTime()', () => {
         it('sends to gitFs', async () => {
           await initRepo();
-          await bitbucket.getBranchLastCommitTime();
+          await bitbucket.getBranchLastCommitTime('');
         });
       });
 
@@ -248,9 +249,9 @@ describe('platform/bitbucket-server', () => {
           expect.assertions(5);
           await initRepo();
 
-          await expect(bitbucket.addReviewers(null, ['name'])).rejects.toThrow(
-            'not-found'
-          );
+          await expect(
+            bitbucket.addReviewers(null as any, ['name'])
+          ).rejects.toThrow('not-found');
 
           await expect(bitbucket.addReviewers(4, ['name'])).rejects.toThrow(
             'not-found'
@@ -426,7 +427,7 @@ describe('platform/bitbucket-server', () => {
           expect.assertions(2);
           await initRepo();
           expect(
-            await bitbucket.findPr('userName1/pullRequest1', false)
+            await bitbucket.findPr('userName1/pullRequest1')
           ).toBeUndefined();
           expect(api.get.mock.calls).toMatchSnapshot();
         });
@@ -480,7 +481,7 @@ describe('platform/bitbucket-server', () => {
       describe('getPr()', () => {
         it('returns null for no prNo', async () => {
           expect.assertions(2);
-          expect(await bitbucket.getPr()).toBeNull();
+          expect(await bitbucket.getPr(undefined as any)).toBeNull();
           expect(api.get.mock.calls).toMatchSnapshot();
         });
         it('gets a PR', async () => {
@@ -497,10 +498,10 @@ describe('platform/bitbucket-server', () => {
           try {
             expect(await bitbucket.getPr(3)).toMatchSnapshot();
 
-            global.gitAuthor = { email: 'bot@renovateapp.com' };
+            global.gitAuthor = { email: 'bot@renovateapp.com', name: 'bot' };
             expect(await bitbucket.getPr(5)).toMatchSnapshot();
 
-            global.gitAuthor = { email: 'jane@example.com' };
+            global.gitAuthor = { email: 'jane@example.com', name: 'jane' };
             expect(await bitbucket.getPr(5)).toMatchSnapshot();
 
             expect(api.get.mock.calls).toMatchSnapshot();
@@ -520,7 +521,7 @@ describe('platform/bitbucket-server', () => {
               reviewers: [],
               fromRef: {},
             },
-          });
+          } as any);
           expect(await bitbucket.getPr(5)).toMatchSnapshot();
           expect(api.get.mock.calls).toMatchSnapshot();
         });
@@ -529,7 +530,7 @@ describe('platform/bitbucket-server', () => {
       describe('getPrFiles()', () => {
         it('returns empty files', async () => {
           expect.assertions(1);
-          expect(await bitbucket.getPrFiles(null)).toHaveLength(0);
+          expect(await bitbucket.getPrFiles(null as any)).toHaveLength(0);
         });
 
         it('returns one file', async () => {
@@ -554,7 +555,7 @@ describe('platform/bitbucket-server', () => {
           await initRepo();
 
           await expect(
-            bitbucket.updatePr(null, 'title', 'body')
+            bitbucket.updatePr(null as any, 'title', 'body')
           ).rejects.toThrow('not-found');
 
           await expect(bitbucket.updatePr(4, 'title', 'body')).rejects.toThrow(
@@ -617,9 +618,9 @@ describe('platform/bitbucket-server', () => {
           expect.assertions(5);
           await initRepo();
 
-          await expect(bitbucket.mergePr(null, 'branch')).rejects.toThrow(
-            'not-found'
-          );
+          await expect(
+            bitbucket.mergePr(null as any, 'branch')
+          ).rejects.toThrow('not-found');
           await expect(bitbucket.mergePr(4, 'branch')).rejects.toThrow(
             'not-found'
           );
@@ -700,7 +701,7 @@ describe('platform/bitbucket-server', () => {
               inProgress: 0,
               failed: 0,
             },
-          });
+          } as any);
 
           await expect(
             bitbucket.getBranchStatus('somebranch', true)
@@ -722,7 +723,7 @@ describe('platform/bitbucket-server', () => {
               inProgress: 1,
               failed: 0,
             },
-          });
+          } as any);
 
           await expect(
             bitbucket.getBranchStatus('somebranch', true)
@@ -734,7 +735,7 @@ describe('platform/bitbucket-server', () => {
               inProgress: 0,
               failed: 0,
             },
-          });
+          } as any);
 
           await expect(
             bitbucket.getBranchStatus('somebranch', true)
@@ -753,7 +754,7 @@ describe('platform/bitbucket-server', () => {
               inProgress: 1,
               failed: 1,
             },
-          });
+          } as any);
 
           await expect(
             bitbucket.getBranchStatus('somebranch', true)
@@ -772,11 +773,14 @@ describe('platform/bitbucket-server', () => {
 
         it('throws repository-changed', async () => {
           expect.assertions(1);
-          GitStorage.mockImplementationOnce(() => ({
-            initRepo: jest.fn(),
-            branchExists: jest.fn(() => Promise.resolve(false)),
-            cleanRepo: jest.fn(),
-          }));
+          GitStorage.mockImplementationOnce(
+            () =>
+              ({
+                initRepo: jest.fn(),
+                branchExists: jest.fn(() => Promise.resolve(false)),
+                cleanRepo: jest.fn(),
+              } as any)
+          );
           await initRepo();
           await expect(
             bitbucket.getBranchStatus('somebranch', true)
@@ -799,7 +803,7 @@ describe('platform/bitbucket-server', () => {
                 },
               ],
             },
-          });
+          } as any);
 
           await expect(
             bitbucket.getBranchStatusCheck('somebranch', 'context-2')
@@ -822,7 +826,7 @@ describe('platform/bitbucket-server', () => {
                 },
               ],
             },
-          });
+          } as any);
 
           await expect(
             bitbucket.getBranchStatusCheck('somebranch', 'context-2')
@@ -845,7 +849,7 @@ describe('platform/bitbucket-server', () => {
                 },
               ],
             },
-          });
+          } as any);
 
           await expect(
             bitbucket.getBranchStatusCheck('somebranch', 'context-2')
@@ -870,7 +874,7 @@ describe('platform/bitbucket-server', () => {
               isLastPage: true,
               values: [],
             },
-          });
+          } as any);
 
           await expect(
             bitbucket.getBranchStatusCheck('somebranch', 'context-2')
@@ -889,28 +893,28 @@ describe('platform/bitbucket-server', () => {
           await bitbucket.setBranchStatus(
             'somebranch',
             'context-2',
-            null,
+            null as any,
             'success'
           );
 
           await bitbucket.setBranchStatus(
             'somebranch',
             'context-2',
-            null,
+            null as any,
             'failed'
           );
 
           await bitbucket.setBranchStatus(
             'somebranch',
             'context-2',
-            null,
+            null as any,
             'failure'
           );
 
           await bitbucket.setBranchStatus(
             'somebranch',
             'context-2',
-            null,
+            null as any,
             'pending'
           );
 
@@ -921,14 +925,14 @@ describe('platform/bitbucket-server', () => {
           await bitbucket.setBranchStatus(
             'somebranch',
             'context-2',
-            null,
+            null as any,
             'success'
           );
 
           await bitbucket.setBranchStatus(
             'somebranch',
             'context-1',
-            null,
+            null as any,
             'success'
           );
 
diff --git a/test/platform/index.spec.js b/test/platform/index.spec.js
index a0078fe096281c10f877587cd19ee09e05177466..b8799633ed8a2f1b1d1c671d74af25f7ca7cd52c 100644
--- a/test/platform/index.spec.js
+++ b/test/platform/index.spec.js
@@ -31,26 +31,26 @@ describe('platform', () => {
   });
 
   it('has same API for github and gitlab', () => {
-    const githubMethods = Object.keys(github);
-    const gitlabMethods = Object.keys(gitlab);
+    const githubMethods = Object.keys(github).sort();
+    const gitlabMethods = Object.keys(gitlab).sort();
     expect(githubMethods).toMatchObject(gitlabMethods);
   });
 
   it('has same API for github and azure', () => {
-    const githubMethods = Object.keys(github);
-    const azureMethods = Object.keys(azure);
+    const githubMethods = Object.keys(github).sort();
+    const azureMethods = Object.keys(azure).sort();
     expect(githubMethods).toMatchObject(azureMethods);
   });
 
   it('has same API for github and Bitbucket', () => {
-    const githubMethods = Object.keys(github);
-    const bitbucketMethods = Object.keys(bitbucket);
+    const githubMethods = Object.keys(github).sort();
+    const bitbucketMethods = Object.keys(bitbucket).sort();
     expect(bitbucketMethods).toMatchObject(githubMethods);
   });
 
   it('has same API for github and Bitbucket Server', () => {
-    const githubMethods = Object.keys(github);
-    const bitbucketMethods = Object.keys(bitbucketServer);
+    const githubMethods = Object.keys(github).sort();
+    const bitbucketMethods = Object.keys(bitbucketServer).sort();
     expect(bitbucketMethods).toMatchObject(githubMethods);
   });
 });
diff --git a/yarn.lock b/yarn.lock
index 1ed4d8d6efb055507fb8a8e0aa6c489bcabf727c..e0baf49068391e79351212745e65dc180afc6c8b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -521,6 +521,14 @@
     "@types/minimatch" "*"
     "@types/node" "*"
 
+"@types/got@9.4.4":
+  version "9.4.4"
+  resolved "https://registry.yarnpkg.com/@types/got/-/got-9.4.4.tgz#78129553f6a41715df601db43532cd0b87a55d3f"
+  integrity sha512-IGAJokJRE9zNoBdY5csIwN4U5qQn+20HxC0kM+BbUdfTKIXa7bOX/pdhy23NnLBRP8Wvyhx7X5e6EHJs+4d8HA==
+  dependencies:
+    "@types/node" "*"
+    "@types/tough-cookie" "*"
+
 "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
@@ -578,10 +586,15 @@
   resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
   integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
 
-"@types/tmp@0.1.0":
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.1.0.tgz#19cf73a7bcf641965485119726397a096f0049bd"
-  integrity sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA==
+"@types/tmp@0.0.33":
+  version "0.0.33"
+  resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
+  integrity sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=
+
+"@types/tough-cookie@*":
+  version "2.3.5"
+  resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d"
+  integrity sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==
 
 "@types/yargs@^12.0.2", "@types/yargs@^12.0.9":
   version "12.0.9"