From cc52c205338d105267c1b4e682abdd150670c3dd Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Mon, 20 May 2019 15:08:18 +0200 Subject: [PATCH] feat(bitbucket-server): convert to typescript (#3756) --- .eslintrc.js | 7 + .../{bb-got-wrapper.js => bb-got-wrapper.ts} | 36 ++- .../bitbucket-server/{index.js => index.ts} | 303 +++++++++--------- .../bitbucket-server/{utils.js => utils.ts} | 55 ++-- lib/platform/common.ts | 37 +++ lib/platform/git/storage.ts | 12 +- lib/types.d.ts | 5 + lib/util/host-rules.ts | 14 +- package.json | 3 +- ...{index.spec.js.snap => index.spec.ts.snap} | 16 - .../{index.spec.js => index.spec.ts} | 158 ++++----- test/platform/index.spec.js | 16 +- yarn.lock | 21 +- 13 files changed, 386 insertions(+), 297 deletions(-) rename lib/platform/bitbucket-server/{bb-got-wrapper.js => bb-got-wrapper.ts} (56%) rename lib/platform/bitbucket-server/{index.js => index.ts} (79%) rename lib/platform/bitbucket-server/{utils.js => utils.ts} (60%) create mode 100644 lib/platform/common.ts rename test/platform/bitbucket-server/__snapshots__/{index.spec.js.snap => index.spec.ts.snap} (99%) rename test/platform/bitbucket-server/{index.spec.js => index.spec.ts} (89%) diff --git a/.eslintrc.js b/.eslintrc.js index 8bfe82c0ddfb20..8e2b877031139d 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 f4b9bd44e74873..066de5393cbeb7 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> = {}; 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 a159d51a347a5c..8adea7fc0cf5f3 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 44423b33d79986..dc6eab449a1105 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 00000000000000..8e09c24be2b487 --- /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( + url: string, + options?: IGotApiOptions + ): Promise>; + post( + url: string, + options?: IGotApiOptions + ): Promise>; + put( + url: string, + options?: IGotApiOptions + ): Promise>; + patch( + url: string, + options?: IGotApiOptions + ): Promise>; + head( + url: string, + options?: IGotApiOptions + ): Promise>; + delete( + url: string, + options?: IGotApiOptions + ): Promise>; + + reset(): void; + + setEndpoint(endpoint: string): void; +} diff --git a/lib/platform/git/storage.ts b/lib/platform/git/storage.ts index 3b9149fc806ec4..986b00d7648ec2 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; } @@ -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 4df000bb6b8c5b..e681ad47649dd9 100644 --- a/lib/types.d.ts +++ b/lib/types.d.ts @@ -11,8 +11,13 @@ declare namespace Renovate { setMeta(obj: any): void; } + + interface IDict { + [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 1438ae6f74d7ff..9b8d6abbee05c4 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 = { + 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 { [key: string]: T; diff --git a/package.json b/package.json index ec53076b6d4f70..cbfa59e86576ca 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 5a01392c476ca1..9ce523c66f9aef 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 8c4bf7cd7e07f9..30cbb322b787a4 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; + let hostRules: jest.Mocked; + let GitStorage: jest.Mock & { + getUrl: jest.MockInstance; + }; 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 a0078fe096281c..b8799633ed8a2f 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 1ed4d8d6efb055..e0baf49068391e 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"