From f0d4995fdac22611a7d5e5f20acc0963d800e67f Mon Sep 17 00:00:00 2001 From: Michael Kriese <michael.kriese@visualon.de> Date: Tue, 26 Nov 2019 16:13:07 +0100 Subject: [PATCH] =?UTF-8?q?fix(eslint):=20'@typescript-eslint/explicit-fun?= =?UTF-8?q?ction-return-=E2=80=A6=20(#4872)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.js | 2 + lib/datasource/docker/index.ts | 28 ++- lib/datasource/github/index.ts | 2 +- lib/datasource/gitlab/index.ts | 10 +- lib/datasource/index.ts | 12 +- lib/datasource/maven/util.ts | 14 +- lib/datasource/metadata.ts | 4 +- lib/datasource/npm/get.ts | 4 +- lib/datasource/npm/npmrc.ts | 2 +- lib/datasource/nuget/v2.ts | 2 +- lib/datasource/nuget/v3.ts | 2 +- lib/datasource/packagist/index.ts | 12 +- lib/datasource/pypi/index.ts | 4 +- lib/datasource/rubygems/get-rubygems-org.ts | 8 +- lib/datasource/rubygems/get.ts | 7 +- lib/datasource/rubygems/retriable.ts | 2 +- lib/datasource/sbt/index.ts | 8 +- lib/datasource/sbt/util.ts | 4 +- lib/datasource/terraform/index.ts | 10 +- lib/logger/pretty-stdout.ts | 4 +- lib/logger/utils.ts | 8 +- lib/platform/azure/azure-got-wrapper.ts | 13 +- lib/platform/azure/azure-helper.ts | 84 ++++---- lib/platform/azure/index.ts | 125 +++++++----- .../bitbucket-server/bb-got-wrapper.ts | 11 +- lib/platform/bitbucket-server/index.ts | 180 +++++++++++------- lib/platform/bitbucket-server/utils.ts | 11 +- lib/platform/bitbucket/bb-got-wrapper.ts | 9 +- lib/platform/bitbucket/comments.ts | 21 +- lib/platform/bitbucket/index.ts | 148 ++++++++------ lib/platform/bitbucket/utils.ts | 22 ++- lib/platform/common.ts | 10 +- lib/platform/git/storage.ts | 73 ++++--- lib/platform/github/gh-got-wrapper.ts | 10 +- lib/platform/github/index.ts | 168 ++++++++++------ lib/platform/gitlab/gl-got-wrapper.ts | 8 +- lib/platform/gitlab/index.ts | 99 +++++----- .../repository/onboarding/branch/check.ts | 4 +- .../__snapshots__/azure-helper.spec.ts.snap | 30 --- test/platform/azure/azure-helper.spec.ts | 57 ------ test/platform/azure/index.spec.ts | 116 ++++++----- test/platform/bitbucket-server/index.spec.ts | 6 +- test/platform/gitlab/index.spec.ts | 2 +- test/workers/global/autodiscover.spec.ts | 2 +- 44 files changed, 771 insertions(+), 587 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 53e5435b79..378cc3c8eb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -25,6 +25,8 @@ module.exports = { 'prefer-template': 'off', 'no-underscore-dangle': 0, + '@typescript-eslint/explicit-function-return-type': 'error', + // TODO: fix lint '@typescript-eslint/camelcase': 'off', // disabled until ?? '@typescript-eslint/no-explicit-any': 0, diff --git a/lib/datasource/docker/index.ts b/lib/datasource/docker/index.ts index 90a11673d7..5695222408 100644 --- a/lib/datasource/docker/index.ts +++ b/lib/datasource/docker/index.ts @@ -9,16 +9,22 @@ import { logger } from '../../logger'; import got from '../../util/got'; import * as hostRules from '../../util/host-rules'; import { PkgReleaseConfig, ReleaseResult } from '../common'; +import { GotResponse } from '../../platform'; // TODO: add got typings when available // TODO: replace www-authenticate with https://www.npmjs.com/package/auth-header ? const ecrRegex = /\d+\.dkr\.ecr\.([-a-z0-9]+)\.amazonaws\.com/; +export interface RegistryRepository { + registry: string; + repository: string; +} + export function getRegistryRepository( lookupName: string, registryUrls: string[] -) { +): RegistryRepository { let registry: string; const split = lookupName.split('/'); if (split.length > 1 && (split[0].includes('.') || split[0].includes(':'))) { @@ -48,7 +54,10 @@ export function getRegistryRepository( }; } -function getECRAuthToken(region: string, opts: hostRules.HostRule) { +function getECRAuthToken( + region: string, + opts: hostRules.HostRule +): Promise<string | null> { const config = { region, accessKeyId: undefined, secretAccessKey: undefined }; if (opts.username && opts.password) { config.accessKeyId = opts.username; @@ -171,22 +180,22 @@ async function getAuthHeaders( } } -function digestFromManifestStr(str: hasha.HashaInput) { +function digestFromManifestStr(str: hasha.HashaInput): string { return 'sha256:' + hasha(str, { algorithm: 'sha256' }); } -function extractDigestFromResponse(manifestResponse) { +function extractDigestFromResponse(manifestResponse: GotResponse): string { if (manifestResponse.headers['docker-content-digest'] === undefined) { return digestFromManifestStr(manifestResponse.body); } - return manifestResponse.headers['docker-content-digest']; + return manifestResponse.headers['docker-content-digest'] as string; } async function getManifestResponse( registry: string, repository: string, tag: string -) { +): Promise<GotResponse> { logger.debug(`getManifestResponse(${registry}, ${repository}, ${tag})`); try { const headers = await getAuthHeaders(registry, repository); @@ -408,12 +417,15 @@ async function getTags( } } -export function getConfigResponse(url: string, headers: OutgoingHttpHeaders) { +export function getConfigResponse( + url: string, + headers: OutgoingHttpHeaders +): Promise<GotResponse> { return got(url, { headers, hooks: { beforeRedirect: [ - (options: any) => { + (options: any): void => { if ( options.search && options.search.indexOf('X-Amz-Algorithm') !== -1 diff --git a/lib/datasource/github/index.ts b/lib/datasource/github/index.ts index 9011e45c3f..6f3eb32e53 100644 --- a/lib/datasource/github/index.ts +++ b/lib/datasource/github/index.ts @@ -66,7 +66,7 @@ export async function getPreset( } const cacheNamespace = 'datasource-github'; -function getCacheKey(repo: string, type: string) { +function getCacheKey(repo: string, type: string): string { return `${repo}:${type}`; } diff --git a/lib/datasource/gitlab/index.ts b/lib/datasource/gitlab/index.ts index 7de82a6273..1ec57d42db 100644 --- a/lib/datasource/gitlab/index.ts +++ b/lib/datasource/gitlab/index.ts @@ -7,7 +7,9 @@ const glGot = api.get; const GitLabApiUrl = 'https://gitlab.com/api/v4/projects'; -async function getDefaultBranchName(urlEncodedPkgName: string) { +async function getDefaultBranchName( + urlEncodedPkgName: string +): Promise<string> { const branchesUrl = `${GitLabApiUrl}/${urlEncodedPkgName}/repository/branches`; type GlBranch = { default: boolean; @@ -61,7 +63,11 @@ export async function getPreset( } const cacheNamespace = 'datasource-gitlab'; -function getCacheKey(depHost: string, repo: string, lookupType: string) { +function getCacheKey( + depHost: string, + repo: string, + lookupType: string +): string { const type = lookupType || 'tags'; return `${depHost}:${repo}:${type}`; } diff --git a/lib/datasource/index.ts b/lib/datasource/index.ts index 19a1cead21..1f9604aad0 100644 --- a/lib/datasource/index.ts +++ b/lib/datasource/index.ts @@ -74,7 +74,9 @@ async function fetchReleases( return dep; } -function getRawReleases(config: PkgReleaseConfig): Promise<ReleaseResult> { +function getRawReleases( + config: PkgReleaseConfig +): Promise<ReleaseResult | null> { const cacheKey = cacheNamespace + config.datasource + @@ -88,7 +90,9 @@ function getRawReleases(config: PkgReleaseConfig): Promise<ReleaseResult> { return global.repoCache[cacheKey]; } -export async function getPkgReleases(config: PkgReleaseConfig) { +export async function getPkgReleases( + config: PkgReleaseConfig +): Promise<ReleaseResult | null> { const res = await getRawReleases({ ...config, lookupName: config.lookupName || config.depName, @@ -101,7 +105,7 @@ export async function getPkgReleases(config: PkgReleaseConfig) { // Filter by version scheme const version = versioning.get(versionScheme); // Return a sorted list of valid Versions - function sortReleases(release1: Release, release2: Release) { + function sortReleases(release1: Release, release2: Release): number { return version.sortVersions(release1.version, release2.version); } if (res.releases) { @@ -112,7 +116,7 @@ export async function getPkgReleases(config: PkgReleaseConfig) { return res; } -export function supportsDigests(config: DigestConfig) { +export function supportsDigests(config: DigestConfig): boolean { return !!datasources[config.datasource].getDigest; } diff --git a/lib/datasource/maven/util.ts b/lib/datasource/maven/util.ts index 751a8b4a73..5dc03904e3 100644 --- a/lib/datasource/maven/util.ts +++ b/lib/datasource/maven/util.ts @@ -2,13 +2,13 @@ import url from 'url'; import got from '../../util/got'; import { logger } from '../../logger'; -function isMavenCentral(pkgUrl: url.URL | string) { +function isMavenCentral(pkgUrl: url.URL | string): boolean { return ( (typeof pkgUrl === 'string' ? pkgUrl : pkgUrl.host) === 'central.maven.org' ); } -function isTemporalError(err: { code: string; statusCode: number }) { +function isTemporalError(err: { code: string; statusCode: number }): boolean { return ( err.code === 'ECONNRESET' || err.statusCode === 429 || @@ -16,19 +16,19 @@ function isTemporalError(err: { code: string; statusCode: number }) { ); } -function isHostError(err: { code: string }) { +function isHostError(err: { code: string }): boolean { return err.code === 'ETIMEDOUT'; } -function isNotFoundError(err: { code: string; statusCode: number }) { +function isNotFoundError(err: { code: string; statusCode: number }): boolean { return err.code === 'ENOTFOUND' || err.statusCode === 404; } -function isPermissionsIssue(err: { statusCode: number }) { +function isPermissionsIssue(err: { statusCode: number }): boolean { return err.statusCode === 401 || err.statusCode === 403; } -function isConnectionError(err: { code: string }) { +function isConnectionError(err: { code: string }): boolean { return err.code === 'ECONNREFUSED'; } @@ -42,7 +42,7 @@ export async function downloadHttpProtocol( hostType, hooks: { beforeRedirect: [ - (options: any) => { + (options: any): void => { if ( options.search && options.search.indexOf('X-Amz-Algorithm') !== -1 diff --git a/lib/datasource/metadata.ts b/lib/datasource/metadata.ts index 4f451957d4..058fadd918 100644 --- a/lib/datasource/metadata.ts +++ b/lib/datasource/metadata.ts @@ -67,7 +67,7 @@ export function addMetaData( dep?: ReleaseResult, datasource?: string, lookupName?: string -) { +): void { if (!dep) { return; } @@ -86,7 +86,7 @@ export function addMetaData( /** * @param {string} url */ - const massageGithubUrl = url => { + const massageGithubUrl = (url: string): string => { return url .replace('http:', 'https:') .replace('www.github.com', 'github.com') diff --git a/lib/datasource/npm/get.ts b/lib/datasource/npm/get.ts index 9c49d53efe..0c54f3acec 100644 --- a/lib/datasource/npm/get.ts +++ b/lib/datasource/npm/get.ts @@ -15,12 +15,12 @@ import { Release, ReleaseResult } from '../common'; let memcache = {}; -export function resetMemCache() { +export function resetMemCache(): void { logger.debug('resetMemCache()'); memcache = {}; } -export function resetCache() { +export function resetCache(): void { resetMemCache(); } diff --git a/lib/datasource/npm/npmrc.ts b/lib/datasource/npm/npmrc.ts index 6a5f36af61..5a2292dcbc 100644 --- a/lib/datasource/npm/npmrc.ts +++ b/lib/datasource/npm/npmrc.ts @@ -27,7 +27,7 @@ function envReplace(value: any, env = process.env): any { }); } -export function setNpmrc(input?: string) { +export function setNpmrc(input?: string): void { if (input) { if (input === npmrcRaw) { return; diff --git a/lib/datasource/nuget/v2.ts b/lib/datasource/nuget/v2.ts index 0a55bdbcd1..7dfecce07b 100644 --- a/lib/datasource/nuget/v2.ts +++ b/lib/datasource/nuget/v2.ts @@ -4,7 +4,7 @@ import { logger } from '../../logger'; import got from '../../util/got'; import { ReleaseResult } from '../common'; -function getPkgProp(pkgInfo: XmlElement, propName: string) { +function getPkgProp(pkgInfo: XmlElement, propName: string): string { return pkgInfo.childNamed('m:properties').childNamed(`d:${propName}`).val; } diff --git a/lib/datasource/nuget/v3.ts b/lib/datasource/nuget/v3.ts index 1c4a446264..636dec0f01 100644 --- a/lib/datasource/nuget/v3.ts +++ b/lib/datasource/nuget/v3.ts @@ -9,7 +9,7 @@ import { ReleaseResult } from '../common'; const defaultNugetFeed = 'https://api.nuget.org/v3/index.json'; const cacheNamespace = 'datasource-nuget'; -export function getDefaultFeed() { +export function getDefaultFeed(): string { return defaultNugetFeed; } diff --git a/lib/datasource/packagist/index.ts b/lib/datasource/packagist/index.ts index 15ca4351b3..867959e8b7 100644 --- a/lib/datasource/packagist/index.ts +++ b/lib/datasource/packagist/index.ts @@ -6,12 +6,12 @@ import parse from 'github-url-from-git'; import pAll from 'p-all'; import { logger } from '../../logger'; -import got from '../../util/got'; +import got, { GotJSONOptions } from '../../util/got'; import * as hostRules from '../../util/host-rules'; import { PkgReleaseConfig, ReleaseResult } from '../common'; -function getHostOpts(url: string) { - const opts: any = { +function getHostOpts(url: string): GotJSONOptions { + const opts: GotJSONOptions = { json: true, }; const { username, password } = hostRules.find({ hostType: 'packagist', url }); @@ -173,7 +173,9 @@ async function getAllPackages(regUrl: string): Promise<AllPackages | null> { const { packages, providersUrl, files, includesFiles } = registryMeta; const providerPackages: Record<string, string> = {}; if (files) { - const queue = files.map(file => () => getPackagistFile(regUrl, file)); + const queue = files.map(file => (): Promise<PackagistFile> => + getPackagistFile(regUrl, file) + ); const resolvedFiles = await pAll(queue, { concurrency: 5 }); for (const res of resolvedFiles) { for (const [name, val] of Object.entries(res.providers)) { @@ -204,7 +206,7 @@ async function getAllPackages(regUrl: string): Promise<AllPackages | null> { return allPackages; } -async function packagistOrgLookup(name: string) { +async function packagistOrgLookup(name: string): Promise<ReleaseResult> { const cacheNamespace = 'datasource-packagist-org'; const cachedResult = await renovateCache.get<ReleaseResult>( cacheNamespace, diff --git a/lib/datasource/pypi/index.ts b/lib/datasource/pypi/index.ts index ea8a9e58b9..149dd52380 100644 --- a/lib/datasource/pypi/index.ts +++ b/lib/datasource/pypi/index.ts @@ -6,14 +6,14 @@ import { matches } from '../../versioning/pep440'; import got from '../../util/got'; import { PkgReleaseConfig, ReleaseResult } from '../common'; -function normalizeName(input: string) { +function normalizeName(input: string): string { return input.toLowerCase().replace(/(-|\.)/g, '_'); } function compatibleVersions( releases: Record<string, { requires_python?: boolean }[]>, compatibility: Record<string, string> -) { +): string[] { const versions = Object.keys(releases); if (!(compatibility && compatibility.python)) { return versions; diff --git a/lib/datasource/rubygems/get-rubygems-org.ts b/lib/datasource/rubygems/get-rubygems-org.ts index 6931ba83d9..9155780551 100644 --- a/lib/datasource/rubygems/get-rubygems-org.ts +++ b/lib/datasource/rubygems/get-rubygems-org.ts @@ -6,7 +6,7 @@ let lastSync = new Date('2000-01-01'); let packageReleases: Record<string, string[]> = Object.create(null); // Because we might need a "constructor" key let contentLength = 0; -async function updateRubyGemsVersions() { +async function updateRubyGemsVersions(): Promise<void> { const url = 'https://rubygems.org/versions'; const options = { headers: { @@ -30,7 +30,7 @@ async function updateRubyGemsVersions() { return; } - function processLine(line: string) { + function processLine(line: string): void { let split: string[]; let pkg: string; let versions: string; @@ -68,14 +68,14 @@ async function updateRubyGemsVersions() { lastSync = new Date(); } -function isDataStale() { +function isDataStale(): boolean { const minutesElapsed = Math.floor( (new Date().getTime() - lastSync.getTime()) / (60 * 1000) ); return minutesElapsed >= 5; } -async function syncVersions() { +async function syncVersions(): Promise<void> { if (isDataStale()) { global.updateRubyGemsVersions = global.updateRubyGemsVersions || updateRubyGemsVersions(); diff --git a/lib/datasource/rubygems/get.ts b/lib/datasource/rubygems/get.ts index e970248dec..a851facda0 100644 --- a/lib/datasource/rubygems/get.ts +++ b/lib/datasource/rubygems/get.ts @@ -1,3 +1,4 @@ +import { OutgoingHttpHeaders } from 'http'; import { logger } from '../../logger'; import got from '../../util/got'; import { maskToken } from '../../util/mask'; @@ -9,7 +10,7 @@ const INFO_PATH = '/api/v1/gems'; const VERSIONS_PATH = '/api/v1/versions'; // istanbul ignore next -const processError = ({ err, ...rest }) => { +const processError = ({ err, ...rest }): null => { const { statusCode, headers = {} } = err; const data = { ...rest, @@ -33,11 +34,11 @@ const processError = ({ err, ...rest }) => { return null; }; -const getHeaders = () => { +const getHeaders = (): OutgoingHttpHeaders => { return { hostType: 'rubygems' }; }; -const fetch = async ({ dependency, registry, path }) => { +const fetch = async ({ dependency, registry, path }): Promise<any> => { const json = true; const retry = { retries: retriable() }; diff --git a/lib/datasource/rubygems/retriable.ts b/lib/datasource/rubygems/retriable.ts index e6743aec84..11c79124b1 100644 --- a/lib/datasource/rubygems/retriable.ts +++ b/lib/datasource/rubygems/retriable.ts @@ -38,7 +38,7 @@ export type HTTPError = InstanceType<got.GotInstance['HTTPError']>; export default (numberOfRetries = NUMBER_OF_RETRIES): got.RetryFunction => ( _?: number, err?: Partial<HTTPError> -) => { +): number => { if (numberOfRetries === 0) { return 0; } diff --git a/lib/datasource/sbt/index.ts b/lib/datasource/sbt/index.ts index e0c8b18e7e..b028ca664e 100644 --- a/lib/datasource/sbt/index.ts +++ b/lib/datasource/sbt/index.ts @@ -12,7 +12,7 @@ async function resolvePackageReleases( const indexContent = await downloadHttpProtocol(searchRoot, 'sbt'); if (indexContent) { const releases: string[] = []; - const parseSubdirs = (content: string) => + const parseSubdirs = (content: string): string[] => parseIndexDir(content, x => { if (x === artifact) return true; if (x.indexOf(`${artifact}_native`) === 0) return false; @@ -27,7 +27,7 @@ async function resolvePackageReleases( ) { searchSubdirs = [`${artifact}_${scalaVersion}`]; } - const parseReleases = (content: string) => + const parseReleases = (content: string): string[] => parseIndexDir(content, x => !/^\.+$/.test(x)); for (const searchSubdir of searchSubdirs) { const content = await downloadHttpProtocol( @@ -49,9 +49,9 @@ async function resolvePluginReleases( rootUrl: string, artifact: string, scalaVersion: string -) { +): Promise<string[]> { const searchRoot = `${rootUrl}/${artifact}`; - const parse = (content: string) => + const parse = (content: string): string[] => parseIndexDir(content, x => !/^\.+$/.test(x)); const indexContent = await downloadHttpProtocol(searchRoot, 'sbt'); if (indexContent) { diff --git a/lib/datasource/sbt/util.ts b/lib/datasource/sbt/util.ts index 5a402d0baa..195d5c243a 100644 --- a/lib/datasource/sbt/util.ts +++ b/lib/datasource/sbt/util.ts @@ -3,8 +3,8 @@ export const SBT_PLUGINS_REPO = export function parseIndexDir( content: string, - filterFn = (x: string) => !/^\.+/.test(x) -) { + filterFn = (x: string): boolean => !/^\.+/.test(x) +): string[] { const unfiltered = content.match(/(?<=href=['"])[^'"]*(?=\/['"])/g) || []; return unfiltered.filter(filterFn); } diff --git a/lib/datasource/terraform/index.ts b/lib/datasource/terraform/index.ts index df9a91ba55..cc2e629494 100644 --- a/lib/datasource/terraform/index.ts +++ b/lib/datasource/terraform/index.ts @@ -4,7 +4,15 @@ import { logger } from '../../logger'; import got from '../../util/got'; import { PkgReleaseConfig, ReleaseResult } from '../common'; -function getRegistryRepository(lookupName: string, registryUrls: string[]) { +interface RegistryRepository { + registry: string; + repository: string; +} + +function getRegistryRepository( + lookupName: string, + registryUrls: string[] +): RegistryRepository { let registry: string; const split = lookupName.split('/'); if (split.length > 3 && split[0].includes('.')) { diff --git a/lib/logger/pretty-stdout.ts b/lib/logger/pretty-stdout.ts index f4becca043..8a2bd6190e 100644 --- a/lib/logger/pretty-stdout.ts +++ b/lib/logger/pretty-stdout.ts @@ -76,7 +76,7 @@ export function getDetails(rec: BunyanRecord): string { .join(',\n')}\n`; } -export function formatRecord(rec: BunyanRecord) { +export function formatRecord(rec: BunyanRecord): string { const level = levels[rec.level]; const msg = `${indent(rec.msg)}`; const meta = getMeta(rec); @@ -96,7 +96,7 @@ export class RenovateStream extends Stream { } // istanbul ignore next - write(data: BunyanRecord) { + write(data: BunyanRecord): boolean { this.emit('data', formatRecord(data)); return true; } diff --git a/lib/logger/utils.ts b/lib/logger/utils.ts index bdfc4cc5d1..abc8dc0211 100644 --- a/lib/logger/utils.ts +++ b/lib/logger/utils.ts @@ -24,19 +24,19 @@ export class ErrorStream extends Stream { this.writable = true; } - write(data: BunyanRecord) { + write(data: BunyanRecord): boolean { const err = { ...data }; for (const prop of excludeProps) delete err[prop]; this._errors.push(err); return true; } - getErrors() { + getErrors(): BunyanRecord[] { return this._errors; } } -function sanitizeValue(value: any, seen = new WeakMap()) { +function sanitizeValue(value: any, seen = new WeakMap()): any { if (Array.isArray(value)) { const length = value.length; const arrayResult = Array(length); @@ -76,7 +76,7 @@ export function withSanitizer(streamConfig): bunyan.Stream { const stream = streamConfig.stream; if (stream && stream.writable) { - const write = (chunk: BunyanRecord, enc, cb) => { + const write = (chunk: BunyanRecord, enc, cb): void => { const raw = sanitizeValue(chunk); const result = streamConfig.type === 'raw' diff --git a/lib/platform/azure/azure-got-wrapper.ts b/lib/platform/azure/azure-got-wrapper.ts index 3558cc1225..28167172dd 100644 --- a/lib/platform/azure/azure-got-wrapper.ts +++ b/lib/platform/azure/azure-got-wrapper.ts @@ -1,10 +1,13 @@ import * as azure from 'azure-devops-node-api'; +import { IGitApi } from 'azure-devops-node-api/GitApi'; +import { ICoreApi } from 'azure-devops-node-api/CoreApi'; +import { IPolicyApi } from 'azure-devops-node-api/PolicyApi'; import * as hostRules from '../../util/host-rules'; const hostType = 'azure'; let endpoint: string; -export function azureObj() { +export function azureObj(): azure.WebApi { const config = hostRules.find({ hostType, url: endpoint }); if (!(config && config.token)) { throw new Error(`No token found for azure`); @@ -13,18 +16,18 @@ export function azureObj() { return new azure.WebApi(endpoint, authHandler); } -export function gitApi() { +export function gitApi(): Promise<IGitApi> { return azureObj().getGitApi(); } -export function coreApi() { +export function coreApi(): Promise<ICoreApi> { return azureObj().getCoreApi(); } -export function policyApi() { +export function policyApi(): Promise<IPolicyApi> { return azureObj().getPolicyApi(); } -export function setEndpoint(e: string) { +export function setEndpoint(e: string): void { endpoint = e; } diff --git a/lib/platform/azure/azure-helper.ts b/lib/platform/azure/azure-helper.ts index 57f956aaf2..266e298896 100644 --- a/lib/platform/azure/azure-helper.ts +++ b/lib/platform/azure/azure-helper.ts @@ -1,18 +1,26 @@ -import { GitPullRequestMergeStrategy } from 'azure-devops-node-api/interfaces/GitInterfaces'; +import { + GitPullRequestMergeStrategy, + GitRef, + GitCommit, + GitPullRequest, +} from 'azure-devops-node-api/interfaces/GitInterfaces'; import * as azureApi from './azure-got-wrapper'; import { logger } from '../../logger'; +import { Pr } from '../common'; const mergePolicyGuid = 'fa4e907d-c16b-4a4c-9dfa-4916e5d171ab'; // Magic GUID for merge strategy policy configurations -export function getNewBranchName(branchName?: string) { +export function getNewBranchName(branchName?: string): string { if (branchName && !branchName.startsWith('refs/heads/')) { return `refs/heads/${branchName}`; } return branchName; } -export function getBranchNameWithoutRefsheadsPrefix(branchPath: string) { +export function getBranchNameWithoutRefsheadsPrefix( + branchPath: string +): string | undefined { if (!branchPath) { logger.error(`getBranchNameWithoutRefsheadsPrefix(${branchPath})`); return undefined; @@ -26,7 +34,9 @@ export function getBranchNameWithoutRefsheadsPrefix(branchPath: string) { return branchPath.substring(11, branchPath.length); } -function getBranchNameWithoutRefsPrefix(branchPath?: string) { +function getBranchNameWithoutRefsPrefix( + branchPath?: string +): string | undefined { if (!branchPath) { logger.error(`getBranchNameWithoutRefsPrefix(${branchPath})`); return undefined; @@ -40,7 +50,10 @@ function getBranchNameWithoutRefsPrefix(branchPath?: string) { return branchPath.substring(5, branchPath.length); } -export async function getRefs(repoId: string, branchName?: string) { +export async function getRefs( + repoId: string, + branchName?: string +): Promise<GitRef[]> { logger.debug(`getRefs(${repoId}, ${branchName})`); const azureApiGit = await azureApi.gitApi(); const refs = await azureApiGit.getRefs( @@ -51,11 +64,16 @@ export async function getRefs(repoId: string, branchName?: string) { return refs; } +export interface AzureBranchObj { + name: string; + oldObjectId: string; +} + export async function getAzureBranchObj( repoId: string, branchName: string, from?: string -) { +): Promise<AzureBranchObj> { const fromBranchName = getNewBranchName(from); const refs = await getRefs(repoId, fromBranchName); if (refs.length === 0) { @@ -71,7 +89,7 @@ export async function getAzureBranchObj( }; } -async function streamToString(stream: NodeJS.ReadableStream) { +async function streamToString(stream: NodeJS.ReadableStream): Promise<string> { const chunks: string[] = []; /* eslint-disable promise/avoid-new */ const p = await new Promise<string>(resolve => { @@ -90,7 +108,7 @@ export async function getFile( repoId: string, filePath: string, branchName: string -) { +): Promise<string | null> { logger.trace(`getFile(filePath=${filePath}, branchName=${branchName})`); const azureApiGit = await azureApi.gitApi(); const item = await azureApiGit.getItemText( @@ -129,50 +147,15 @@ export async function getFile( return null; // no file found } -export async function getChanges( - files: { name: string; contents: any }[], - repoId: string, - branchName: string -) { - const changes = []; - for (const file of files) { - // Add or update - let changeType = 1; - const fileAlreadyThere = await getFile(repoId, file.name, branchName); - if (fileAlreadyThere) { - changeType = 2; - } - - changes.push({ - changeType, - item: { - path: file.name, - }, - newContent: { - Content: file.contents, - ContentType: 0, // RawText - }, - }); - } - - return changes; -} - -export function max4000Chars(str: string) { +export function max4000Chars(str: string): string { if (str && str.length >= 4000) { return str.substring(0, 3999); } return str; } -export function getRenovatePRFormat(azurePr: { - pullRequestId: any; - description: any; - status: number; - mergeStatus: number; - targetRefName: string; -}) { - const pr = azurePr as any; +export function getRenovatePRFormat(azurePr: GitPullRequest): Pr { + const pr: Pr = azurePr as any; pr.displayNumber = `Pull Request #${azurePr.pullRequestId}`; pr.number = azurePr.pullRequestId; @@ -213,14 +196,19 @@ export function getRenovatePRFormat(azurePr: { return pr; } -export async function getCommitDetails(commit: string, repoId: string) { +export async function getCommitDetails( + commit: string, + repoId: string +): Promise<GitCommit> { logger.debug(`getCommitDetails(${commit}, ${repoId})`); const azureApiGit = await azureApi.gitApi(); const results = await azureApiGit.getCommit(commit, repoId); return results; } -export function getProjectAndRepo(str: string) { +export function getProjectAndRepo( + str: string +): { project: string; repo: string } { logger.trace(`getProjectAndRepo(${str})`); const strSplited = str.split(`/`); if (strSplited.length === 1) { diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts index 1f3ff34a64..57f6226219 100644 --- a/lib/platform/azure/index.ts +++ b/lib/platform/azure/index.ts @@ -4,9 +4,16 @@ import * as azureHelper from './azure-helper'; import * as azureApi from './azure-got-wrapper'; import * as hostRules from '../../util/host-rules'; import { appSlug } from '../../config/app-strings'; -import GitStorage from '../git/storage'; +import GitStorage, { StatusResult, File } from '../git/storage'; import { logger } from '../../logger'; -import { PlatformConfig, RepoParams, RepoConfig } from '../common'; +import { + PlatformConfig, + RepoParams, + RepoConfig, + Pr, + Issue, + VulnerabilityAlert, +} from '../common'; import { sanitize } from '../../util/sanitize'; import { smartTruncate } from '../utils/pr-body'; @@ -37,7 +44,7 @@ export function initPlatform({ }: { endpoint: string; token: string; -}) { +}): PlatformConfig { if (!endpoint) { throw new Error('Init: You must configure an Azure DevOps endpoint'); } @@ -56,14 +63,14 @@ export function initPlatform({ return platformConfig; } -export async function getRepos() { +export async function getRepos(): Promise<string[]> { logger.info('Autodiscovering Azure DevOps repositories'); const azureApiGit = await azureApi.gitApi(); const repos = await azureApiGit.getRepositories(); return repos.map(repo => `${repo.project!.name}/${repo.name}`); } -async function getBranchCommit(fullBranchName: string) { +async function getBranchCommit(fullBranchName: string): Promise<string> { const azureApiGit = await azureApi.gitApi(); const commit = await azureApiGit.getBranch( config.repoId, @@ -77,7 +84,7 @@ export async function initRepo({ localDir, azureWorkItemId, optimizeForDisabled, -}: RepoParams) { +}: RepoParams): Promise<RepoConfig> { logger.debug(`initRepo("${repository}")`); config = { repository, azureWorkItemId } as any; const azureApiGit = await azureApi.gitApi(); @@ -141,19 +148,21 @@ export async function initRepo({ return repoConfig; } -export function getRepoForceRebase() { +export function getRepoForceRebase(): boolean { return false; } // Search -export /* istanbul ignore next */ function getFileList(branchName: string) { +export /* istanbul ignore next */ function getFileList( + branchName: string +): Promise<string[]> { return config.storage.getFileList(branchName); } export /* istanbul ignore next */ async function setBaseBranch( branchName = config.baseBranch -) { +): Promise<void> { logger.debug(`Setting baseBranch to ${branchName}`); config.baseBranch = branchName; delete config.baseCommitSHA; @@ -164,35 +173,39 @@ export /* istanbul ignore next */ async function setBaseBranch( export /* istanbul ignore next */ function setBranchPrefix( branchPrefix: string -) { +): Promise<void> { return config.storage.setBranchPrefix(branchPrefix); } // Branch -export /* istanbul ignore next */ function branchExists(branchName: string) { +export /* istanbul ignore next */ function branchExists( + branchName: string +): Promise<boolean> { return config.storage.branchExists(branchName); } export /* istanbul ignore next */ function getAllRenovateBranches( branchPrefix: string -) { +): Promise<string[]> { return config.storage.getAllRenovateBranches(branchPrefix); } -export /* istanbul ignore next */ function isBranchStale(branchName: string) { +export /* istanbul ignore next */ function isBranchStale( + branchName: string +): Promise<boolean> { return config.storage.isBranchStale(branchName); } export /* istanbul ignore next */ function getFile( filePath: string, branchName: string -) { +): Promise<string> { return config.storage.getFile(filePath, branchName); } // istanbul ignore next -async function abandonPr(prNo: number) { +async function abandonPr(prNo: number): Promise<void> { logger.debug(`abandonPr(prNo)(${prNo})`); const azureApiGit = await azureApi.gitApi(); await azureApiGit.updatePullRequest( @@ -204,7 +217,7 @@ async function abandonPr(prNo: number) { ); } -export async function getPr(pullRequestId: number) { +export async function getPr(pullRequestId: number): Promise<Pr | null> { logger.debug(`getPr(${pullRequestId})`); if (!pullRequestId) { return null; @@ -231,8 +244,9 @@ export async function findPr( branchName: string, prTitle: string | null, state = 'all' -) { +): Promise<Pr | null> { logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`); + // TODO: fix typing let prsFiltered: any[] = []; try { const azureApiGit = await azureApi.gitApi(); @@ -271,7 +285,7 @@ export async function findPr( return prsFiltered[0]; } -export async function getBranchPr(branchName: string) { +export async function getBranchPr(branchName: string): Promise<Pr | null> { logger.debug(`getBranchPr(${branchName})`); const existingPr = await findPr(branchName, null, 'open'); return existingPr ? getPr(existingPr.pullRequestId) : null; @@ -280,7 +294,7 @@ export async function getBranchPr(branchName: string) { export /* istanbul ignore next */ async function deleteBranch( branchName: string, abandonAssociatedPr = false -) { +): Promise<void> { await config.storage.deleteBranch(branchName); if (abandonAssociatedPr) { const pr = await getBranchPr(branchName); @@ -290,24 +304,28 @@ export /* istanbul ignore next */ async function deleteBranch( export /* istanbul ignore next */ function getBranchLastCommitTime( branchName: string -) { +): Promise<Date> { return config.storage.getBranchLastCommitTime(branchName); } -export /* istanbul ignore next */ function getRepoStatus() { +export /* istanbul ignore next */ function getRepoStatus(): Promise< + StatusResult +> { return config.storage.getRepoStatus(); } -export /* istanbul ignore next */ function mergeBranch(branchName: string) { +export /* istanbul ignore next */ function mergeBranch( + branchName: string +): Promise<void> { return config.storage.mergeBranch(branchName); } export /* istanbul ignore next */ function commitFilesToBranch( branchName: string, - files: any[], + files: File[], message: string, parentBranch = config.baseBranch -) { +): Promise<void> { return config.storage.commitFilesToBranch( branchName, files, @@ -316,18 +334,20 @@ export /* istanbul ignore next */ function commitFilesToBranch( ); } -export /* istanbul ignore next */ function getCommitMessages() { +export /* istanbul ignore next */ function getCommitMessages(): Promise< + string[] +> { return config.storage.getCommitMessages(); } -export function getPrList() { +export function getPrList(): Pr[] { return []; } export async function getBranchStatusCheck( branchName: string, context?: string -) { +): Promise<string> { logger.trace(`getBranchStatusCheck(${branchName}, ${context})`); const azureApiGit = await azureApi.gitApi(); const branch = await azureApiGit.getBranch( @@ -343,7 +363,7 @@ export async function getBranchStatusCheck( export async function getBranchStatus( branchName: string, requiredStatusChecks: any -) { +): Promise<string> { logger.debug(`getBranchStatus(${branchName})`); if (!requiredStatusChecks) { // null means disable status checks, so it always succeeds @@ -365,7 +385,7 @@ export async function createPr( labels: string[], useDefaultBranch?: boolean, platformOptions: any = {} -) { +): Promise<Pr> { const sourceRefName = azureHelper.getNewBranchName(branchName); const targetRefName = azureHelper.getNewBranchName( useDefaultBranch ? config.defaultBranch : config.baseBranch @@ -402,6 +422,7 @@ export async function createPr( pr.pullRequestId! ); } + // TODO: fixme await labels.forEach(async label => { await azureApiGit.createPullRequestLabel( { @@ -415,7 +436,11 @@ export async function createPr( return azureHelper.getRenovatePRFormat(pr); } -export async function updatePr(prNo: number, title: string, body?: string) { +export async function updatePr( + prNo: number, + title: string, + body?: string +): Promise<void> { logger.debug(`updatePr(${prNo}, ${title}, body)`); const azureApiGit = await azureApi.gitApi(); const objToUpdate: any = { @@ -431,7 +456,7 @@ export async function ensureComment( issueNo: number, topic: string | null, content: string -) { +): Promise<void> { logger.debug(`ensureComment(${issueNo}, ${topic}, content)`); const body = `### ${topic}\n\n${sanitize(content)}`; const azureApiGit = await azureApi.gitApi(); @@ -445,7 +470,10 @@ export async function ensureComment( ); } -export async function ensureCommentRemoval(issueNo: number, topic: string) { +export async function ensureCommentRemoval( + issueNo: number, + topic: string +): Promise<void> { logger.debug(`ensureCommentRemoval(issueNo, topic)(${issueNo}, ${topic})`); if (issueNo) { const azureApiGit = await azureApi.gitApi(); @@ -477,18 +505,18 @@ export function setBranchStatus( description: string, state: string, targetUrl: string -) { +): void { logger.debug( `setBranchStatus(${branchName}, ${context}, ${description}, ${state}, ${targetUrl}) - Not supported by Azure DevOps (yet!)` ); } -export async function mergePr(pr: number) { +export async function mergePr(pr: number): Promise<void> { logger.info(`mergePr(pr)(${pr}) - Not supported by Azure DevOps (yet!)`); await null; } -export function getPrBody(input: string) { +export function getPrBody(input: string): string { // Remove any HTML we use return smartTruncate(input, 4000) .replace(new RegExp(`\n---\n\n.*?<!-- ${appSlug}-rebase -->.*?\n`), '') @@ -498,18 +526,19 @@ export function getPrBody(input: string) { .replace('</details>', ''); } -export /* istanbul ignore next */ function findIssue() { +export /* istanbul ignore next */ function findIssue(): Issue | null { logger.warn(`findIssue() is not implemented`); + return null; } -export /* istanbul ignore next */ function ensureIssue() { +export /* istanbul ignore next */ function ensureIssue(): void { logger.warn(`ensureIssue() is not implemented`); } // eslint-disable-next-line @typescript-eslint/no-empty-function -export /* istanbul ignore next */ function ensureIssueClosing() {} +export /* istanbul ignore next */ function ensureIssueClosing(): void {} -export /* istanbul ignore next */ function getIssueList() { +export /* istanbul ignore next */ function getIssueList(): Issue[] { logger.debug(`getIssueList()`); // TODO: Needs implementation return []; @@ -520,7 +549,10 @@ export /* istanbul ignore next */ function getIssueList() { * @param {number} issueNo * @param {string[]} assignees */ -export async function addAssignees(issueNo: number, assignees: string[]) { +export async function addAssignees( + issueNo: number, + assignees: string[] +): Promise<void> { logger.trace(`addAssignees(${issueNo}, ${assignees})`); await ensureComment( issueNo, @@ -534,7 +566,10 @@ export async function addAssignees(issueNo: number, assignees: string[]) { * @param {number} prNo * @param {string[]} reviewers */ -export async function addReviewers(prNo: number, reviewers: string[]) { +export async function addReviewers( + prNo: number, + reviewers: string[] +): Promise<void> { logger.trace(`addReviewers(${prNo}, ${reviewers})`); const azureApiGit = await azureApi.gitApi(); const azureApiCore = await azureApi.coreApi(); @@ -594,25 +629,25 @@ export async function addReviewers(prNo: number, reviewers: string[]) { export /* istanbul ignore next */ async function deleteLabel( prNumber: number, label: string -) { +): Promise<void> { logger.debug(`Deleting label ${label} from #${prNumber}`); const azureApiGit = await azureApi.gitApi(); await azureApiGit.deletePullRequestLabels(config.repoId, prNumber, label); } // to become async? -export function getPrFiles(prNo: number) { +export function getPrFiles(prNo: number): string[] { logger.info( `getPrFiles(prNo)(${prNo}) - Not supported by Azure DevOps (yet!)` ); return []; } -export function getVulnerabilityAlerts() { +export function getVulnerabilityAlerts(): VulnerabilityAlert[] { return []; } -export function cleanRepo() { +export function cleanRepo(): void { // istanbul ignore if if (config.storage && config.storage.cleanRepo) { config.storage.cleanRepo(); diff --git a/lib/platform/bitbucket-server/bb-got-wrapper.ts b/lib/platform/bitbucket-server/bb-got-wrapper.ts index 5f1188ff0a..dc2ee77e23 100644 --- a/lib/platform/bitbucket-server/bb-got-wrapper.ts +++ b/lib/platform/bitbucket-server/bb-got-wrapper.ts @@ -1,11 +1,14 @@ import URL from 'url'; import { GotJSONOptions } from 'got'; import got from '../../util/got'; -import { GotApi, GotApiOptions } from '../common'; +import { GotApi, GotApiOptions, GotResponse } from '../common'; let baseUrl: string; -function get(path: string, options: GotApiOptions & GotJSONOptions) { +function get( + path: string, + options: GotApiOptions & GotJSONOptions +): Promise<GotResponse> { const url = URL.resolve(baseUrl, path); const opts: GotApiOptions & GotJSONOptions = { hostType: 'bitbucket-server', @@ -24,11 +27,11 @@ const helpers = ['get', 'post', 'put', 'patch', 'head', 'delete']; export const api: GotApi = {} as any; for (const x of helpers) { - (api as any)[x] = (url: string, opts: any) => + (api as any)[x] = (url: string, opts: any): Promise<GotResponse> => get(url, Object.assign({}, opts, { method: x.toUpperCase() })); } -api.setBaseUrl = (e: string) => { +api.setBaseUrl = (e: string): void => { baseUrl = e; }; diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts index 5d8cd1efa3..b71655f88f 100644 --- a/lib/platform/bitbucket-server/index.ts +++ b/lib/platform/bitbucket-server/index.ts @@ -4,9 +4,17 @@ import delay from 'delay'; import { api } from './bb-got-wrapper'; import * as utils from './utils'; import * as hostRules from '../../util/host-rules'; -import GitStorage from '../git/storage'; +import GitStorage, { File, StatusResult } from '../git/storage'; import { logger } from '../../logger'; -import { PlatformConfig, RepoParams, RepoConfig } from '../common'; +import { + PlatformConfig, + RepoParams, + RepoConfig, + Pr, + Issue, + VulnerabilityAlert, + GotResponse, +} from '../common'; import { sanitize } from '../../util/sanitize'; import { smartTruncate } from '../utils/pr-body'; @@ -27,7 +35,7 @@ interface BbsConfig { fileList: any[]; mergeMethod: string; owner: string; - prList: any[]; + prList: Pr[]; projectKey: string; repository: string; repositorySlug: string; @@ -45,7 +53,7 @@ const defaults: any = { }; /* istanbul ignore next */ -function updatePrVersion(pr: number, version: number) { +function updatePrVersion(pr: number, version: number): number { const res = Math.max(config.prVersions.get(pr) || 0, version); config.prVersions.set(pr, res); return res; @@ -59,7 +67,7 @@ export function initPlatform({ endpoint: string; username: string; password: string; -}) { +}): PlatformConfig { if (!endpoint) { throw new Error('Init: You must configure a Bitbucket Server endpoint'); } @@ -78,7 +86,7 @@ export function initPlatform({ } // Get all repositories that the user has access to -export async function getRepos() { +export async function getRepos(): Promise<string[]> { logger.info('Autodiscovering Bitbucket Server repositories'); try { const repos = await utils.accumulateValues( @@ -96,7 +104,7 @@ export async function getRepos() { } } -export function cleanRepo() { +export function cleanRepo(): void { logger.debug(`cleanRepo()`); if (config.storage) { config.storage.cleanRepo(); @@ -111,7 +119,7 @@ export async function initRepo({ localDir, optimizeForDisabled, bbUseDefaultReviewers, -}: RepoParams) { +}: RepoParams): Promise<RepoConfig> { logger.debug( `initRepo("${JSON.stringify({ repository, localDir }, null, 2)}")` ); @@ -208,7 +216,7 @@ export async function initRepo({ } } -export function getRepoForceRebase() { +export function getRepoForceRebase(): boolean { 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 @@ -217,21 +225,25 @@ export function getRepoForceRebase() { return false; } -export async function setBaseBranch(branchName: string = config.defaultBranch) { +export async function setBaseBranch( + branchName: string = config.defaultBranch +): Promise<void> { config.baseBranch = branchName; await config.storage.setBaseBranch(branchName); } export /* istanbul ignore next */ function setBranchPrefix( branchPrefix: string -) { +): Promise<void> { return config.storage.setBranchPrefix(branchPrefix); } // Search // Get full file list -export function getFileList(branchName: string = config.baseBranch) { +export function getFileList( + branchName: string = config.baseBranch +): Promise<string[]> { logger.debug(`getFileList(${branchName})`); return config.storage.getFileList(branchName); } @@ -239,18 +251,21 @@ export function getFileList(branchName: string = config.baseBranch) { // Branch // Returns true if branch exists, otherwise false -export function branchExists(branchName: string) { +export function branchExists(branchName: string): Promise<boolean> { logger.debug(`branchExists(${branchName})`); return config.storage.branchExists(branchName); } -export function isBranchStale(branchName: string) { +export function isBranchStale(branchName: string): Promise<boolean> { logger.debug(`isBranchStale(${branchName})`); return config.storage.isBranchStale(branchName); } // Gets details for a PR -export async function getPr(prNo: number, refreshCache?: boolean) { +export async function getPr( + prNo: number, + refreshCache?: boolean +): Promise<Pr | null> { logger.debug(`getPr(${prNo})`); if (!prNo) { return null; @@ -314,7 +329,7 @@ export async function getPr(prNo: number, refreshCache?: boolean) { // TODO: coverage // istanbul ignore next -function matchesState(state: string, desiredState: string) { +function matchesState(state: string, desiredState: string): boolean { if (desiredState === 'all') { return true; } @@ -330,14 +345,14 @@ const isRelevantPr = ( branchName: string, prTitle: string | null | undefined, state: string -) => (p: { branchName: string; title: string; state: string }) => +) => (p: Pr): boolean => p.branchName === branchName && (!prTitle || p.title === prTitle) && matchesState(p.state, state); // TODO: coverage // eslint-disable-next-line @typescript-eslint/no-unused-vars -export async function getPrList(_args?: any) { +export async function getPrList(_args?: any): Promise<Pr[]> { logger.debug(`getPrList()`); // istanbul ignore next if (!config.prList) { @@ -365,7 +380,7 @@ export async function findPr( prTitle?: string, state = 'all', refreshCache?: boolean -) { +): Promise<Pr | null> { logger.debug(`findPr(${branchName}, "${prTitle}", "${state}")`); const prList = await getPrList({ refreshCache }); const pr = prList.find(isRelevantPr(branchName, prTitle, state)); @@ -378,23 +393,28 @@ export async function findPr( } // Returns the Pull Request for a branch. Null if not exists. -export async function getBranchPr(branchName: string, refreshCache?: boolean) { +export async function getBranchPr( + branchName: string, + refreshCache?: boolean +): Promise<Pr | null> { logger.debug(`getBranchPr(${branchName})`); const existingPr = await findPr(branchName, undefined, 'open'); return existingPr ? getPr(existingPr.number, refreshCache) : null; } -export function getAllRenovateBranches(branchPrefix: string) { +export function getAllRenovateBranches( + branchPrefix: string +): Promise<string[]> { logger.debug('getAllRenovateBranches'); return config.storage.getAllRenovateBranches(branchPrefix); } export async function commitFilesToBranch( branchName: string, - files: any[], + files: File[], message: string, parentBranch: string = config.baseBranch -) { +): Promise<void> { logger.debug( `commitFilesToBranch(${JSON.stringify( { branchName, filesLength: files.length, message, parentBranch }, @@ -415,12 +435,15 @@ export async function commitFilesToBranch( await getBranchPr(branchName, true); } -export function getFile(filePath: string, branchName: string) { +export function getFile(filePath: string, branchName: string): Promise<string> { logger.debug(`getFile(${filePath}, ${branchName})`); return config.storage.getFile(filePath, branchName); } -export async function deleteBranch(branchName: string, closePr = false) { +export async function deleteBranch( + branchName: string, + closePr = false +): Promise<void> { logger.debug(`deleteBranch(${branchName}, closePr=${closePr})`); // TODO: coverage // istanbul ignore next @@ -428,27 +451,29 @@ export async function deleteBranch(branchName: string, closePr = false) { // getBranchPr const pr = await getBranchPr(branchName); if (pr) { - const { body } = await api.post( + const { body } = await api.post<{ version: number }>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests/${pr.number}/decline?version=${pr.version}` ); - updatePrVersion(pr, body); + updatePrVersion(pr.number, body.version); } } return config.storage.deleteBranch(branchName); } -export function mergeBranch(branchName: string) { +export function mergeBranch(branchName: string): Promise<void> { logger.debug(`mergeBranch(${branchName})`); return config.storage.mergeBranch(branchName); } -export function getBranchLastCommitTime(branchName: string) { +export function getBranchLastCommitTime(branchName: string): Promise<Date> { logger.debug(`getBranchLastCommitTime(${branchName})`); return config.storage.getBranchLastCommitTime(branchName); } -export /* istanbul ignore next */ function getRepoStatus() { +export /* istanbul ignore next */ function getRepoStatus(): Promise< + StatusResult +> { return config.storage.getRepoStatus(); } @@ -458,7 +483,7 @@ export /* istanbul ignore next */ function getRepoStatus() { export async function getBranchStatus( branchName: string, requiredStatusChecks?: string[] | boolean | null -) { +): Promise<string> { logger.debug( `getBranchStatus(${branchName}, requiredStatusChecks=${!!requiredStatusChecks})` ); @@ -495,7 +520,7 @@ export async function getBranchStatus( export async function getBranchStatusCheck( branchName: string, context: string -) { +): Promise<string | null> { logger.debug(`getBranchStatusCheck(${branchName}, context=${context})`); const branchCommit = await config.storage.getBranchCommit(branchName); @@ -530,7 +555,7 @@ export async function setBranchStatus( description: string, state: string | null, targetUrl?: string -) { +): Promise<void> { logger.debug(`setBranchStatus(${branchName})`); const existingStatus = await getBranchStatusCheck(branchName, context); @@ -577,7 +602,9 @@ export async function setBranchStatus( // return []; // } -export /* istanbul ignore next */ function findIssue(title: string) { +export /* istanbul ignore next */ function findIssue( + title: string +): Issue | null { 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" @@ -588,7 +615,7 @@ export /* istanbul ignore next */ function findIssue(title: string) { export /* istanbul ignore next */ function ensureIssue( title: string, body: string -) { +): Promise<'updated' | 'created' | null> { logger.warn({ title }, 'Cannot ensure issue'); // TODO: Needs implementation // This is used by Renovate when creating its own issues, e.g. for deprecated package warnings, config error notifications, or "masterIssue" @@ -596,13 +623,15 @@ export /* istanbul ignore next */ function ensureIssue( return null; } -export /* istanbul ignore next */ function getIssueList() { +export /* istanbul ignore next */ function getIssueList(): Issue[] { logger.debug(`getIssueList()`); // TODO: Needs implementation return []; } -export /* istanbul ignore next */ function ensureIssueClosing(title: string) { +export /* istanbul ignore next */ function ensureIssueClosing( + title: string +): void { 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" @@ -610,14 +639,17 @@ export /* istanbul ignore next */ function ensureIssueClosing(title: string) { } // eslint-disable-next-line no-unused-vars -export function addAssignees(iid: number, assignees: string[]) { +export function addAssignees(iid: number, assignees: string[]): void { 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 } -export async function addReviewers(prNo: number, reviewers: string[]) { +export async function addReviewers( + prNo: number, + reviewers: string[] +): Promise<void> { logger.debug(`Adding reviewers ${reviewers} to #${prNo}`); try { @@ -653,13 +685,15 @@ export async function addReviewers(prNo: number, reviewers: string[]) { } // eslint-disable-next-line no-unused-vars -export function deleteLabel(issueNo: number, label: string) { +export function deleteLabel(issueNo: number, label: string): void { 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: number) { +type Comment = { text: string; id: number }; + +async function getComments(prNo: number): Promise<Comment[]> { // 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/${config.repositorySlug}/pull-requests/${prNo}/activities` @@ -670,14 +704,14 @@ async function getComments(prNo: number) { (a: { action: string; commentAction: string }) => a.action === 'COMMENTED' && a.commentAction === 'ADDED' ) - .map((a: { comment: string }) => a.comment); + .map((a: { comment: Comment }) => a.comment); logger.debug(`Found ${comments.length} comments`); return comments; } -async function addComment(prNo: number, text: string) { +async function addComment(prNo: number, text: string): Promise<void> { // POST /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments await api.post( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests/${prNo}/comments`, @@ -687,7 +721,10 @@ async function addComment(prNo: number, text: string) { ); } -async function getCommentVersion(prNo: number, commentId: number) { +async function getCommentVersion( + prNo: number, + commentId: number +): Promise<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/${config.repositorySlug}/pull-requests/${prNo}/comments/${commentId}` @@ -696,7 +733,11 @@ async function getCommentVersion(prNo: number, commentId: number) { return version; } -async function editComment(prNo: number, commentId: number, text: string) { +async function editComment( + prNo: number, + commentId: number, + text: string +): Promise<void> { const version = await getCommentVersion(prNo, commentId); // PUT /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId} @@ -708,7 +749,7 @@ async function editComment(prNo: number, commentId: number, text: string) { ); } -async function deleteComment(prNo: number, commentId: number) { +async function deleteComment(prNo: number, commentId: number): Promise<void> { const version = await getCommentVersion(prNo, commentId); // DELETE /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId} @@ -721,7 +762,7 @@ export async function ensureComment( prNo: number, topic: string | null, rawContent: string -) { +): Promise<boolean> { const content = sanitize(rawContent); try { const comments = await getComments(prNo); @@ -731,7 +772,7 @@ export async function ensureComment( if (topic) { logger.debug(`Ensuring comment "${topic}" in #${prNo}`); body = `### ${topic}\n\n${content}`; - comments.forEach((comment: { text: string; id: number }) => { + comments.forEach(comment => { if (comment.text.startsWith(`### ${topic}\n\n`)) { commentId = comment.id; commentNeedsUpdating = comment.text !== body; @@ -740,7 +781,7 @@ export async function ensureComment( } else { logger.debug(`Ensuring content-only comment in #${prNo}`); body = `${content}`; - comments.forEach((comment: { text: string; id: number }) => { + comments.forEach(comment => { if (comment.text === body) { commentId = comment.id; commentNeedsUpdating = false; @@ -766,12 +807,15 @@ export async function ensureComment( } } -export async function ensureCommentRemoval(prNo: number, topic: string) { +export async function ensureCommentRemoval( + prNo: number, + topic: string +): Promise<void> { try { logger.debug(`Ensuring comment "${topic}" in #${prNo} is removed`); const comments = await getComments(prNo); - let commentId; - comments.forEach((comment: { text: string; id: any }) => { + let commentId: number; + comments.forEach(comment => { if (comment.text.startsWith(`### ${topic}\n\n`)) { commentId = comment.id; } @@ -786,7 +830,8 @@ export async function ensureCommentRemoval(prNo: number, topic: string) { // Pull Request -const escapeHash = input => (input ? input.replace(/#/g, '%23') : input); +const escapeHash = (input: string): string => + input ? input.replace(/#/g, '%23') : input; export async function createPr( branchName: string, @@ -794,7 +839,7 @@ export async function createPr( rawDescription: string, _labels?: string[] | null, useDefaultBranch?: boolean -) { +): Promise<Pr> { const description = sanitize(rawDescription); logger.debug(`createPr(${branchName}, title=${title})`); const base = useDefaultBranch ? config.defaultBranch : config.baseBranch; @@ -831,7 +876,7 @@ export async function createPr( }, reviewers, }; - let prInfoRes; + let prInfoRes: GotResponse; try { prInfoRes = await api.post( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests`, @@ -854,7 +899,7 @@ export async function createPr( throw err; } - const pr = { + const pr: Pr = { id: prInfoRes.body.id, displayNumber: `Pull Request #${prInfoRes.body.id}`, isModified: false, @@ -873,24 +918,24 @@ export async function createPr( // Return a list of all modified files in a PR // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html -export async function getPrFiles(prNo: number) { +export async function getPrFiles(prNo: number): Promise<string[]> { logger.debug(`getPrFiles(${prNo})`); if (!prNo) { return []; } // GET /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/changes - const values = await utils.accumulateValues( + const values = await utils.accumulateValues<{ path: { toString: string } }>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests/${prNo}/changes?withComments=false` ); - return values.map((f: { path: string }) => f.path.toString); + return values.map(f => f.path.toString); } export async function updatePr( prNo: number, title: string, rawDescription: string -) { +): Promise<void> { const description = sanitize(rawDescription); logger.debug(`updatePr(${prNo}, title=${title})`); @@ -900,7 +945,7 @@ export async function updatePr( throw Object.assign(new Error('not-found'), { statusCode: 404 }); } - const { body } = await api.put( + const { body } = await api.put<{ version: number }>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests/${prNo}`, { body: { @@ -926,7 +971,10 @@ export async function updatePr( } // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html#idp261 -export async function mergePr(prNo: number, branchName: string) { +export async function mergePr( + prNo: number, + branchName: string +): Promise<boolean> { logger.debug(`mergePr(${prNo}, ${branchName})`); // Used for "automerge" feature try { @@ -934,7 +982,7 @@ export async function mergePr(prNo: number, branchName: string) { if (!pr) { throw Object.assign(new Error('not-found'), { statusCode: 404 }); } - const { body } = await api.post( + const { body } = await api.post<{ version: number }>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests/${prNo}/merge?version=${pr.version}` ); updatePrVersion(prNo, body.version); @@ -956,7 +1004,7 @@ export async function mergePr(prNo: number, branchName: string) { return true; } -export function getPrBody(input: string) { +export function getPrBody(input: string): string { logger.debug(`getPrBody(${input.split('\n')[0]})`); // Remove any HTML we use return smartTruncate(input, 30000) @@ -966,12 +1014,12 @@ export function getPrBody(input: string) { .replace(new RegExp('<!--.*?-->', 'g'), ''); } -export function getCommitMessages() { +export function getCommitMessages(): Promise<string[]> { logger.debug(`getCommitMessages()`); return config.storage.getCommitMessages(); } -export function getVulnerabilityAlerts() { +export function getVulnerabilityAlerts(): VulnerabilityAlert[] { logger.debug(`getVulnerabilityAlerts()`); return []; } diff --git a/lib/platform/bitbucket-server/utils.ts b/lib/platform/bitbucket-server/utils.ts index b77e41e3b9..cb33fe0e56 100644 --- a/lib/platform/bitbucket-server/utils.ts +++ b/lib/platform/bitbucket-server/utils.ts @@ -1,6 +1,7 @@ // SEE for the reference https://github.com/renovatebot/renovate/blob/c3e9e572b225085448d94aa121c7ec81c14d3955/lib/platform/bitbucket/utils.js import url from 'url'; import { api } from './bb-got-wrapper'; +import { Pr } from '../common'; // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html#idp250 const prStateMapping: any = { @@ -9,7 +10,7 @@ const prStateMapping: any = { OPEN: 'open', }; -export function prInfo(pr: any) { +export function prInfo(pr: any): Pr { return { version: pr.version, number: pr.id, @@ -23,7 +24,7 @@ export function prInfo(pr: any) { }; } -const addMaxLength = (inputUrl: string, limit = 100) => { +const addMaxLength = (inputUrl: string, limit = 100): string => { const { search, ...parsedUrl } = url.parse(inputUrl, true); // eslint-disable-line @typescript-eslint/no-unused-vars const maxedUrl = url.format({ ...parsedUrl, @@ -32,13 +33,13 @@ const addMaxLength = (inputUrl: string, limit = 100) => { return maxedUrl; }; -export async function accumulateValues( +export async function accumulateValues<T = any>( reqUrl: string, method = 'get', options?: any, limit?: number -) { - let accumulator: any = []; +): Promise<T[]> { + let accumulator: T[] = []; let nextUrl = addMaxLength(reqUrl, limit); const lowerCaseMethod = method.toLocaleLowerCase(); diff --git a/lib/platform/bitbucket/bb-got-wrapper.ts b/lib/platform/bitbucket/bb-got-wrapper.ts index 27aa0a2879..0c54eddcc6 100644 --- a/lib/platform/bitbucket/bb-got-wrapper.ts +++ b/lib/platform/bitbucket/bb-got-wrapper.ts @@ -1,8 +1,11 @@ import { GotJSONOptions } from 'got'; import got from '../../util/got'; -import { GotApi, GotApiOptions } from '../common'; +import { GotApi, GotApiOptions, GotResponse } from '../common'; -async function get(path: string, options: GotApiOptions & GotJSONOptions) { +async function get( + path: string, + options: GotApiOptions & GotJSONOptions +): Promise<GotResponse> { const opts: GotApiOptions & GotJSONOptions = { json: true, hostType: 'bitbucket', @@ -18,7 +21,7 @@ const helpers = ['get', 'post', 'put', 'patch', 'head', 'delete']; export const api: GotApi = {} as any; for (const x of helpers) { - (api as any)[x] = (url: string, opts: any) => + (api as any)[x] = (url: string, opts: any): Promise<GotResponse> => get(url, Object.assign({}, opts, { method: x.toUpperCase() })); } diff --git a/lib/platform/bitbucket/comments.ts b/lib/platform/bitbucket/comments.ts index 8c3b900ea8..51cfd78ce9 100644 --- a/lib/platform/bitbucket/comments.ts +++ b/lib/platform/bitbucket/comments.ts @@ -9,7 +9,10 @@ interface Comment { export type CommentsConfig = Pick<Config, 'repository'>; -async function getComments(config: CommentsConfig, prNo: number) { +async function getComments( + config: CommentsConfig, + prNo: number +): Promise<Comment[]> { const comments = await accumulateValues<Comment>( `/2.0/repositories/${config.repository}/pullrequests/${prNo}/comments` ); @@ -18,7 +21,11 @@ async function getComments(config: CommentsConfig, prNo: number) { return comments; } -async function addComment(config: CommentsConfig, prNo: number, raw: string) { +async function addComment( + config: CommentsConfig, + prNo: number, + raw: string +): Promise<void> { await api.post( `/2.0/repositories/${config.repository}/pullrequests/${prNo}/comments`, { @@ -32,7 +39,7 @@ async function editComment( prNo: number, commentId: number, raw: string -) { +): Promise<void> { await api.put( `/2.0/repositories/${config.repository}/pullrequests/${prNo}/comments/${commentId}`, { @@ -45,7 +52,7 @@ async function deleteComment( config: CommentsConfig, prNo: number, commentId: number -) { +): Promise<void> { await api.delete( `/2.0/repositories/${config.repository}/pullrequests/${prNo}/comments/${commentId}` ); @@ -56,7 +63,7 @@ export async function ensureComment( prNo: number, topic: string | null, content: string -) { +): Promise<boolean> { try { const comments = await getComments(config, prNo); let body: string; @@ -104,11 +111,11 @@ export async function ensureCommentRemoval( config: CommentsConfig, prNo: number, topic: string -) { +): Promise<void> { try { logger.debug(`Ensuring comment "${topic}" in #${prNo} is removed`); const comments = await getComments(config, prNo); - let commentId; + let commentId: number; comments.forEach(comment => { if (comment.content.raw.startsWith(`### ${topic}\n\n`)) { commentId = comment.id; diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts index 1b484c6904..b467a32c41 100644 --- a/lib/platform/bitbucket/index.ts +++ b/lib/platform/bitbucket/index.ts @@ -4,11 +4,18 @@ import { api } from './bb-got-wrapper'; import * as utils from './utils'; import * as hostRules from '../../util/host-rules'; import { logger } from '../../logger'; -import GitStorage from '../git/storage'; +import GitStorage, { StatusResult, File } from '../git/storage'; import { readOnlyIssueBody } from '../utils/read-only-issue-body'; import { appSlug } from '../../config/app-strings'; import * as comments from './comments'; -import { PlatformConfig, RepoParams, RepoConfig } from '../common'; +import { + PlatformConfig, + RepoParams, + RepoConfig, + Pr, + Issue, + VulnerabilityAlert, +} from '../common'; import { sanitize } from '../../util/sanitize'; import { smartTruncate } from '../utils/pr-body'; @@ -22,7 +29,7 @@ export function initPlatform({ endpoint?: string; username: string; password: string; -}) { +}): PlatformConfig { if (!(username && password)) { throw new Error( 'Init: You must configure a Bitbucket username and password' @@ -41,13 +48,13 @@ export function initPlatform({ } // Get all repositories that the user has access to -export async function getRepos() { +export async function getRepos(): Promise<string[]> { logger.info('Autodiscovering Bitbucket Cloud repositories'); try { - const repos = await utils.accumulateValues( + const repos = await utils.accumulateValues<{ full_name: string }>( `/2.0/repositories/?role=contributor` ); - return repos.map((repo: { full_name: string }) => repo.full_name); + return repos.map(repo => repo.full_name); } catch (err) /* istanbul ignore next */ { logger.error({ err }, `bitbucket getRepos error`); throw err; @@ -60,7 +67,7 @@ export async function initRepo({ localDir, optimizeForDisabled, bbUseDefaultReviewers, -}: RepoParams) { +}: RepoParams): Promise<RepoConfig> { logger.debug(`initRepo("${repository}")`); const opts = hostRules.find({ hostType: 'bitbucket', @@ -71,7 +78,7 @@ export async function initRepo({ username: opts!.username, bbUseDefaultReviewers: bbUseDefaultReviewers !== false, } as any; - let info; + let info: utils.RepoInfo; try { info = utils.repoInfoTransformer( (await api.get(`/2.0/repositories/${repository}`)).body @@ -133,7 +140,7 @@ export async function initRepo({ } // Returns true if repository has rule enforcing PRs are up-to-date with base branch before merging -export function getRepoForceRebase() { +export function getRepoForceRebase(): boolean { // BB doesnt have an option to flag staled branches return false; } @@ -141,11 +148,13 @@ export function getRepoForceRebase() { // Search // Get full file list -export function getFileList(branchName?: string) { +export function getFileList(branchName?: string): Promise<string[]> { return config.storage.getFileList(branchName); } -export async function setBaseBranch(branchName = config.baseBranch) { +export async function setBaseBranch( + branchName = config.baseBranch +): Promise<void> { logger.debug(`Setting baseBranch to ${branchName}`); config.baseBranch = branchName; delete config.baseCommitSHA; @@ -156,31 +165,36 @@ export async function setBaseBranch(branchName = config.baseBranch) { export /* istanbul ignore next */ function setBranchPrefix( branchPrefix: string -) { +): Promise<void> { return config.storage.setBranchPrefix(branchPrefix); } // Branch // Returns true if branch exists, otherwise false -export function branchExists(branchName: string) { +export function branchExists(branchName: string): Promise<boolean> { return config.storage.branchExists(branchName); } -export function getAllRenovateBranches(branchPrefix: string) { +export function getAllRenovateBranches( + branchPrefix: string +): Promise<string[]> { return config.storage.getAllRenovateBranches(branchPrefix); } -export function isBranchStale(branchName: string) { +export function isBranchStale(branchName: string): Promise<boolean> { return config.storage.isBranchStale(branchName); } -export function getFile(filePath: string, branchName?: string) { +export function getFile( + filePath: string, + branchName?: string +): Promise<string> { return config.storage.getFile(filePath, branchName); } // istanbul ignore next -function matchesState(state: string, desiredState: string) { +function matchesState(state: string, desiredState: string): boolean { if (desiredState === 'all') { return true; } @@ -190,7 +204,7 @@ function matchesState(state: string, desiredState: string) { return state === desiredState; } -export async function getPrList() { +export async function getPrList(): Promise<Pr[]> { logger.debug('getPrList()'); if (!config.prList) { logger.debug('Retrieving PR list'); @@ -207,11 +221,11 @@ export async function findPr( branchName: string, prTitle?: string | null, state = 'all' -) { +): Promise<Pr | null> { logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`); const prList = await getPrList(); const pr = prList.find( - (p: { branchName: string; title: string; state: string }) => + p => p.branchName === branchName && (!prTitle || p.title === prTitle) && matchesState(p.state, state) @@ -222,7 +236,10 @@ export async function findPr( return pr; } -export async function deleteBranch(branchName: string, closePr?: boolean) { +export async function deleteBranch( + branchName: string, + closePr?: boolean +): Promise<void> { if (closePr) { const pr = await findPr(branchName, null, 'open'); if (pr) { @@ -234,25 +251,25 @@ export async function deleteBranch(branchName: string, closePr?: boolean) { return config.storage.deleteBranch(branchName); } -export function getBranchLastCommitTime(branchName: string) { +export function getBranchLastCommitTime(branchName: string): Promise<Date> { return config.storage.getBranchLastCommitTime(branchName); } // istanbul ignore next -export function getRepoStatus() { +export function getRepoStatus(): Promise<StatusResult> { return config.storage.getRepoStatus(); } -export function mergeBranch(branchName: string) { +export function mergeBranch(branchName: string): Promise<void> { return config.storage.mergeBranch(branchName); } export function commitFilesToBranch( branchName: string, - files: any[], + files: File[], message: string, parentBranch = config.baseBranch -) { +): Promise<void> { return config.storage.commitFilesToBranch( branchName, files, @@ -261,11 +278,11 @@ export function commitFilesToBranch( ); } -export function getCommitMessages() { +export function getCommitMessages(): Promise<string[]> { return config.storage.getCommitMessages(); } -async function isPrConflicted(prNo: number) { +async function isPrConflicted(prNo: number): Promise<boolean> { const diff = (await api.get( `/2.0/repositories/${config.repository}/pullrequests/${prNo}/diff`, { json: false } as any @@ -275,7 +292,7 @@ async function isPrConflicted(prNo: number) { } // Gets details for a PR -export async function getPr(prNo: number) { +export async function getPr(prNo: number): Promise<Pr | null> { const pr = (await api.get( `/2.0/repositories/${config.repository}/pullrequests/${prNo}` )).body; @@ -330,10 +347,11 @@ export async function getPr(prNo: number) { return res; } -const escapeHash = input => (input ? input.replace(/#/g, '%23') : input); +const escapeHash = (input: string): string => + input ? input.replace(/#/g, '%23') : input; // Return the commit SHA for a branch -async function getBranchCommit(branchName: string) { +async function getBranchCommit(branchName: string): Promise<string | null> { try { const branch = (await api.get( `/2.0/repositories/${config.repository}/refs/branches/${escapeHash( @@ -348,7 +366,7 @@ async function getBranchCommit(branchName: string) { } // Returns the Pull Request for a branch. Null if not exists. -export async function getBranchPr(branchName: string) { +export async function getBranchPr(branchName: string): Promise<Pr | null> { logger.debug(`getBranchPr(${branchName})`); const existingPr = await findPr(branchName, null, 'open'); return existingPr ? getPr(existingPr.number) : null; @@ -358,7 +376,7 @@ export async function getBranchPr(branchName: string) { export async function getBranchStatus( branchName: string, requiredStatusChecks?: string[] -) { +): Promise<string> { logger.debug(`getBranchStatus(${branchName})`); if (!requiredStatusChecks) { // null means disable status checks, so it always succeeds @@ -400,7 +418,7 @@ export async function getBranchStatus( export async function getBranchStatusCheck( branchName: string, context: string -) { +): Promise<string | null> { const sha = await getBranchCommit(branchName); const statuses = await utils.accumulateValues( `/2.0/repositories/${config.repository}/commit/${sha}/statuses` @@ -422,7 +440,7 @@ export async function setBranchStatus( description: string, state: string, targetUrl?: string -) { +): Promise<void> { const sha = await getBranchCommit(branchName); // TargetUrl can not be empty so default to bitbucket @@ -442,7 +460,9 @@ export async function setBranchStatus( ); } -async function findOpenIssues(title: string) { +type BbIssue = { id: number; content?: { raw: string } }; + +async function findOpenIssues(title: string): Promise<BbIssue[]> { try { const filter = encodeURIComponent( [ @@ -462,7 +482,7 @@ async function findOpenIssues(title: string) { } } -export async function findIssue(title: string) { +export async function findIssue(title: string): Promise<Issue> { logger.debug(`findIssue(${title})`); /* istanbul ignore if */ @@ -481,7 +501,7 @@ export async function findIssue(title: string) { }; } -async function closeIssue(issueNumber: number) { +async function closeIssue(issueNumber: number): Promise<void> { await api.put( `/2.0/repositories/${config.repository}/issues/${issueNumber}`, { @@ -490,7 +510,7 @@ async function closeIssue(issueNumber: number) { ); } -export function getPrBody(input: string) { +export function getPrBody(input: string): string { // Remove any HTML we use return smartTruncate(input, 50000) .replace(/<\/?summary>/g, '**') @@ -499,7 +519,10 @@ export function getPrBody(input: string) { .replace(/\]\(\.\.\/pull\//g, '](../../pull-requests/'); } -export async function ensureIssue(title: string, body: string) { +export async function ensureIssue( + title: string, + body: string +): Promise<string | null> { logger.debug(`ensureIssue()`); const description = getPrBody(sanitize(body)); @@ -554,7 +577,9 @@ export async function ensureIssue(title: string, body: string) { return null; } -export /* istanbul ignore next */ async function getIssueList() { +export /* istanbul ignore next */ async function getIssueList(): Promise< + Issue[] +> { logger.debug(`getIssueList()`); /* istanbul ignore if */ @@ -580,7 +605,7 @@ export /* istanbul ignore next */ async function getIssueList() { } } -export async function ensureIssueClosing(title: string) { +export async function ensureIssueClosing(title: string): Promise<void> { /* istanbul ignore if */ if (!config.has_issues) { logger.debug('Issues are disabled - cannot ensureIssueClosing'); @@ -593,13 +618,19 @@ export async function ensureIssueClosing(title: string) { } // eslint-disable-next-line @typescript-eslint/no-unused-vars -export function addAssignees(_prNr: number, _assignees: string[]) { +export function addAssignees( + _prNr: number, + _assignees: string[] +): Promise<void> { // Bitbucket supports "participants" and "reviewers" so does not seem to have the concept of "assignee" logger.warn('Cannot add assignees'); return Promise.resolve(); } -export async function addReviewers(prId: number, reviewers: string[]) { +export async function addReviewers( + prId: number, + reviewers: string[] +): Promise<void> { logger.debug(`Adding reviewers ${reviewers} to #${prId}`); const { title } = await getPr(prId); @@ -614,7 +645,7 @@ export async function addReviewers(prId: number, reviewers: string[]) { }); } -export /* istanbul ignore next */ function deleteLabel() { +export /* istanbul ignore next */ function deleteLabel(): never { throw new Error('deleteLabel not implemented'); } @@ -622,12 +653,15 @@ export function ensureComment( prNo: number, topic: string | null, content: string -) { +): Promise<boolean> { // https://developer.atlassian.com/bitbucket/api/2/reference/search?q=pullrequest+comment return comments.ensureComment(config, prNo, topic, sanitize(content)); } -export function ensureCommentRemoval(prNo: number, topic: string) { +export function ensureCommentRemoval( + prNo: number, + topic: string +): Promise<void> { return comments.ensureCommentRemoval(config, prNo, topic); } @@ -638,7 +672,7 @@ export async function createPr( description: string, _labels?: string[], useDefaultBranch = true -) { +): Promise<Pr> { // labels is not supported in Bitbucket: https://bitbucket.org/site/master/issues/11976/ability-to-add-labels-to-pull-requests-bb const base = useDefaultBranch @@ -679,11 +713,12 @@ export async function createPr( `/2.0/repositories/${config.repository}/pullrequests`, { body } )).body; - const pr = { + // TODO: fix types + const pr: Pr = { number: prInfo.id, displayNumber: `Pull Request #${prInfo.id}`, isModified: false, - }; + } as any; // istanbul ignore if if (config.prList) { config.prList.push(pr); @@ -700,7 +735,7 @@ interface Commit { } // Return a list of all modified files in a PR -export async function getPrFiles(prNo: number) { +export async function getPrFiles(prNo: number): Promise<string[]> { logger.debug({ prNo }, 'getPrFiles'); const diff = (await api.get( `/2.0/repositories/${config.repository}/pullrequests/${prNo}/diff`, @@ -714,14 +749,17 @@ export async function updatePr( prNo: number, title: string, description: string -) { +): Promise<void> { logger.debug(`updatePr(${prNo}, ${title}, body)`); await api.put(`/2.0/repositories/${config.repository}/pullrequests/${prNo}`, { body: { title, description: sanitize(description) }, }); } -export async function mergePr(prNo: number, branchName: string) { +export async function mergePr( + prNo: number, + branchName: string +): Promise<boolean> { logger.debug(`mergePr(${prNo}, ${branchName})`); try { @@ -745,7 +783,7 @@ export async function mergePr(prNo: number, branchName: string) { // Pull Request -export function cleanRepo() { +export function cleanRepo(): void { // istanbul ignore if if (config.storage && config.storage.cleanRepo) { config.storage.cleanRepo(); @@ -753,6 +791,6 @@ export function cleanRepo() { config = {} as any; } -export function getVulnerabilityAlerts() { +export function getVulnerabilityAlerts(): VulnerabilityAlert[] { return []; } diff --git a/lib/platform/bitbucket/utils.ts b/lib/platform/bitbucket/utils.ts index 8ab90f46b9..e20a7cd422 100644 --- a/lib/platform/bitbucket/utils.ts +++ b/lib/platform/bitbucket/utils.ts @@ -1,7 +1,7 @@ import url from 'url'; import { api } from './bb-got-wrapper'; import { Storage } from '../git/storage'; -import { GotResponse } from '../common'; +import { GotResponse, Pr } from '../common'; export interface Config { baseBranch: string; @@ -11,7 +11,7 @@ export interface Config { has_issues: boolean; mergeMethod: string; owner: string; - prList: any[]; + prList: Pr[]; repository: string; storage: Storage; bbUseDefaultReviewers: boolean; @@ -26,7 +26,15 @@ export interface PagedResult<T = any> { values: T[]; } -export function repoInfoTransformer(repoInfoBody: any) { +export interface RepoInfo { + isFork: boolean; + owner: string; + mainbranch: string; + mergeMethod: string; + has_issues: boolean; +} + +export function repoInfoTransformer(repoInfoBody: any): RepoInfo { return { isFork: !!repoInfoBody.parent, owner: repoInfoBody.owner.username, @@ -55,7 +63,7 @@ export const buildStates: { pending: 'INPROGRESS', }; -const addMaxLength = (inputUrl: string, pagelen = 100) => { +const addMaxLength = (inputUrl: string, pagelen = 100): string => { const { search, ...parsedUrl } = url.parse(inputUrl, true); // eslint-disable-line @typescript-eslint/no-unused-vars const maxedUrl = url.format({ ...parsedUrl, @@ -69,7 +77,7 @@ export async function accumulateValues<T = any>( method = 'get', options?: any, pagelen?: number -) { +): Promise<T[]> { let accumulator: T[] = []; let nextUrl = addMaxLength(reqUrl, pagelen); const lowerCaseMethod = method.toLocaleLowerCase(); @@ -86,7 +94,7 @@ export async function accumulateValues<T = any>( return accumulator; } -export /* istanbul ignore next */ function isConflicted(files: any) { +export /* istanbul ignore next */ function isConflicted(files: any): boolean { for (const file of files) { for (const chunk of file.chunks) { for (const change of chunk.changes) { @@ -99,7 +107,7 @@ export /* istanbul ignore next */ function isConflicted(files: any) { return false; } -export function prInfo(pr: any) { +export function prInfo(pr: any): Pr { return { number: pr.id, body: pr.summary ? pr.summary.raw : /* istanbul ignore next */ undefined, diff --git a/lib/platform/common.ts b/lib/platform/common.ts index 7cc9e24f2c..544b9b4904 100644 --- a/lib/platform/common.ts +++ b/lib/platform/common.ts @@ -1,6 +1,7 @@ import got from 'got'; import Git from 'simple-git/promise'; import { RenovateConfig } from '../config/common'; +import { File } from './git/storage'; export interface FileData { name: string; @@ -77,7 +78,10 @@ export interface RepoParams { /** * TODO: Proper typing */ -export type Pr = any; +export type Pr = { branchName: string; title: string; state: string } & Record< + string, + any +>; /** * TODO: Proper typing @@ -158,7 +162,7 @@ export interface Platform { setBaseBranch(baseBranch: string): Promise<void>; commitFilesToBranch( branchName: string, - updatedFiles: any[], + updatedFiles: File[], commitMessage: string, parentBranch?: string ): Promise<void>; @@ -173,7 +177,7 @@ export interface Platform { branchName: string, requiredStatusChecks?: string[] | null ): Promise<BranchStatus>; - getBranchPr(branchName: string): Promise<Pr>; + getBranchPr(branchName: string): Promise<Pr | null>; getRepoStatus(): Promise<Git.StatusResult>; getFile(lockFileName: string, branchName?: string): Promise<string>; initPlatform(config: RenovateConfig): Promise<PlatformConfig>; diff --git a/lib/platform/git/storage.ts b/lib/platform/git/storage.ts index 2d79546378..cdb22fbadd 100644 --- a/lib/platform/git/storage.ts +++ b/lib/platform/git/storage.ts @@ -11,6 +11,23 @@ declare module 'fs-extra' { export function exists(pathLike: string): Promise<boolean>; } +export type StatusResult = Git.StatusResult; + +/** + * File to commit to branch + */ +export interface File { + /** + * Relative file path + */ + name: string; + + /** + * file contents + */ + contents: string; +} + interface StorageConfig { localDir: string; baseBranch?: string; @@ -21,12 +38,12 @@ interface StorageConfig { interface LocalConfig extends StorageConfig { baseBranch: string; baseBranchSha: string; - branchExists: { [branch: string]: boolean }; + branchExists: Record<string, boolean>; branchPrefix: string; } // istanbul ignore next -function checkForPlatformFailure(err: Error) { +function checkForPlatformFailure(err: Error): void { if (process.env.NODE_ENV === 'test') { return; } @@ -47,11 +64,11 @@ function checkForPlatformFailure(err: Error) { } } -function localName(branchName: string) { +function localName(branchName: string): string { return branchName.replace(/^origin\//, ''); } -function throwBaseBranchValidationError(branchName) { +function throwBaseBranchValidationError(branchName: string): never { const error = new Error('config-validation'); error.validationError = 'baseBranch not found'; error.validationMessage = @@ -66,7 +83,7 @@ export class Storage { private _cwd: string | undefined; - private async _resetToBranch(branchName: string) { + private async _resetToBranch(branchName: string): Promise<void> { logger.debug(`resetToBranch(${branchName})`); await this._git!.raw(['reset', '--hard']); await this._git!.checkout(branchName); @@ -74,7 +91,7 @@ export class Storage { await this._git!.raw(['clean', '-fd']); } - private async _cleanLocalBranches() { + private async _cleanLocalBranches(): Promise<void> { const existingBranches = (await this._git!.raw(['branch'])) .split('\n') .map(branch => branch.trim()) @@ -86,7 +103,7 @@ export class Storage { } } - async initRepo(args: StorageConfig) { + async initRepo(args: StorageConfig): Promise<void> { this.cleanRepo(); // eslint-disable-next-line no-multi-assign const config: LocalConfig = (this._config = { ...args } as any); @@ -98,7 +115,7 @@ export class Storage { let clone = true; // TODO: move to private class scope - async function determineBaseBranch(git: Git.SimpleGit) { + async function determineBaseBranch(git: Git.SimpleGit): Promise<void> { // see https://stackoverflow.com/a/44750379/1438522 try { config.baseBranch = @@ -197,11 +214,11 @@ export class Storage { } // istanbul ignore next - getRepoStatus() { + getRepoStatus(): Promise<StatusResult> { return this._git!.status(); } - async createBranch(branchName: string, sha: string) { + async createBranch(branchName: string, sha: string): Promise<void> { logger.debug(`createBranch(${branchName})`); await this._git!.reset('hard'); await this._git!.raw(['clean', '-fd']); @@ -211,7 +228,7 @@ export class Storage { } // Return the commit SHA for a branch - async getBranchCommit(branchName: string) { + async getBranchCommit(branchName: string): Promise<string> { if (!(await this.branchExists(branchName))) { throw Error( 'Cannot fetch commit for branch that does not exist: ' + branchName @@ -221,7 +238,7 @@ export class Storage { return res.trim(); } - async getCommitMessages() { + async getCommitMessages(): Promise<string[]> { logger.debug('getCommitMessages'); const res = await this._git!.log({ n: 10, @@ -230,7 +247,7 @@ export class Storage { return res.all.map(commit => commit.message); } - async setBaseBranch(branchName: string) { + async setBaseBranch(branchName: string): Promise<void> { if (branchName) { if (!(await this.branchExists(branchName))) { throwBaseBranchValidationError(branchName); @@ -266,7 +283,7 @@ export class Storage { * When we initially clone, we clone only the default branch so how no knowledge of other branches existing. * By calling this function once the repo's branchPrefix is known, we can fetch all of Renovate's branches in one command. */ - async setBranchPrefix(branchPrefix: string) { + async setBranchPrefix(branchPrefix: string): Promise<void> { logger.debug('Setting branchPrefix: ' + branchPrefix); this._config.branchPrefix = branchPrefix; const ref = `refs/heads/${branchPrefix}*:refs/remotes/origin/${branchPrefix}*`; @@ -278,7 +295,7 @@ export class Storage { } } - async getFileList(branchName?: string) { + async getFileList(branchName?: string): Promise<string[]> { const branch = branchName || this._config.baseBranch; const exists = await this.branchExists(branch); if (!exists) { @@ -303,7 +320,7 @@ export class Storage { ); } - async getSubmodules() { + async getSubmodules(): Promise<string[]> { return ( (await this._git!.raw([ 'config', @@ -318,7 +335,7 @@ export class Storage { .filter((_e: string, i: number) => i % 2); } - async branchExists(branchName: string) { + async branchExists(branchName: string): Promise<boolean> { // First check cache if (this._config.branchExists[branchName] !== undefined) { return this._config.branchExists[branchName]; @@ -349,14 +366,14 @@ export class Storage { } } - async getAllRenovateBranches(branchPrefix: string) { + async getAllRenovateBranches(branchPrefix: string): Promise<string[]> { const branches = await this._git!.branch(['--remotes', '--verbose']); return branches.all .map(localName) .filter(branchName => branchName.startsWith(branchPrefix)); } - async isBranchStale(branchName: string) { + async isBranchStale(branchName: string): Promise<boolean> { if (!(await this.branchExists(branchName))) { throw Error( 'Cannot check staleness for branch that does not exist: ' + branchName @@ -371,11 +388,11 @@ export class Storage { return !branches.all.map(localName).includes(branchName); } - private async _deleteLocalBranch(branchName: string) { + private async _deleteLocalBranch(branchName: string): Promise<void> { await this._git!.branch(['-D', branchName]); } - async deleteBranch(branchName: string) { + async deleteBranch(branchName: string): Promise<void> { try { await this._git!.raw(['push', '--delete', 'origin', branchName]); logger.debug({ branchName }, 'Deleted remote branch'); @@ -394,7 +411,7 @@ export class Storage { this._config.branchExists[branchName] = false; } - async mergeBranch(branchName: string) { + async mergeBranch(branchName: string): Promise<void> { await this._git!.reset('hard'); await this._git!.checkout(['-B', branchName, 'origin/' + branchName]); await this._git!.checkout(this._config.baseBranch); @@ -403,7 +420,7 @@ export class Storage { limits.incrementLimit('prCommitsPerRunLimit'); } - async getBranchLastCommitTime(branchName: string) { + async getBranchLastCommitTime(branchName: string): Promise<Date> { try { const time = await this._git!.show([ '-s', @@ -417,7 +434,7 @@ export class Storage { } } - async getFile(filePath: string, branchName?: string) { + async getFile(filePath: string, branchName?: string): Promise<string | null> { if (branchName) { const exists = await this.branchExists(branchName); if (!exists) { @@ -438,10 +455,10 @@ export class Storage { async commitFilesToBranch( branchName: string, - files: any[], + files: File[], message: string, parentBranch = this._config.baseBranch - ) { + ): Promise<void> { logger.debug(`Committing files to branch ${branchName}`); try { await this._git!.reset('hard'); @@ -494,7 +511,7 @@ export class Storage { } // eslint-disable-next-line - cleanRepo() {} + cleanRepo(): void {} static getUrl({ protocol, @@ -508,7 +525,7 @@ export class Storage { hostname?: string; host?: string; repository: string; - }) { + }): string { if (protocol === 'ssh') { return `git@${hostname}:${repository}.git`; } diff --git a/lib/platform/github/gh-got-wrapper.ts b/lib/platform/github/gh-got-wrapper.ts index 5f6a2ed4ef..85b6a2170a 100644 --- a/lib/platform/github/gh-got-wrapper.ts +++ b/lib/platform/github/gh-got-wrapper.ts @@ -4,7 +4,7 @@ import pAll from 'p-all'; import got from '../../util/got'; import { maskToken } from '../../util/mask'; -import { GotApi } from '../common'; +import { GotApi, GotResponse } from '../common'; import { logger } from '../../logger'; const hostType = 'github'; @@ -14,7 +14,7 @@ async function get( path: string, options?: any, okToRetry = true -): Promise<any> { +): Promise<GotResponse> { const opts = { hostType, baseUrl, @@ -58,7 +58,7 @@ async function get( new Array(lastPage), (x, i) => i + 1 ).slice(1); - const queue = pageNumbers.map(page => () => { + const queue = pageNumbers.map(page => (): Promise<GotResponse> => { const nextUrl = URL.parse(linkHeader.next.url, true); delete nextUrl.search; nextUrl.query.page = page.toString(); @@ -163,11 +163,11 @@ async function get( const helpers = ['get', 'post', 'put', 'patch', 'head', 'delete']; for (const x of helpers) { - (get as any)[x] = (url: string, opts: any) => + (get as any)[x] = (url: string, opts: any): Promise<GotResponse> => get(url, Object.assign({}, opts, { method: x.toUpperCase() })); } -get.setBaseUrl = (u: string) => { +get.setBaseUrl = (u: string): void => { baseUrl = u; }; diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index cf9dfd8e4d..2fff829332 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -6,8 +6,14 @@ import URL from 'url'; import { logger } from '../../logger'; import { api } from './gh-got-wrapper'; import * as hostRules from '../../util/host-rules'; -import GitStorage from '../git/storage'; -import { PlatformConfig, RepoParams, RepoConfig } from '../common'; +import GitStorage, { StatusResult, File } from '../git/storage'; +import { + PlatformConfig, + RepoParams, + RepoConfig, + Issue, + VulnerabilityAlert, +} from '../common'; import { appName, @@ -50,8 +56,8 @@ interface LocalRepoConfig { parentRepo: string; baseCommitSHA: string | null; forkToken?: string; - closedPrList: { [num: number]: Pr } | null; - openPrList: { [num: number]: Pr } | null; + closedPrList: PrList | null; + openPrList: PrList | null; prList: Pr[] | null; issueList: any[] | null; mergeMethod: string; @@ -66,6 +72,9 @@ interface LocalRepoConfig { renovateUsername: string; } +type BranchProtection = any; +type PrList = Record<number, Pr>; + let config: LocalRepoConfig = {} as any; const defaults = { @@ -73,7 +82,8 @@ const defaults = { endpoint: 'https://api.github.com/', }; -const escapeHash = input => (input ? input.replace(/#/g, '%23') : input); +const escapeHash = (input: string): string => + input ? input.replace(/#/g, '%23') : input; export async function initPlatform({ endpoint, @@ -81,7 +91,7 @@ export async function initPlatform({ }: { endpoint: string; token: string; -}) { +}): Promise<PlatformConfig> { if (!token) { throw new Error('Init: You must configure a GitHub personal access token'); } @@ -130,7 +140,7 @@ export async function initPlatform({ } // Get all repositories that the user has access to -export async function getRepos() { +export async function getRepos(): Promise<string[]> { logger.info('Autodiscovering GitHub repositories'); try { const res = await api.get('user/repos?per_page=100', { paginate: true }); @@ -141,7 +151,7 @@ export async function getRepos() { } } -export function cleanRepo() { +export function cleanRepo(): void { // istanbul ignore if if (config.storage) { config.storage.cleanRepo(); @@ -150,7 +160,9 @@ export function cleanRepo() { config = {} as any; } -async function getBranchProtection(branchName: string) { +async function getBranchProtection( + branchName: string +): Promise<BranchProtection> { // istanbul ignore if if (config.parentRepo) { return {}; @@ -162,7 +174,7 @@ async function getBranchProtection(branchName: string) { } // Return the commit SHA for a branch -async function getBranchCommit(branchName: string) { +async function getBranchCommit(branchName: string): Promise<string> { try { const res = await api.get( `repos/${config.repository}/git/refs/heads/${escapeHash(branchName)}` @@ -180,7 +192,7 @@ async function getBranchCommit(branchName: string) { } } -async function getBaseCommitSHA() { +async function getBaseCommitSHA(): Promise<string> { if (!config.baseCommitSHA) { config.baseCommitSHA = await getBranchCommit(config.baseBranch); } @@ -198,7 +210,7 @@ export async function initRepo({ includeForks, renovateUsername, optimizeForDisabled, -}: RepoParams) { +}: RepoParams): Promise<RepoConfig> { logger.debug(`initRepo("${repository}")`); logger.info('Authenticated as user: ' + renovateUsername); logger.info('Using renovate version: ' + global.renovateVersion); @@ -421,7 +433,7 @@ export async function initRepo({ return repoConfig; } -export async function getRepoForceRebase() { +export async function getRepoForceRebase(): Promise<boolean> { if (config.repoForceRebase === undefined) { try { config.repoForceRebase = false; @@ -467,63 +479,73 @@ export async function getRepoForceRebase() { } // istanbul ignore next -export async function setBaseBranch(branchName = config.baseBranch) { +export async function setBaseBranch( + branchName = config.baseBranch +): Promise<void> { config.baseBranch = branchName; config.baseCommitSHA = null; await config.storage.setBaseBranch(branchName); } // istanbul ignore next -export function setBranchPrefix(branchPrefix: string) { +export function setBranchPrefix(branchPrefix: string): Promise<void> { return config.storage.setBranchPrefix(branchPrefix); } // Search // istanbul ignore next -export function getFileList(branchName = config.baseBranch) { +export function getFileList(branchName = config.baseBranch): Promise<string[]> { return config.storage.getFileList(branchName); } // Branch // istanbul ignore next -export function branchExists(branchName: string) { +export function branchExists(branchName: string): Promise<boolean> { return config.storage.branchExists(branchName); } // istanbul ignore next -export function getAllRenovateBranches(branchPrefix: string) { +export function getAllRenovateBranches( + branchPrefix: string +): Promise<string[]> { return config.storage.getAllRenovateBranches(branchPrefix); } // istanbul ignore next -export function isBranchStale(branchName: string) { +export function isBranchStale(branchName: string): Promise<boolean> { return config.storage.isBranchStale(branchName); } // istanbul ignore next -export function getFile(filePath: string, branchName?: string) { +export function getFile( + filePath: string, + branchName?: string +): Promise<string> { return config.storage.getFile(filePath, branchName); } // istanbul ignore next -export function deleteBranch(branchName: string, closePr?: boolean) { +export function deleteBranch( + branchName: string, + closePr?: boolean +): Promise<void> { return config.storage.deleteBranch(branchName); } // istanbul ignore next -export function getBranchLastCommitTime(branchName: string) { +export function getBranchLastCommitTime(branchName: string): Promise<Date> { return config.storage.getBranchLastCommitTime(branchName); } // istanbul ignore next -export function getRepoStatus() { +export function getRepoStatus(): Promise<StatusResult> { return config.storage.getRepoStatus(); } // istanbul ignore next -export function mergeBranch(branchName: string) { +export function mergeBranch(branchName: string): Promise<void> { if (config.pushProtection) { logger.info( { branch: branchName }, @@ -536,10 +558,10 @@ export function mergeBranch(branchName: string) { // istanbul ignore next export function commitFilesToBranch( branchName: string, - files: any[], + files: File[], message: string, parentBranch = config.baseBranch -) { +): Promise<void> { return config.storage.commitFilesToBranch( branchName, files, @@ -549,11 +571,11 @@ export function commitFilesToBranch( } // istanbul ignore next -export function getCommitMessages() { +export function getCommitMessages(): Promise<string[]> { return config.storage.getCommitMessages(); } -async function getClosedPrs() { +async function getClosedPrs(): Promise<PrList> { if (!config.closedPrList) { config.closedPrList = {}; let query; @@ -619,7 +641,7 @@ async function getClosedPrs() { return config.closedPrList; } -async function getOpenPrs() { +async function getOpenPrs(): Promise<PrList> { // istanbul ignore if if (config.isGhe) { logger.debug( @@ -786,7 +808,7 @@ async function getOpenPrs() { } // Gets details for a PR -export async function getPr(prNo: number) { +export async function getPr(prNo: number): Promise<Pr | null> { if (!prNo) { return null; } @@ -896,7 +918,7 @@ export async function getPr(prNo: number) { return pr; } -function matchesState(state: string, desiredState: string) { +function matchesState(state: string, desiredState: string): boolean { if (desiredState === 'all') { return true; } @@ -906,7 +928,7 @@ function matchesState(state: string, desiredState: string) { return state === desiredState; } -export async function getPrList() { +export async function getPrList(): Promise<Pr[]> { logger.trace('getPrList()'); if (!config.prList) { logger.debug('Retrieving PR list'); @@ -948,7 +970,7 @@ export async function findPr( branchName: string, prTitle?: string | null, state = 'all' -) { +): Promise<Pr | null> { logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`); const prList = await getPrList(); const pr = prList.find( @@ -964,7 +986,7 @@ export async function findPr( } // Returns the Pull Request for a branch. Null if not exists. -export async function getBranchPr(branchName: string) { +export async function getBranchPr(branchName: string): Promise<Pr | null> { logger.debug(`getBranchPr(${branchName})`); const existingPr = await findPr(branchName, null, 'open'); return existingPr ? getPr(existingPr.number) : null; @@ -974,7 +996,7 @@ export async function getBranchPr(branchName: string) { export async function getBranchStatus( branchName: string, requiredStatusChecks: any -) { +): Promise<string> { logger.debug(`getBranchStatus(${branchName})`); if (!requiredStatusChecks) { // null means disable status checks, so it always succeeds @@ -1066,7 +1088,7 @@ export async function getBranchStatus( export async function getBranchStatusCheck( branchName: string, context: string -) { +): Promise<string> { const branchCommit = await config.storage.getBranchCommit(branchName); const url = `repos/${config.repository}/commits/${branchCommit}/statuses`; try { @@ -1092,7 +1114,7 @@ export async function setBranchStatus( description: string, state: string, targetUrl?: string -) { +): Promise<void> { // istanbul ignore if if (config.parentRepo) { logger.info('Cannot set branch status when in forking mode'); @@ -1119,7 +1141,9 @@ export async function setBranchStatus( // Issue /* istanbul ignore next */ -async function getGraphqlIssues(afterCursor: string | null = null) { +async function getGraphqlIssues( + afterCursor: string | null = null +): Promise<[boolean, Issue[], string | null]> { const url = 'graphql'; const headers = { accept: 'application/vnd.github.merge-info-preview+json', @@ -1170,7 +1194,7 @@ async function getGraphqlIssues(afterCursor: string | null = null) { } // istanbul ignore next -async function getRestIssues() { +async function getRestIssues(): Promise<Issue[]> { logger.debug('Retrieving issueList'); const res = await api.get< { @@ -1197,7 +1221,7 @@ async function getRestIssues() { })); } -export async function getIssueList() { +export async function getIssueList(): Promise<Issue[]> { if (!config.issueList) { logger.debug('Retrieving issueList'); const filterBySupportMinimumGheVersion = '2.17.0'; @@ -1228,7 +1252,7 @@ export async function getIssueList() { return config.issueList; } -export async function findIssue(title: string) { +export async function findIssue(title: string): Promise<Issue | null> { logger.debug(`findIssue(${title})`); const [issue] = (await getIssueList()).filter( i => i.state === 'open' && i.title === title @@ -1246,7 +1270,7 @@ export async function findIssue(title: string) { }; } -async function closeIssue(issueNumber: number) { +async function closeIssue(issueNumber: number): Promise<void> { logger.debug(`closeIssue(${issueNumber})`); await api.patch( `repos/${config.parentRepo || config.repository}/issues/${issueNumber}`, @@ -1261,7 +1285,7 @@ export async function ensureIssue( rawbody: string, once = false, reopen = true -) { +): Promise<string | null> { logger.debug(`ensureIssue(${title})`); const body = sanitize(rawbody); try { @@ -1332,7 +1356,7 @@ export async function ensureIssue( return null; } -export async function ensureIssueClosing(title: string) { +export async function ensureIssueClosing(title: string): Promise<void> { logger.debug(`ensureIssueClosing(${title})`); const issueList = await getIssueList(); for (const issue of issueList) { @@ -1343,7 +1367,10 @@ export async function ensureIssueClosing(title: string) { } } -export async function addAssignees(issueNo: number, assignees: string[]) { +export async function addAssignees( + issueNo: number, + assignees: string[] +): Promise<void> { logger.debug(`Adding assignees ${assignees} to #${issueNo}`); const repository = config.parentRepo || config.repository; await api.post(`repos/${repository}/issues/${issueNo}/assignees`, { @@ -1353,7 +1380,10 @@ export async function addAssignees(issueNo: number, assignees: string[]) { }); } -export async function addReviewers(prNo: number, reviewers: string[]) { +export async function addReviewers( + prNo: number, + reviewers: string[] +): Promise<void> { logger.debug(`Adding reviewers ${reviewers} to #${prNo}`); const userReviewers = reviewers.filter(e => !e.startsWith('team:')); @@ -1373,7 +1403,10 @@ export async function addReviewers(prNo: number, reviewers: string[]) { ); } -async function addLabels(issueNo: number, labels: string[] | null) { +async function addLabels( + issueNo: number, + labels: string[] | null +): Promise<void> { logger.debug(`Adding labels ${labels} to #${issueNo}`); const repository = config.parentRepo || config.repository; if (is.array(labels) && labels.length) { @@ -1383,7 +1416,10 @@ async function addLabels(issueNo: number, labels: string[] | null) { } } -export async function deleteLabel(issueNo: number, label: string) { +export async function deleteLabel( + issueNo: number, + label: string +): Promise<void> { logger.debug(`Deleting label ${label} from #${issueNo}`); const repository = config.parentRepo || config.repository; try { @@ -1393,7 +1429,7 @@ export async function deleteLabel(issueNo: number, label: string) { } } -async function addComment(issueNo: number, body: string) { +async function addComment(issueNo: number, body: string): Promise<void> { // POST /repos/:owner/:repo/issues/:number/comments await api.post( `repos/${config.parentRepo || @@ -1404,7 +1440,7 @@ async function addComment(issueNo: number, body: string) { ); } -async function editComment(commentId: number, body: string) { +async function editComment(commentId: number, body: string): Promise<void> { // PATCH /repos/:owner/:repo/issues/comments/:id await api.patch( `repos/${config.parentRepo || @@ -1415,7 +1451,7 @@ async function editComment(commentId: number, body: string) { ); } -async function deleteComment(commentId: number) { +async function deleteComment(commentId: number): Promise<void> { // DELETE /repos/:owner/:repo/issues/comments/:id await api.delete( `repos/${config.parentRepo || @@ -1423,7 +1459,7 @@ async function deleteComment(commentId: number) { ); } -async function getComments(issueNo: number) { +async function getComments(issueNo: number): Promise<Comment[]> { const pr = (await getClosedPrs())[issueNo]; if (pr) { logger.debug('Returning closed PR list comments'); @@ -1452,7 +1488,7 @@ export async function ensureComment( issueNo: number, topic: string | null, rawContent: string -) { +): Promise<boolean> { const content = sanitize(rawContent); try { const comments = await getComments(issueNo); @@ -1509,10 +1545,13 @@ export async function ensureComment( } } -export async function ensureCommentRemoval(issueNo: number, topic: string) { +export async function ensureCommentRemoval( + issueNo: number, + topic: string +): Promise<void> { logger.debug(`Ensuring comment "${topic}" in #${issueNo} is removed`); const comments = await getComments(issueNo); - let commentId; + let commentId: number; comments.forEach(comment => { if (comment.body.startsWith(`### ${topic}\n\n`)) { commentId = comment.id; @@ -1537,7 +1576,7 @@ export async function createPr( labels: string[] | null, useDefaultBranch: boolean, platformOptions: { statusCheckVerify?: boolean } = {} -) { +): Promise<Pr> { const body = sanitize(rawBody); const base = useDefaultBranch ? config.defaultBranch : config.baseBranch; // Include the repository owner to handle forkMode and regular mode @@ -1583,7 +1622,7 @@ export async function createPr( } // Return a list of all modified files in a PR -export async function getPrFiles(prNo: number) { +export async function getPrFiles(prNo: number): Promise<string[]> { logger.debug({ prNo }, 'getPrFiles'); if (!prNo) { return []; @@ -1594,7 +1633,11 @@ export async function getPrFiles(prNo: number) { return files.map((f: { filename: string }) => f.filename); } -export async function updatePr(prNo: number, title: string, rawBody?: string) { +export async function updatePr( + prNo: number, + title: string, + rawBody?: string +): Promise<void> { logger.debug(`updatePr(${prNo}, ${title}, body)`); const body = sanitize(rawBody); const patchBody: any = { title }; @@ -1622,7 +1665,10 @@ export async function updatePr(prNo: number, title: string, rawBody?: string) { } } -export async function mergePr(prNo: number, branchName: string) { +export async function mergePr( + prNo: number, + branchName: string +): Promise<boolean> { logger.debug(`mergePr(${prNo}, ${branchName})`); // istanbul ignore if if (config.isGhe && config.pushProtection) { @@ -1721,7 +1767,7 @@ export async function mergePr(prNo: number, branchName: string) { return true; } -export function getPrBody(input: string) { +export function getPrBody(input: string): string { if (config.isGhe) { return smartTruncate(input, 60000); } @@ -1733,7 +1779,7 @@ export function getPrBody(input: string) { return smartTruncate(massagedInput, 60000); } -export async function getVulnerabilityAlerts() { +export async function getVulnerabilityAlerts(): Promise<VulnerabilityAlert[]> { // istanbul ignore if if (config.isGhe) { logger.debug( diff --git a/lib/platform/gitlab/gl-got-wrapper.ts b/lib/platform/gitlab/gl-got-wrapper.ts index e6ecea23df..7384bdaba7 100644 --- a/lib/platform/gitlab/gl-got-wrapper.ts +++ b/lib/platform/gitlab/gl-got-wrapper.ts @@ -1,13 +1,13 @@ import parseLinkHeader from 'parse-link-header'; -import { GotApi } from '../common'; +import { GotApi, GotResponse } from '../common'; import got from '../../util/got'; import { logger } from '../../logger'; const hostType = 'gitlab'; let baseUrl = 'https://gitlab.com/api/v4/'; -async function get(path: string, options: any) { +async function get(path: string, options: any): Promise<GotResponse> { const opts = { hostType, baseUrl, @@ -60,11 +60,11 @@ interface GlGotApi export const api: GlGotApi = {} as any; for (const x of helpers) { - (api as any)[x] = (url: string, opts: any) => + (api as any)[x] = (url: string, opts: any): Promise<GotResponse> => get(url, Object.assign({}, opts, { method: x.toUpperCase() })); } -api.setBaseUrl = e => { +api.setBaseUrl = (e: string): void => { baseUrl = e; }; diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index 91e84734b7..87b9b5ddb5 100644 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -1,21 +1,24 @@ import URL, { URLSearchParams } from 'url'; import is from '@sindresorhus/is'; -import { bool } from 'aws-sdk/clients/signer'; -import simplegit from 'simple-git/promise'; import { api } from './gl-got-wrapper'; import * as hostRules from '../../util/host-rules'; -import GitStorage from '../git/storage'; +import GitStorage, { StatusResult } from '../git/storage'; import { PlatformConfig, RepoParams, RepoConfig, PlatformPrOptions, + GotResponse, + Pr, + Issue, + VulnerabilityAlert, } from '../common'; import { configFileNames } from '../../config/app-strings'; import { logger } from '../../logger'; import { sanitize } from '../../util/sanitize'; import { smartTruncate } from '../utils/pr-body'; +import { RenovateConfig } from '../../config'; const defaultConfigFile = configFileNames[0]; let config: { @@ -43,7 +46,7 @@ export async function initPlatform({ }: { token: string; endpoint: string; -}): Promise<any> { +}): Promise<PlatformConfig> { if (!token) { throw new Error('Init: You must configure a GitLab personal access token'); } @@ -73,7 +76,7 @@ export async function initPlatform({ } // Get all repositories that the user has access to -export async function getRepos(): Promise<any> { +export async function getRepos(): Promise<string[]> { logger.info('Autodiscovering GitLab repositories'); try { const url = `projects?membership=true&per_page=100`; @@ -92,7 +95,7 @@ function urlEscape(str: string): string { return str ? str.replace(/\//g, '%2F') : str; } -export function cleanRepo(): any { +export function cleanRepo(): void { // istanbul ignore if if (config.storage) { config.storage.cleanRepo(); @@ -106,11 +109,17 @@ export async function initRepo({ repository, localDir, optimizeForDisabled, -}: RepoParams): Promise<any> { +}: RepoParams): Promise<RepoConfig> { config = {} as any; config.repository = urlEscape(repository); config.localDir = localDir; - let res; + let res: GotResponse<{ + archived: boolean; + mirror: boolean; + default_branch: string; + http_url_to_repo: string; + forked_from_project: boolean; + }>; try { res = await api.get(`projects/${config.repository}`); if (res.body.archived) { @@ -129,7 +138,7 @@ export async function initRepo({ throw new Error('empty'); } if (optimizeForDisabled) { - let renovateConfig; + let renovateConfig: RenovateConfig; try { renovateConfig = JSON.parse( Buffer.from( @@ -158,7 +167,7 @@ export async function initRepo({ hostType: defaults.hostType, url: defaults.endpoint, }); - let url; + let url: string; if (res.body.http_url_to_repo === null) { logger.debug('no http_url_to_repo found. Falling back to old behaviour.'); const { host, protocol } = URL.parse(defaults.endpoint); @@ -206,13 +215,13 @@ export async function initRepo({ return repoConfig; } -export function getRepoForceRebase(): bool { +export function getRepoForceRebase(): boolean { return false; } export async function setBaseBranch( branchName = config.baseBranch -): Promise<any> { +): Promise<void> { logger.debug(`Setting baseBranch to ${branchName}`); config.baseBranch = branchName; await config.storage.setBaseBranch(branchName); @@ -240,7 +249,7 @@ export function branchExists(branchName: string): Promise<boolean> { export async function getBranchStatus( branchName: string, requiredStatusChecks?: string[] | null -) { +): Promise<string> { logger.debug(`getBranchStatus(${branchName})`); if (!requiredStatusChecks) { // null means disable status checks, so it always succeeds @@ -292,7 +301,7 @@ export async function createPr( labels?: string[] | null, useDefaultBranch?: boolean, platformOptions?: PlatformPrOptions -) { +): Promise<Pr> { const description = sanitize(rawDescription); const targetBranch = useDefaultBranch ? config.defaultBranch @@ -336,7 +345,7 @@ export async function createPr( return pr; } -export async function getPr(iid: number) { +export async function getPr(iid: number): Promise<Pr> { logger.debug(`getPr(${iid})`); const url = `projects/${config.repository}/merge_requests/${iid}?include_diverged_commits_count=1`; const pr = (await api.get(url)).body; @@ -389,7 +398,7 @@ export async function getPr(iid: number) { } // Return a list of all modified files in a PR -export async function getPrFiles(mrNo: number) { +export async function getPrFiles(mrNo: number): Promise<string[]> { logger.debug({ mrNo }, 'getPrFiles'); if (!mrNo) { return []; @@ -401,7 +410,7 @@ export async function getPrFiles(mrNo: number) { } // istanbul ignore next -async function closePr(iid: number) { +async function closePr(iid: number): Promise<void> { await api.put(`projects/${config.repository}/merge_requests/${iid}`, { body: { state_event: 'close', @@ -413,7 +422,7 @@ export async function updatePr( iid: number, title: string, description: string -) { +): Promise<void> { await api.put(`projects/${config.repository}/merge_requests/${iid}`, { body: { title, @@ -422,7 +431,7 @@ export async function updatePr( }); } -export async function mergePr(iid: number) { +export async function mergePr(iid: number): Promise<boolean> { try { await api.put(`projects/${config.repository}/merge_requests/${iid}/merge`, { body: { @@ -445,7 +454,7 @@ export async function mergePr(iid: number) { } } -export function getPrBody(input: string) { +export function getPrBody(input: string): string { return smartTruncate( input .replace(/Pull Request/g, 'Merge Request') @@ -458,7 +467,7 @@ export function getPrBody(input: string) { // Branch // Returns the Pull Request for a branch. Null if not exists. -export async function getBranchPr(branchName: string): Promise<any> { +export async function getBranchPr(branchName: string): Promise<Pr> { logger.debug(`getBranchPr(${branchName})`); // istanbul ignore if if (!(await branchExists(branchName))) { @@ -518,7 +527,7 @@ export function getFile( export async function deleteBranch( branchName: string, shouldClosePr = false -): Promise<any> { +): Promise<void> { if (shouldClosePr) { logger.debug('Closing PR'); const pr = await getBranchPr(branchName); @@ -539,14 +548,14 @@ export function getBranchLastCommitTime(branchName: string): Promise<Date> { } // istanbul ignore next -export function getRepoStatus(): Promise<simplegit.StatusResult> { +export function getRepoStatus(): Promise<StatusResult> { return config.storage.getRepoStatus(); } export async function getBranchStatusCheck( branchName: string, context: string -): Promise<any> { +): Promise<string | null> { // First, get the branch commit SHA const branchSha = await config.storage.getBranchCommit(branchName); // Now, check the statuses for that commit @@ -623,12 +632,7 @@ export async function getIssueList(): Promise<any[]> { return config.issueList; } -export async function findIssue( - title: string -): Promise<{ - number: any; - body: any; -}> { +export async function findIssue(title: string): Promise<Issue | null> { logger.debug(`findIssue(${title})`); try { const issueList = await getIssueList(); @@ -652,7 +656,7 @@ export async function findIssue( export async function ensureIssue( title: string, body: string -): Promise<'updated' | 'created'> { +): Promise<'updated' | 'created' | null> { logger.debug(`ensureIssue()`); const description = getPrBody(sanitize(body)); try { @@ -706,7 +710,7 @@ export async function ensureIssueClosing(title: string): Promise<void> { export async function addAssignees( iid: number, assignees: string[] -): Promise<any> { +): Promise<void> { logger.debug(`Adding assignees ${assignees} to #${iid}`); try { let assigneeId = (await api.get(`users?username=${assignees[0]}`)).body[0] @@ -731,7 +735,7 @@ export async function addAssignees( } } -export function addReviewers(iid: number, reviewers: string[]): any { +export function addReviewers(iid: number, reviewers: string[]): void { logger.debug(`addReviewers('${iid}, '${reviewers})`); logger.warn('Unimplemented in GitLab: approvals'); } @@ -739,7 +743,7 @@ export function addReviewers(iid: number, reviewers: string[]): any { export async function deleteLabel( issueNo: number, label: string -): Promise<any> { +): Promise<void> { logger.debug(`Deleting label ${label} from #${issueNo}`); try { const pr = await getPr(issueNo); @@ -752,7 +756,7 @@ export async function deleteLabel( } } -async function getComments(issueNo: number): Promise<any> { +async function getComments(issueNo: number): Promise<any[]> { // GET projects/:owner/:repo/merge_requests/:number/notes logger.debug(`Getting comments for #${issueNo}`); const url = `projects/${config.repository}/merge_requests/${issueNo}/notes`; @@ -761,7 +765,7 @@ async function getComments(issueNo: number): Promise<any> { return comments; } -async function addComment(issueNo: number, body: string): Promise<any> { +async function addComment(issueNo: number, body: string): Promise<void> { // POST projects/:owner/:repo/merge_requests/:number/notes await api.post( `projects/${config.repository}/merge_requests/${issueNo}/notes`, @@ -775,7 +779,7 @@ async function editComment( issueNo: number, commentId: number, body: string -): Promise<any> { +): Promise<void> { // PUT projects/:owner/:repo/merge_requests/:number/notes/:id await api.put( `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}`, @@ -785,7 +789,10 @@ async function editComment( ); } -async function deleteComment(issueNo: number, commentId: number): Promise<any> { +async function deleteComment( + issueNo: number, + commentId: number +): Promise<void> { // DELETE projects/:owner/:repo/merge_requests/:number/notes/:id await api.delete( `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}` @@ -796,7 +803,7 @@ export async function ensureComment( issueNo: number, topic: string | null | undefined, rawContent: string -): Promise<any> { +): Promise<void> { const content = sanitize(rawContent); const massagedTopic = topic ? topic.replace(/Pull Request/g, 'Merge Request').replace(/PR/g, 'MR') @@ -839,7 +846,7 @@ export async function ensureComment( export async function ensureCommentRemoval( issueNo: number, topic: string -): Promise<any> { +): Promise<void> { logger.debug(`Ensuring comment "${topic}" in #${issueNo} is removed`); const comments = await getComments(issueNo); let commentId; @@ -859,7 +866,7 @@ const mapPullRequests = (pr: { title: string; state: string; created_at: string; -}) => ({ +}): Pr => ({ number: pr.iid, branchName: pr.source_branch, title: pr.title, @@ -867,7 +874,7 @@ const mapPullRequests = (pr: { createdAt: pr.created_at, }); -async function fetchPrList(): Promise<any> { +async function fetchPrList(): Promise<Pr[]> { const query = new URLSearchParams({ per_page: '100', author_id: `${authorId}`, @@ -885,14 +892,14 @@ async function fetchPrList(): Promise<any> { } } -export async function getPrList(): Promise<any> { +export async function getPrList(): Promise<Pr[]> { if (!config.prList) { config.prList = await fetchPrList(); } return config.prList; } -function matchesState(state: string, desiredState: string): bool { +function matchesState(state: string, desiredState: string): boolean { if (desiredState === 'all') { return true; } @@ -906,7 +913,7 @@ export async function findPr( branchName: string, prTitle?: string | null, state = 'all' -): Promise<any> { +): Promise<Pr> { logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`); const prList = await getPrList(); return prList.find( @@ -921,6 +928,6 @@ export function getCommitMessages(): Promise<string[]> { return config.storage.getCommitMessages(); } -export function getVulnerabilityAlerts(): any[] { +export function getVulnerabilityAlerts(): VulnerabilityAlert[] { return []; } diff --git a/lib/workers/repository/onboarding/branch/check.ts b/lib/workers/repository/onboarding/branch/check.ts index 635643ce3b..b5d3ea108f 100644 --- a/lib/workers/repository/onboarding/branch/check.ts +++ b/lib/workers/repository/onboarding/branch/check.ts @@ -91,5 +91,5 @@ export const isOnboarded = async (config: RenovateConfig): Promise<boolean> => { throw new Error('disabled'); }; -export const onboardingPrExists = (): Promise<boolean> => - platform.getBranchPr(onboardingBranch); +export const onboardingPrExists = async (): Promise<boolean> => + (await platform.getBranchPr(onboardingBranch)) != null; diff --git a/test/platform/azure/__snapshots__/azure-helper.spec.ts.snap b/test/platform/azure/__snapshots__/azure-helper.spec.ts.snap index fd991ce6c0..84a2c45350 100644 --- a/test/platform/azure/__snapshots__/azure-helper.spec.ts.snap +++ b/test/platform/azure/__snapshots__/azure-helper.spec.ts.snap @@ -14,36 +14,6 @@ Object { } `; -exports[`platform/azure/helpers getChanges should be get the commit obj formated (file to create) 1`] = ` -Array [ - Object { - "changeType": 1, - "item": Object { - "path": "./myFilePath/test", - }, - "newContent": Object { - "Content": "Hello world!", - "ContentType": 0, - }, - }, -] -`; - -exports[`platform/azure/helpers getChanges should be get the commit obj formated (file to update) 1`] = ` -Array [ - Object { - "changeType": 2, - "item": Object { - "path": "./myFilePath/test", - }, - "newContent": Object { - "Content": "Hello world!", - "ContentType": 0, - }, - }, -] -`; - exports[`platform/azure/helpers getCommitDetails should get commit details 1`] = ` Object { "parents": Array [ diff --git a/test/platform/azure/azure-helper.spec.ts b/test/platform/azure/azure-helper.spec.ts index e4223fafbf..f531481cd9 100644 --- a/test/platform/azure/azure-helper.spec.ts +++ b/test/platform/azure/azure-helper.spec.ts @@ -105,63 +105,6 @@ describe('platform/azure/helpers', () => { }); }); - describe('getChanges', () => { - it('should be get the commit obj formated (file to update)', async () => { - let eventCount = 0; - const mockEventStream = new Readable({ - objectMode: true, - /* eslint-disable func-names */ - /* eslint-disable object-shorthand */ - read: function() { - if (eventCount < 1) { - eventCount += 1; - return this.push('{"hello": "test"}'); - } - return this.push(null); - }, - }); - - azureApi.gitApi.mockImplementationOnce( - () => - ({ - getItemText: jest.fn(() => mockEventStream), - } as any) - ); - - const res = await azureHelper.getChanges( - [ - { - name: './myFilePath/test', - contents: 'Hello world!', - }, - ], - '123', - 'repository' - ); - expect(res).toMatchSnapshot(); - }); - it('should be get the commit obj formated (file to create)', async () => { - azureApi.gitApi.mockImplementationOnce( - () => - ({ - getItemText: jest.fn(() => null), - } as any) - ); - - const res = await azureHelper.getChanges( - [ - { - name: './myFilePath/test', - contents: 'Hello world!', - }, - ], - '123', - 'repository' - ); - expect(res).toMatchSnapshot(); - }); - }); - describe('getFile', () => { it('should return null error GitItemNotFoundException', async () => { let eventCount = 0; diff --git a/test/platform/azure/index.spec.ts b/test/platform/azure/index.spec.ts index 4c9640a826..93e346002a 100644 --- a/test/platform/azure/index.spec.ts +++ b/test/platform/azure/index.spec.ts @@ -215,12 +215,15 @@ describe('platform/azure', () => { azureHelper.getNewBranchName.mockImplementationOnce( () => 'refs/heads/branch-a' ); - azureHelper.getRenovatePRFormat.mockImplementationOnce(() => ({ - number: 1, - head: { ref: 'branch-a' }, - title: 'branch a pr', - state: 'open', - })); + azureHelper.getRenovatePRFormat.mockImplementationOnce( + () => + ({ + number: 1, + head: { ref: 'branch-a' }, + title: 'branch a pr', + state: 'open', + } as any) + ); const res = await azure.findPr('branch-a', 'branch a pr', 'open'); expect(res).toMatchSnapshot(); }); @@ -241,12 +244,15 @@ describe('platform/azure', () => { azureHelper.getNewBranchName.mockImplementationOnce( () => 'refs/heads/branch-a' ); - azureHelper.getRenovatePRFormat.mockImplementationOnce(() => ({ - number: 1, - head: { ref: 'branch-a' }, - title: 'branch a pr', - state: 'closed', - })); + azureHelper.getRenovatePRFormat.mockImplementationOnce( + () => + ({ + number: 1, + head: { ref: 'branch-a' }, + title: 'branch a pr', + state: 'closed', + } as any) + ); const res = await azure.findPr('branch-a', 'branch a pr', '!open'); expect(res).toMatchSnapshot(); }); @@ -267,12 +273,15 @@ describe('platform/azure', () => { azureHelper.getNewBranchName.mockImplementationOnce( () => 'refs/heads/branch-a' ); - azureHelper.getRenovatePRFormat.mockImplementationOnce(() => ({ - number: 1, - head: { ref: 'branch-a' }, - title: 'branch a pr', - state: 'closed', - })); + azureHelper.getRenovatePRFormat.mockImplementationOnce( + () => + ({ + number: 1, + head: { ref: 'branch-a' }, + title: 'branch a pr', + state: 'closed', + } as any) + ); const res = await azure.findPr('branch-a', 'branch a pr', 'closed'); expect(res).toMatchSnapshot(); }); @@ -293,12 +302,15 @@ describe('platform/azure', () => { azureHelper.getNewBranchName.mockImplementationOnce( () => 'refs/heads/branch-a' ); - azureHelper.getRenovatePRFormat.mockImplementationOnce(() => ({ - number: 1, - head: { ref: 'branch-a' }, - title: 'branch a pr', - state: 'closed', - })); + azureHelper.getRenovatePRFormat.mockImplementationOnce( + () => + ({ + number: 1, + head: { ref: 'branch-a' }, + title: 'branch a pr', + state: 'closed', + } as any) + ); const res = await azure.findPr('branch-a', 'branch a pr'); expect(res).toMatchSnapshot(); }); @@ -342,13 +354,16 @@ describe('platform/azure', () => { azureHelper.getNewBranchName.mockImplementation( () => 'refs/heads/branch-a' ); - azureHelper.getRenovatePRFormat.mockImplementation(() => ({ - pullRequestId: 1, - number: 1, - head: { ref: 'branch-a' }, - title: 'branch a pr', - isClosed: false, - })); + azureHelper.getRenovatePRFormat.mockImplementation( + () => + ({ + pullRequestId: 1, + number: 1, + head: { ref: 'branch-a' }, + title: 'branch a pr', + isClosed: false, + } as any) + ); const pr = await azure.getBranchPr('somebranch'); expect(pr).toMatchSnapshot(); }); @@ -416,10 +431,13 @@ describe('platform/azure', () => { ]), } as any) ); - azureHelper.getRenovatePRFormat.mockImplementation(() => ({ - pullRequestId: 1234, - labels: ['renovate'], - })); + azureHelper.getRenovatePRFormat.mockImplementation( + () => + ({ + pullRequestId: 1234, + labels: ['renovate'], + } as any) + ); const pr = await azure.getPr(1234); expect(pr).toMatchSnapshot(); }); @@ -438,11 +456,14 @@ describe('platform/azure', () => { createPullRequestLabel: jest.fn(() => ({})), } as any) ); - azureHelper.getRenovatePRFormat.mockImplementation(() => ({ - displayNumber: 'Pull Request #456', - number: 456, - pullRequestId: 456, - })); + azureHelper.getRenovatePRFormat.mockImplementation( + () => + ({ + displayNumber: 'Pull Request #456', + number: 456, + pullRequestId: 456, + } as any) + ); const pr = await azure.createPr( 'some-branch', 'The Title', @@ -463,11 +484,14 @@ describe('platform/azure', () => { createPullRequestLabel: jest.fn(() => ({})), } as any) ); - azureHelper.getRenovatePRFormat.mockImplementation(() => ({ - displayNumber: 'Pull Request #456', - number: 456, - pullRequestId: 456, - })); + azureHelper.getRenovatePRFormat.mockImplementation( + () => + ({ + displayNumber: 'Pull Request #456', + number: 456, + pullRequestId: 456, + } as any) + ); const pr = await azure.createPr( 'some-branch', 'The Title', @@ -507,7 +531,7 @@ describe('platform/azure', () => { updatePullRequest: updateFn, } as any) ); - azureHelper.getRenovatePRFormat.mockImplementation(x => x); + azureHelper.getRenovatePRFormat.mockImplementation(x => x as any); const pr = await azure.createPr( 'some-branch', 'The Title', diff --git a/test/platform/bitbucket-server/index.spec.ts b/test/platform/bitbucket-server/index.spec.ts index 063944356a..75dfed7b14 100644 --- a/test/platform/bitbucket-server/index.spec.ts +++ b/test/platform/bitbucket-server/index.spec.ts @@ -211,7 +211,11 @@ describe('platform/bitbucket-server', () => { it('sends to gitFs', async () => { expect.assertions(1); await initRepo(); - await bitbucket.commitFilesToBranch('some-branch', [{}], 'message'); + await bitbucket.commitFilesToBranch( + 'some-branch', + [{ name: 'test', contents: 'dummy' }], + 'message' + ); expect(api.get.mock.calls).toMatchSnapshot(); }); }); diff --git a/test/platform/gitlab/index.spec.ts b/test/platform/gitlab/index.spec.ts index 4a714d20f8..9ad8f53aa9 100644 --- a/test/platform/gitlab/index.spec.ts +++ b/test/platform/gitlab/index.spec.ts @@ -260,7 +260,7 @@ describe('platform/gitlab', () => { describe('setBaseBranch(branchName)', () => { it('sets the base branch', async () => { await initRepo(); - await gitlab.setBaseBranch('some-branch'); + await gitlab.setBaseBranch(); expect(api.get.mock.calls).toMatchSnapshot(); }); it('uses default base branch', async () => { diff --git a/test/workers/global/autodiscover.spec.ts b/test/workers/global/autodiscover.spec.ts index 0344702eab..83da940a9a 100644 --- a/test/workers/global/autodiscover.spec.ts +++ b/test/workers/global/autodiscover.spec.ts @@ -40,7 +40,7 @@ describe('lib/workers/global/autodiscover', () => { hostRules.find = jest.fn(() => ({ token: 'abc', })); - ghApi.getRepos = jest.fn(() => Promise.resolve([{}, {}])); + ghApi.getRepos = jest.fn(() => Promise.resolve(['a', 'b'])); const res = await autodiscoverRepositories(config); expect(res.repositories).toHaveLength(2); }); -- GitLab