diff --git a/lib/config/common.ts b/lib/config/common.ts index 818b311a4227cee6b417ae4a9c660d861dfbc400..b057689f3b812291f6aa60c9eb2d400fb4caa0ae 100644 --- a/lib/config/common.ts +++ b/lib/config/common.ts @@ -37,6 +37,7 @@ export interface RenovateSharedConfig { platform?: string; postUpgradeTasks?: PostUpgradeTasks; prBodyColumns?: string[]; + prBodyDefinitions?: Record<string, string>; prCreation?: 'immediate' | 'not-pending' | 'status-success' | 'approval'; productLinks?: Record<string, string>; prPriority?: number; diff --git a/lib/datasource/common.ts b/lib/datasource/common.ts index 9b9037a8866ce00caaa0a925de5358003df304fe..d9c0ce47123fdd93783d2778160b9b0f365b90d4 100644 --- a/lib/datasource/common.ts +++ b/lib/datasource/common.ts @@ -36,7 +36,10 @@ export function isGetPkgReleasesConfig( } export interface Release { + canBeUnpublished?: boolean; changelogUrl?: string; + checksumUrl?: string; + downloadUrl?: string; gitRef?: string; isDeprecated?: boolean; @@ -60,7 +63,7 @@ export interface ReleaseResult { pkgName?: string; releases: Release[]; sourceUrl?: string; - tags?: string[]; + tags?: Record<string, string>; versions?: any; } diff --git a/lib/datasource/npm/get.ts b/lib/datasource/npm/get.ts index 8510815ca3f935aa67b6e990b182f7e82413a230..f138f66a2ce3ba8d4c3f3c168e161256468ad4ae 100644 --- a/lib/datasource/npm/get.ts +++ b/lib/datasource/npm/get.ts @@ -15,7 +15,7 @@ import { getNpmrc } from './npmrc'; const http = new Http(id); -let memcache = {}; +let memcache: Record<string, string> = {}; export function resetMemCache(): void { logger.debug('resetMemCache()'); @@ -38,7 +38,7 @@ export interface NpmDependency extends ReleaseResult { latestVersion: string; sourceUrl: string; versions: Record<string, any>; - 'dist-tags': string[]; + 'dist-tags': Record<string, string>; 'renovate-config': any; sourceDirectory?: string; } diff --git a/lib/datasource/npm/releases.ts b/lib/datasource/npm/releases.ts index 1af62cafbb5cb3046df55fd9ec289ff6f0df4317..ae4edbeaef2b8394aeab7d711a576e1acdb29357 100644 --- a/lib/datasource/npm/releases.ts +++ b/lib/datasource/npm/releases.ts @@ -9,7 +9,7 @@ export async function getReleases({ if (npmrc) { setNpmrc(npmrc); } - const res: ReleaseResult = await getDependency(lookupName); + const res = await getDependency(lookupName); if (res) { res.tags = res['dist-tags']; delete res['dist-tags']; diff --git a/lib/missing.d.ts b/lib/missing.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..c5a5ccc8d5c1483b3ec6c4c8a416b5cf43f8bba8 --- /dev/null +++ b/lib/missing.d.ts @@ -0,0 +1,66 @@ +declare module 'conventional-commits-detector' { + function detector(commits: string[]): string; + export = detector; +} + +declare module 'json-dup-key-validator' { + export function validate( + jsonString: string, + allowDuplicatedKeys?: boolean + ): string | undefined; + + export function parse<T = unknown>( + jsonString: string, + allowDuplicatedKeys?: boolean + ): T; +} + +declare module 'changelog-filename-regex' { + const re: RegExp; + export = re; +} + +declare module 'linkify-markdown' { + export function linkify( + source: string, + options: Record<string, unknown> + ): string; +} + +declare module 'get-installed-path' { + interface Options { + cwd?: string; + local?: boolean; + paths?: string[]; + } + export function getInstalledPath( + arg: string, + opts?: Options + ): Promise<string>; +} + +declare module '@snyk/ruby-semver/lib/ruby/gem-version' { + export function create(version: string): any; + export function parse(version: string): any; +} + +declare module '@snyk/ruby-semver/lib/ruby/gem-requirement' { + export function parse(version: string): any; +} + +declare module '@snyk/ruby-semver' { + export function diff(a: any, b: any): string; + export function eq(a: any, b: any): boolean; + export function gt(a: any, b: any): boolean; + export function gte(a: any, b: any): boolean; + export function lte(a: any, b: any): boolean; + export function major(version: any): number; + export function maxSatisfying(version: any[], range: string): string; + export function minSatisfying(version: any[], range: string): string; + export function minor(version: any): number; + export function patch(version: any): number; + + export function prerelease(version: any): string[]; + export function satisfies(version: any, range: string): boolean; + export function valid(version: any): boolean; +} diff --git a/lib/platform/azure/__snapshots__/index.spec.ts.snap b/lib/platform/azure/__snapshots__/index.spec.ts.snap index d3ce8c6ad57481dd2543175f295599c8aceb5401..72bd61768f123f5d63d4beb909c89dd5348279b7 100644 --- a/lib/platform/azure/__snapshots__/index.spec.ts.snap +++ b/lib/platform/azure/__snapshots__/index.spec.ts.snap @@ -137,7 +137,7 @@ Object { "labels": Array [ "renovate", ], - "pullRequestId": 1234, + "number": 1234, } `; @@ -145,7 +145,7 @@ exports[`platform/azure getPr(prNo) should return a pr thats been modified 1`] = Object { "isModified": true, "labels": Array [], - "pullRequestId": 1234, + "number": 1234, } `; diff --git a/lib/platform/azure/azure-helper.ts b/lib/platform/azure/azure-helper.ts index d68dc1a2d516c0b0436f34e3a01bdcc753f75a4c..db438950f6a8a55f0c35016cc2c230de259f195e 100644 --- a/lib/platform/azure/azure-helper.ts +++ b/lib/platform/azure/azure-helper.ts @@ -4,7 +4,6 @@ import { GitPullRequestMergeStrategy, GitRef, } from 'azure-devops-node-api/interfaces/GitInterfaces'; - import { Options } from 'simple-git/promise'; import { PR_STATE_CLOSED, @@ -12,9 +11,10 @@ import { PR_STATE_OPEN, } from '../../constants/pull-requests'; import { logger } from '../../logger'; + import { HostRule } from '../../types'; -import { Pr } from '../common'; import * as azureApi from './azure-got-wrapper'; +import { AzurePr } from './types'; const mergePolicyGuid = 'fa4e907d-c16b-4a4c-9dfa-4916e5d171ab'; // Magic GUID for merge strategy policy configurations @@ -180,15 +180,15 @@ export function max4000Chars(str: string): string { return str; } -export function getRenovatePRFormat(azurePr: GitPullRequest): Pr { - const pr: Pr = azurePr as any; +export function getRenovatePRFormat(azurePr: GitPullRequest): AzurePr { + const pr: AzurePr = azurePr as any; pr.displayNumber = `Pull Request #${azurePr.pullRequestId}`; pr.number = azurePr.pullRequestId; pr.body = azurePr.description; pr.targetBranch = getBranchNameWithoutRefsheadsPrefix(azurePr.targetRefName); pr.branchName = pr.targetBranch; - pr.createdAt = pr.creationDate; + pr.createdAt = azurePr.creationDate?.toISOString(); // status // export declare enum PullRequestStatus { diff --git a/lib/platform/azure/index.spec.ts b/lib/platform/azure/index.spec.ts index 084a6c511b78866604937490d66920309d6529c5..0762a6bbd95c29b7161337590c6aa69091467b70 100644 --- a/lib/platform/azure/index.spec.ts +++ b/lib/platform/azure/index.spec.ts @@ -505,7 +505,7 @@ describe('platform/azure', () => { azureHelper.getRenovatePRFormat.mockImplementation( () => ({ - pullRequestId: 1234, + number: 1234, } as any) ); const pr = await azure.getPr(1234); @@ -542,7 +542,7 @@ describe('platform/azure', () => { azureHelper.getRenovatePRFormat.mockImplementation( () => ({ - pullRequestId: 1234, + number: 1234, isModified: false, } as any) ); diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts index 711fd0ba3d397192ec4ccba6c0d9123888633d60..9bb3700045da3632e2d8f108fa07ec4c5dff0b3d 100644 --- a/lib/platform/azure/index.ts +++ b/lib/platform/azure/index.ts @@ -2,7 +2,6 @@ import { GitPullRequest, GitPullRequestMergeStrategy, } from 'azure-devops-node-api/interfaces/GitInterfaces'; - import { RenovateConfig } from '../../config/common'; import { REPOSITORY_DISABLED } from '../../constants/error-messages'; import { PLATFORM_TYPE_AZURE } from '../../constants/platforms'; @@ -35,6 +34,7 @@ import GitStorage, { StatusResult } from '../git/storage'; import { smartTruncate } from '../utils/pr-body'; import * as azureApi from './azure-got-wrapper'; import * as azureHelper from './azure-helper'; +import { AzurePr } from './types'; interface Config { storage: GitStorage; @@ -47,7 +47,8 @@ interface Config { repoId: string; project: string; azureWorkItemId: string; - prList: Pr[]; + prList: AzurePr[]; + fileList: null; repository: string; } @@ -241,7 +242,7 @@ async function abandonPr(prNo: number): Promise<void> { ); } -export async function getPrList(): Promise<Pr[]> { +export async function getPrList(): Promise<AzurePr[]> { logger.debug('getPrList()'); if (!config.prList) { const azureApiGit = await azureApi.gitApi(); @@ -273,7 +274,7 @@ export async function getPr(pullRequestId: number): Promise<Pr | null> { return null; } const azurePr = (await getPrList()).find( - (item) => item.pullRequestId === pullRequestId + (item) => item.number === pullRequestId ); if (!azurePr) { @@ -345,7 +346,7 @@ export async function getBranchPr(branchName: string): Promise<Pr | null> { branchName, state: PR_STATE_OPEN, }); - return existingPr ? getPr(existingPr.pullRequestId) : null; + return existingPr ? getPr(existingPr.number) : null; } export /* istanbul ignore next */ async function deleteBranch( diff --git a/lib/platform/azure/types.ts b/lib/platform/azure/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..86b1282523876a6efc427d08503ec6b4aafa04f8 --- /dev/null +++ b/lib/platform/azure/types.ts @@ -0,0 +1,5 @@ +import { Pr } from '../common'; + +export interface AzurePr extends Pr { + sourceRefName?: string; +} diff --git a/lib/platform/bitbucket-server/index.spec.ts b/lib/platform/bitbucket-server/index.spec.ts index 9229a58a47f7a6d9af00bd2414d617b1f9778b51..2c90f2b2b127609e927d00b6aef8aa4213c1a72a 100644 --- a/lib/platform/bitbucket-server/index.spec.ts +++ b/lib/platform/bitbucket-server/index.spec.ts @@ -574,7 +574,7 @@ describe('platform/bitbucket-server', () => { it('posts PR', async () => { expect.assertions(3); await initRepo(); - const { id } = await bitbucket.createPr({ + const { number: id } = await bitbucket.createPr({ branchName: 'branch', prTitle: 'title', prBody: 'body', @@ -587,7 +587,7 @@ describe('platform/bitbucket-server', () => { it('posts PR default branch', async () => { expect.assertions(3); await initRepo(); - const { id } = await bitbucket.createPr({ + const { number: id } = await bitbucket.createPr({ branchName: 'branch', prTitle: 'title', prBody: 'body', diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts index 3cdd5b269b077594f71a5b39d36f9b69af0e34f6..d5af7775967becffc93a1b4d13dada0110bbb713 100644 --- a/lib/platform/bitbucket-server/index.ts +++ b/lib/platform/bitbucket-server/index.ts @@ -1,6 +1,5 @@ import url, { URLSearchParams } from 'url'; import delay from 'delay'; - import { RenovateConfig } from '../../config/common'; import { REPOSITORY_CHANGED, @@ -34,7 +33,9 @@ import { import GitStorage, { StatusResult } from '../git/storage'; import { smartTruncate } from '../utils/pr-body'; import { api } from './bb-got-wrapper'; +import { BbbsRestPr, BbsConfig, BbsPr, BbsRestUserRef } from './types'; import * as utils from './utils'; +import { PartialDeep } from 'type-fest'; /* * Version: 5.3 (EOL Date: 15 Aug 2019) * See following docs for api information: @@ -45,23 +46,6 @@ import * as utils from './utils'; * https://confluence.atlassian.com/support/atlassian-support-end-of-life-policy-201851003.html#AtlassianSupportEndofLifePolicy-BitbucketServer */ -interface BbsConfig { - baseBranch: string; - bbUseDefaultReviewers: boolean; - defaultBranch: string; - mergeMethod: string; - owner: string; - prList: Pr[]; - projectKey: string; - repository: string; - repositorySlug: string; - storage: GitStorage; - - prVersions: Map<number, number>; - - username: string; -} - let config: BbsConfig = {} as any; const defaults: any = { @@ -293,7 +277,7 @@ export function isBranchStale(branchName: string): Promise<boolean> { export async function getPr( prNo: number, refreshCache?: boolean -): Promise<Pr | null> { +): Promise<BbsPr | null> { logger.debug(`getPr(${prNo})`); if (!prNo) { return null; @@ -304,11 +288,11 @@ export async function getPr( { useCache: !refreshCache } ); - const pr: any = { + const pr: BbsPr = { displayNumber: `Pull Request #${res.body.id}`, ...utils.prInfo(res.body), reviewers: res.body.reviewers.map( - (r: { user: { name: any } }) => r.user.name + (r: { user: { name: string } }) => r.user.name ), isModified: false, }; @@ -426,7 +410,7 @@ export async function findPr({ export async function getBranchPr( branchName: string, refreshCache?: boolean -): Promise<Pr | null> { +): Promise<BbsPr | null> { logger.debug(`getBranchPr(${branchName})`); const existingPr = await findPr({ branchName, @@ -915,19 +899,19 @@ export async function createPr({ const description = sanitize(rawDescription); logger.debug(`createPr(${branchName}, title=${title})`); const base = useDefaultBranch ? config.defaultBranch : config.baseBranch; - let reviewers = []; + let reviewers: BbsRestUserRef[] = []; /* istanbul ignore else */ if (config.bbUseDefaultReviewers) { logger.debug(`fetching default reviewers`); const { id } = ( - await api.get( + await api.get<{ id: number }>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}` ) ).body; const defReviewers = ( - await api.get( + await api.get<{ name: string }[]>( `./rest/default-reviewers/1.0/projects/${config.projectKey}/repos/${ config.repositorySlug }/reviewers?sourceRefId=refs/heads/${escapeHash( @@ -936,12 +920,12 @@ export async function createPr({ ) ).body; - reviewers = defReviewers.map((u: { name: string }) => ({ + reviewers = defReviewers.map((u) => ({ user: { name: u.name }, })); } - const body = { + const body: PartialDeep<BbbsRestPr> = { title, description, fromRef: { @@ -952,9 +936,9 @@ export async function createPr({ }, reviewers, }; - let prInfoRes: GotResponse; + let prInfoRes: GotResponse<BbbsRestPr>; try { - prInfoRes = await api.post( + prInfoRes = await api.post<BbbsRestPr>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests`, { body } ); @@ -975,8 +959,7 @@ export async function createPr({ throw err; } - const pr: Pr = { - id: prInfoRes.body.id, + const pr: BbsPr = { displayNumber: `Pull Request #${prInfoRes.body.id}`, isModified: false, ...utils.prInfo(prInfoRes.body), diff --git a/lib/platform/bitbucket-server/types.ts b/lib/platform/bitbucket-server/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..aafd4b7dbac115fb7388a0e100c33cecd54770d6 --- /dev/null +++ b/lib/platform/bitbucket-server/types.ts @@ -0,0 +1,55 @@ +import { Pr } from '../common'; +import GitStorage from '../git/storage'; + +export interface BbsConfig { + baseBranch: string; + bbUseDefaultReviewers: boolean; + defaultBranch: string; + fileList: any[]; + mergeMethod: string; + owner: string; + prList: BbsPr[]; + projectKey: string; + repository: string; + repositorySlug: string; + storage: GitStorage; + + prVersions: Map<number, number>; + + username: string; +} + +export interface BbsPr extends Pr { + version?: number; +} + +export enum BbsRestPrState { + Declined = 'DECLINED', + Open = 'OPEN', + Merged = 'MERGED', +} + +export interface BbsRestBranchRef { + displayId: string; + id: string; +} + +export interface BbsRestUser { + name: string; +} + +export interface BbsRestUserRef { + user: BbsRestUser; +} + +export interface BbbsRestPr { + createdDate: string; + description: string; + fromRef: BbsRestBranchRef; + id: number; + reviewers: BbsRestUserRef[]; + state: BbsRestPrState; + title: string; + toRef: BbsRestBranchRef; + version?: number; +} diff --git a/lib/platform/bitbucket-server/utils.ts b/lib/platform/bitbucket-server/utils.ts index 89c9d60f60ad22bafeb78cbe22cc4e3ed3bdd4cf..d9982c79c2ecb93ea540ce70f5ebc9d042b334eb 100644 --- a/lib/platform/bitbucket-server/utils.ts +++ b/lib/platform/bitbucket-server/utils.ts @@ -5,8 +5,8 @@ import { PR_STATE_MERGED, PR_STATE_OPEN, } from '../../constants/pull-requests'; -import { Pr } from '../common'; import { api } from './bb-got-wrapper'; +import { BbbsRestPr, BbsPr } from './types'; // https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html#idp250 const prStateMapping: any = { @@ -15,7 +15,7 @@ const prStateMapping: any = { OPEN: PR_STATE_OPEN, }; -export function prInfo(pr: any): Pr { +export function prInfo(pr: BbbsRestPr): BbsPr { return { version: pr.version, number: pr.id, diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts index 45f13da74f5bc1e9f59909e218471012d6895b38..39f1fa85a0803041a1edd2caefb322dcbb0f5425 100644 --- a/lib/platform/bitbucket/index.ts +++ b/lib/platform/bitbucket/index.ts @@ -729,7 +729,7 @@ export async function createPr({ logger.debug({ repository: config.repository, title, base }, 'Creating PR'); - let reviewers = []; + let reviewers: { uuid: { raw: string } }[] = []; if (config.bbUseDefaultReviewers) { const reviewersResponse = ( diff --git a/lib/platform/common.ts b/lib/platform/common.ts index a561651e6ffb11129b61705f08a10334a481cd8d..6690e178b4b16c901b92714640aea818921ddf37 100644 --- a/lib/platform/common.ts +++ b/lib/platform/common.ts @@ -1,7 +1,12 @@ import got from 'got'; import Git from 'simple-git/promise'; import { RenovateConfig } from '../config/common'; -import { BranchStatus } from '../types'; +import { + BranchStatus, + VulnerabilityAlert as _VulnerabilityAlert, +} from '../types'; + +export type VulnerabilityAlert = _VulnerabilityAlert; /** * File to commit to branch @@ -93,15 +98,27 @@ export interface RepoParams { } /** - * TODO: Proper typing + * */ -export type Pr = { +export interface Pr { + body?: string; branchName: string; - title: string; - state: string; + canMerge?: boolean; + canMergeReason?: string; + createdAt?: string; + displayNumber?: string; isConflicted?: boolean; isModified?: boolean; -} & Record<string, any>; + isStale?: boolean; + labels?: string[]; + number?: number; + reviewers?: string[]; + sha?: string; + sourceRepo?: string; + state: string; + targetBranch?: string; + title: string; +} /** * TODO: Proper typing @@ -154,10 +171,6 @@ export interface EnsureCommentRemovalConfig { topic?: string; content?: string; } -/** - * TODO: Proper typing - */ -export type VulnerabilityAlert = any; export type EnsureIssueResult = 'updated' | 'created'; diff --git a/lib/platform/gitea/__snapshots__/index.spec.ts.snap b/lib/platform/gitea/__snapshots__/index.spec.ts.snap index 3eb0dd25a0cda84efaaced7db72dec90314d5baf..c79019e9522ac5e3af413ad9fadfb25e013f7f4b 100644 --- a/lib/platform/gitea/__snapshots__/index.spec.ts.snap +++ b/lib/platform/gitea/__snapshots__/index.spec.ts.snap @@ -5,7 +5,6 @@ Object { "body": "pr-body", "branchName": "pr-branch", "canMerge": true, - "closedAt": "2017-12-28T12:17:48Z", "createdAt": "2014-04-01T05:14:20Z", "displayNumber": "Pull Request #42", "isConflicted": false, @@ -25,7 +24,6 @@ Object { "body": "pr-body", "branchName": "pr-branch", "canMerge": true, - "closedAt": "2017-12-28T12:17:48Z", "createdAt": "2014-04-01T05:14:20Z", "displayNumber": "Pull Request #42", "isConflicted": false, @@ -45,7 +43,6 @@ Object { "body": "some random pull request", "branchName": "some-head-branch", "canMerge": true, - "closedAt": null, "createdAt": "2015-03-22T20:36:16Z", "displayNumber": "Pull Request #1", "isConflicted": false, @@ -65,7 +62,6 @@ Object { "body": "some random pull request", "branchName": "some-head-branch", "canMerge": true, - "closedAt": null, "createdAt": "2015-03-22T20:36:16Z", "displayNumber": "Pull Request #1", "isConflicted": false, @@ -86,7 +82,6 @@ Array [ "body": "some random pull request", "branchName": "some-head-branch", "canMerge": true, - "closedAt": null, "createdAt": "2015-03-22T20:36:16Z", "displayNumber": "Pull Request #1", "isConflicted": false, @@ -103,7 +98,6 @@ Array [ "body": "other random pull request", "branchName": "other-head-branch", "canMerge": true, - "closedAt": "2016-01-09T10:03:21Z", "createdAt": "2011-08-18T22:30:38Z", "displayNumber": "Pull Request #2", "isConflicted": false, diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts index e50378ddf0bb80551886fe28ed9e9deaf42fa585..ff00f8d0aae0f9d204d04eea7fa04a22a2632740 100644 --- a/lib/platform/gitea/index.ts +++ b/lib/platform/gitea/index.ts @@ -103,7 +103,6 @@ function toRenovatePR(data: helper.PR): Pr | null { targetBranch: data.base.ref, sourceRepo: data.head.repo.full_name, createdAt: data.created_at, - closedAt: data.closed_at, canMerge: data.mergeable, isConflicted: !data.mergeable, isStale: undefined, diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index 9a1e7d5be4647732a393087bfef798f7ccd19316..636d2fe811ae4fb7f4a0e62bbb9cbc30c2d054a8 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -1,7 +1,6 @@ import URL from 'url'; import is from '@sindresorhus/is'; import delay from 'delay'; - import { configFileNames } from '../../config/app-strings'; import { PLATFORM_FAILURE, @@ -39,6 +38,7 @@ import { FindPRConfig, Issue, PlatformConfig, + Pr, RepoConfig, RepoParams, VulnerabilityAlert, @@ -47,60 +47,18 @@ import GitStorage, { StatusResult } from '../git/storage'; import { smartTruncate } from '../utils/pr-body'; import { api } from './gh-got-wrapper'; import { getGraphqlNodes } from './gh-graphql-wrapper'; +import { + BranchProtection, + CombinedBranchStatus, + Comment, + GhBranchStatus, + GhPr, + LocalRepoConfig, + PrList, +} from './types'; const defaultConfigFile = configFileNames[0]; -interface Comment { - id: number; - body: string; -} - -interface Pr { - displayNumber: string; - state: string; - title: string; - branchName: string; - number: number; - comments: Comment[]; - - createdAt: string; - - sha: string; - - sourceRepo: string; - isModified: boolean; -} - -interface LocalRepoConfig { - repositoryName: string; - pushProtection: boolean; - prReviewsRequired: boolean; - repoForceRebase?: boolean; - storage: GitStorage; - parentRepo: string; - baseCommitSHA: string | null; - forkMode?: boolean; - forkToken?: string; - closedPrList: PrList | null; - openPrList: PrList | null; - prList: Pr[] | null; - issueList: any[] | null; - mergeMethod: string; - baseBranch: string; - defaultBranch: string; - enterpriseVersion: string; - gitPrivateKey?: string; - repositoryOwner: string; - repository: string | null; - localDir: string; - isGhe: boolean; - renovateUsername: string; - productLinks: any; -} - -type BranchProtection = any; -type PrList = Record<number, Pr>; - let config: LocalRepoConfig = {} as any; const defaults = { @@ -1063,20 +1021,6 @@ export async function getBranchPr(branchName: string): Promise<Pr | null> { return existingPr ? getPr(existingPr.number) : null; } -// https://developer.github.com/v3/repos/statuses -// https://developer.github.com/v3/checks/runs/ -type BranchState = 'failure' | 'pending' | 'success'; - -interface GhBranchStatus { - context: string; - state: BranchState | 'error'; -} - -interface CombinedBranchStatus { - state: BranchState; - statuses: GhBranchStatus[]; -} - async function getStatus( branchName: string, useCache = true @@ -1104,7 +1048,7 @@ export async function getBranchStatus( logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`); return BranchStatus.red; } - let commitStatus; + let commitStatus: CombinedBranchStatus; try { commitStatus = await getStatus(branchName); } catch (err) /* istanbul ignore next */ { @@ -1672,7 +1616,7 @@ export async function createPr({ } logger.debug({ title, head, base }, 'Creating PR'); const pr = ( - await api.post<Pr>( + await api.post<GhPr>( `repos/${config.parentRepo || config.repository}/pulls`, options ) diff --git a/lib/platform/github/types.ts b/lib/platform/github/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..a4f6ea91b6e091bc8fb89401ca0b63f2d7ff24ed --- /dev/null +++ b/lib/platform/github/types.ts @@ -0,0 +1,56 @@ +import { Pr } from '../common'; +import GitStorage from '../git/storage'; + +// https://developer.github.com/v3/repos/statuses +// https://developer.github.com/v3/checks/runs/ +export type CombinedBranchState = 'failure' | 'pending' | 'success'; +export type BranchState = 'failure' | 'pending' | 'success' | 'error'; + +export interface GhBranchStatus { + context: string; + state: BranchState; +} + +export interface CombinedBranchStatus { + state: CombinedBranchState; + statuses: GhBranchStatus[]; +} + +export interface Comment { + id: number; + body: string; +} + +export interface GhPr extends Pr { + comments: Comment[]; +} + +export interface LocalRepoConfig { + repositoryName: string; + pushProtection: boolean; + prReviewsRequired: boolean; + repoForceRebase?: boolean; + storage: GitStorage; + parentRepo: string; + baseCommitSHA: string | null; + forkMode?: boolean; + forkToken?: string; + closedPrList: PrList | null; + openPrList: PrList | null; + prList: GhPr[] | null; + issueList: any[] | null; + mergeMethod: string; + baseBranch: string; + defaultBranch: string; + enterpriseVersion: string; + gitPrivateKey?: string; + repositoryOwner: string; + repository: string | null; + localDir: string; + isGhe: boolean; + renovateUsername: string; + productLinks: any; +} + +export type BranchProtection = any; +export type PrList = Record<number, GhPr>; diff --git a/lib/types/index.ts b/lib/types/index.ts index fbc1cdb92d312aefe040d0f375a72ce36a2b4480..05321e3056e3bbe0afd07eb4d9a090ffcf451bef 100644 --- a/lib/types/index.ts +++ b/lib/types/index.ts @@ -2,3 +2,4 @@ export * from './host-rules'; export * from './skip-reason'; export * from './versioning'; export * from './branch-status'; +export * from './vulnerability-alert'; diff --git a/lib/types/vulnerability-alert.ts b/lib/types/vulnerability-alert.ts new file mode 100644 index 0000000000000000000000000000000000000000..be512c37aec39d0ef4196f469f742d94ed2be56e --- /dev/null +++ b/lib/types/vulnerability-alert.ts @@ -0,0 +1,23 @@ +export interface VulnerabilityPackage { + ecosystem: 'MAVEN' | 'NPM' | 'NUGET' | 'PIP' | 'RUBYGEMS' | string; + name: string; +} +export interface SecurityVulnerability { + firstPatchedVersion?: { identifier: string }; + package: VulnerabilityPackage; + vulnerableVersionRange: string; +} +export interface SecurityAdvisory { + description?: string; + identifiers?: { type: string; value: string }[]; + references: { url: string }[]; + severity: 'HIGH' | 'MODERATE' | string; +} +export interface VulnerabilityAlert { + dismissReason?: string | null; + securityAdvisory: SecurityAdvisory; + securityVulnerability: SecurityVulnerability; + vulnerableManifestFilename: string; + vulnerableManifestPath: string; + vulnerableRequirements?: string; +} diff --git a/lib/util/regex.ts b/lib/util/regex.ts index 08aeebe210e12c2937dddb533f9bfa30a9806381..d1e7aa9559a9c56502372dc6711f81d41ea513f9 100644 --- a/lib/util/regex.ts +++ b/lib/util/regex.ts @@ -1,7 +1,7 @@ import { CONFIG_VALIDATION } from '../constants/error-messages'; import { logger } from '../logger'; -let RegEx; +let RegEx: RegExpConstructor; try { // eslint-disable-next-line diff --git a/lib/workers/branch/auto-replace.spec.ts b/lib/workers/branch/auto-replace.spec.ts index d2c35d71b0046893463be80d7bfc1ff6d8bb19da..bd0ee1f1393f41981a7cce7f7152dad425679222 100644 --- a/lib/workers/branch/auto-replace.spec.ts +++ b/lib/workers/branch/auto-replace.spec.ts @@ -1,8 +1,8 @@ import { readFileSync } from 'fs'; import { resolve } from 'path'; import { defaultConfig } from '../../../test/util'; -import { RenovateConfig } from '../../config'; import { extractPackageFile } from '../../manager/html'; +import { BranchUpgradeConfig } from '../common'; import { doAutoReplace } from './auto-replace'; const sampleHtml = readFileSync( @@ -14,8 +14,8 @@ jest.mock('../../util/fs'); describe('workers/branch/auto-replace', () => { describe('doAutoReplace', () => { - let parentBranch; - let upgrade: RenovateConfig; + let parentBranch: string; + let upgrade: BranchUpgradeConfig; beforeEach(() => { upgrade = { ...JSON.parse(JSON.stringify(defaultConfig)), diff --git a/lib/workers/branch/auto-replace.ts b/lib/workers/branch/auto-replace.ts index ae075e7315824a8fba3977add59aa5c334a25c33..eb5259a26ad2ce5f8a83965b3ee132109834f093 100644 --- a/lib/workers/branch/auto-replace.ts +++ b/lib/workers/branch/auto-replace.ts @@ -1,13 +1,15 @@ import { WORKER_FILE_UPDATE_FAILED } from '../../constants/error-messages'; import { logger } from '../../logger'; import { get } from '../../manager'; +import { PackageDependency } from '../../manager/common'; import { writeLocalFile } from '../../util/fs'; import { escapeRegExp, regEx } from '../../util/regex'; import { matchAt, replaceAt } from '../../util/string'; import { compile } from '../../util/template'; +import { BranchUpgradeConfig } from '../common'; export async function confirmIfDepUpdated( - upgrade, + upgrade: BranchUpgradeConfig, newContent: string ): Promise<boolean> { const { @@ -62,13 +64,13 @@ export async function confirmIfDepUpdated( return false; } -function getDepsSignature(deps): string { +function getDepsSignature(deps: PackageDependency[]): string { return deps.map((dep) => `${dep.depName}${dep.lookupName}`).join(','); } export async function checkBranchDepsMatchBaseDeps( - upgrade, - branchContent + upgrade: BranchUpgradeConfig, + branchContent: string ): Promise<boolean> { const { baseDeps, manager, packageFile } = upgrade; const extractPackageFile = get(manager, 'extractPackageFile'); @@ -86,7 +88,7 @@ export async function checkBranchDepsMatchBaseDeps( } export async function doAutoReplace( - upgrade, + upgrade: BranchUpgradeConfig, existingContent: string, parentBranch: string | null ): Promise<string | null> { diff --git a/lib/workers/branch/get-updated.spec.ts b/lib/workers/branch/get-updated.spec.ts index d3ab1cfdf80d8b9c1cfaf53bb63e9f66e4a85e19..74b6b6308c21d2051302a46b75ce6f388b0e3665 100644 --- a/lib/workers/branch/get-updated.spec.ts +++ b/lib/workers/branch/get-updated.spec.ts @@ -3,6 +3,7 @@ import * as datasourceGitSubmodules from '../../datasource/git-submodules'; import * as _composer from '../../manager/composer'; import * as _gitSubmodules from '../../manager/git-submodules'; import * as _npm from '../../manager/npm'; +import { BranchConfig } from '../common'; import * as _autoReplace from './auto-replace'; import { getUpdatedPackageFiles } from './get-updated'; @@ -18,35 +19,35 @@ jest.mock('./auto-replace'); describe('workers/branch/get-updated', () => { describe('getUpdatedPackageFiles()', () => { - let config; + let config: BranchConfig; beforeEach(() => { config = { ...defaultConfig, upgrades: [], - }; + } as never; npm.updateDependency = jest.fn(); platform.getFile.mockResolvedValueOnce('existing content'); }); it('handles autoreplace base updated', async () => { - config.upgrades.push({ manager: 'html' }); + config.upgrades.push({ manager: 'html', branchName: undefined }); autoReplace.doAutoReplace.mockResolvedValueOnce('updated-file'); const res = await getUpdatedPackageFiles(config); expect(res).toMatchSnapshot(); }); it('handles autoreplace branch no update', async () => { - config.upgrades.push({ manager: 'html' }); + config.upgrades.push({ manager: 'html', branchName: undefined }); autoReplace.doAutoReplace.mockResolvedValueOnce('existing content'); const res = await getUpdatedPackageFiles(config); expect(res).toMatchSnapshot(); }); it('handles autoreplace failure', async () => { - config.upgrades.push({ manager: 'html' }); + config.upgrades.push({ manager: 'html', branchName: undefined }); autoReplace.doAutoReplace.mockResolvedValueOnce(null); await expect(getUpdatedPackageFiles(config)).rejects.toThrow(); }); it('handles autoreplace branch needs update', async () => { config.parentBranch = 'some branch'; - config.upgrades.push({ manager: 'html' }); + config.upgrades.push({ manager: 'html', branchName: undefined }); autoReplace.doAutoReplace.mockResolvedValueOnce(null); autoReplace.doAutoReplace.mockResolvedValueOnce('updated-file'); const res = await getUpdatedPackageFiles(config); @@ -60,14 +61,14 @@ describe('workers/branch/get-updated', () => { config.parentBranch = 'some-branch'; config.upgrades.push({ manager: 'npm', - }); + } as never); await expect(getUpdatedPackageFiles(config)).rejects.toThrow(); }); it('handles content change', async () => { config.parentBranch = 'some-branch'; config.upgrades.push({ manager: 'npm', - }); + } as never); npm.updateDependency.mockReturnValue('some new content'); const res = await getUpdatedPackageFiles(config); expect(res).toMatchSnapshot(); @@ -76,6 +77,7 @@ describe('workers/branch/get-updated', () => { config.parentBranch = 'some-branch'; config.upgrades.push({ manager: 'composer', + branchName: undefined, }); autoReplace.doAutoReplace.mockResolvedValueOnce('some new content'); composer.updateArtifacts.mockResolvedValueOnce([ @@ -94,7 +96,7 @@ describe('workers/branch/get-updated', () => { config.upgrades.push({ manager: 'composer', updateType: 'lockFileMaintenance', - }); + } as never); composer.updateArtifacts.mockResolvedValueOnce([ { file: { @@ -111,7 +113,7 @@ describe('workers/branch/get-updated', () => { config.upgrades.push({ manager: 'composer', updateType: 'lockFileMaintenance', - }); + } as never); composer.updateArtifacts.mockResolvedValueOnce([ { artifactError: { @@ -127,6 +129,7 @@ describe('workers/branch/get-updated', () => { config.parentBranch = 'some-branch'; config.upgrades.push({ manager: 'composer', + branchName: undefined, }); autoReplace.doAutoReplace.mockResolvedValueOnce('some new content'); composer.updateArtifacts.mockResolvedValueOnce([ @@ -144,7 +147,7 @@ describe('workers/branch/get-updated', () => { config.upgrades.push({ manager: 'git-submodules', datasource: datasourceGitSubmodules.id, - }); + } as never); gitSubmodules.updateDependency.mockResolvedValueOnce('existing content'); const res = await getUpdatedPackageFiles(config); expect(res).toMatchSnapshot(); diff --git a/lib/workers/branch/lock-files/index.spec.ts b/lib/workers/branch/lock-files/index.spec.ts index 62d6314e066c4de63068b61c1a8f1bb166a676d1..5ee5f65fe4007a0bcb9f5eb7f516b78a37ed7161 100644 --- a/lib/workers/branch/lock-files/index.spec.ts +++ b/lib/workers/branch/lock-files/index.spec.ts @@ -1,6 +1,7 @@ import _fs from 'fs-extra'; import { mocked } from '../../../../test/util'; import { getConfig } from '../../../config/defaults'; +import { PostUpdateConfig } from '../../../manager/common'; import * as _lockFiles from '../../../manager/npm/post-update'; import * as _lerna from '../../../manager/npm/post-update/lerna'; import * as _npm from '../../../manager/npm/post-update/npm'; @@ -256,7 +257,7 @@ describe('manager/npm/post-update', () => { }); */ describe('writeUpdatedPackageFiles', () => { - let config; + let config: PostUpdateConfig; beforeEach(() => { config = { ...defaultConfig, @@ -298,7 +299,7 @@ describe('manager/npm/post-update', () => { }); }); describe('getAdditionalFiles', () => { - let config; + let config: PostUpdateConfig; beforeEach(() => { config = { ...defaultConfig, diff --git a/lib/workers/branch/lock-files/npm.spec.ts b/lib/workers/branch/lock-files/npm.spec.ts index 97e7f952dac4e1de12bf9065dcec4fd7187956c6..d54be72105bde169f74615ec9669c27e93aa43e7 100644 --- a/lib/workers/branch/lock-files/npm.spec.ts +++ b/lib/workers/branch/lock-files/npm.spec.ts @@ -1,7 +1,7 @@ import { exec as _exec } from 'child_process'; import path from 'path'; import _fs from 'fs-extra'; -import { getInstalledPath } from 'get-installed-path'; +import { getInstalledPath as _getInstalledPath } from 'get-installed-path'; import { envMock, mockExecAll } from '../../../../test/execUtil'; import { mocked } from '../../../../test/util'; import * as npmHelper from '../../../manager/npm/post-update/npm'; @@ -13,6 +13,7 @@ jest.mock('child_process'); jest.mock('../../../util/exec/env'); jest.mock('get-installed-path'); +const getInstalledPath: jest.Mock<string> = _getInstalledPath as never; getInstalledPath.mockImplementation(() => null); const exec: jest.Mock<typeof _exec> = _exec as any; const env = mocked(_env); diff --git a/lib/workers/branch/lock-files/pnpm.spec.ts b/lib/workers/branch/lock-files/pnpm.spec.ts index 98a0084b40bdc560621a6281254ebb167847d7d6..2069352e4c251f297a7727b88103e232f25d9180 100644 --- a/lib/workers/branch/lock-files/pnpm.spec.ts +++ b/lib/workers/branch/lock-files/pnpm.spec.ts @@ -1,8 +1,9 @@ import { exec as _exec } from 'child_process'; import _fs from 'fs-extra'; -import { getInstalledPath } from 'get-installed-path'; +import { getInstalledPath as _getInstalledPath } from 'get-installed-path'; import { envMock, mockExecAll } from '../../../../test/execUtil'; import { mocked } from '../../../../test/util'; +import { PostUpdateConfig } from '../../../manager/common'; import * as _pnpmHelper from '../../../manager/npm/post-update/pnpm'; import { BinarySource } from '../../../util/exec/common'; import * as _env from '../../../util/exec/env'; @@ -12,6 +13,7 @@ jest.mock('child_process'); jest.mock('../../../util/exec/env'); jest.mock('get-installed-path'); +const getInstalledPath: jest.Mock<string> = _getInstalledPath as never; getInstalledPath.mockImplementation(() => null); const exec: jest.Mock<typeof _exec> = _exec as any; @@ -20,7 +22,7 @@ const fs = mocked(_fs); const pnpmHelper = mocked(_pnpmHelper); describe('generateLockFile', () => { - let config; + let config: PostUpdateConfig; beforeEach(() => { config = { cacheDir: 'some-cache-dir' }; env.getChildProcessEnv.mockReturnValue(envMock.basic); diff --git a/lib/workers/branch/lock-files/yarn.spec.ts b/lib/workers/branch/lock-files/yarn.spec.ts index 6dcbf1afb35eb9cef990b2b0c3f81d7eca1d63d3..cac97c2475f7dc702f00c4a0816db9db928fd2bd 100644 --- a/lib/workers/branch/lock-files/yarn.spec.ts +++ b/lib/workers/branch/lock-files/yarn.spec.ts @@ -1,6 +1,6 @@ import { exec as _exec } from 'child_process'; import _fs from 'fs-extra'; -import { getInstalledPath } from 'get-installed-path'; +import { getInstalledPath as _getInstalledPath } from 'get-installed-path'; import { ExecSnapshots, envMock, mockExecAll } from '../../../../test/execUtil'; import { getName, mocked } from '../../../../test/util'; import * as _yarnHelper from '../../../manager/npm/post-update/yarn'; @@ -12,6 +12,7 @@ jest.mock('child_process'); jest.mock('../../../util/exec/env'); jest.mock('get-installed-path'); +const getInstalledPath: jest.Mock<string> = _getInstalledPath as never; getInstalledPath.mockImplementation(() => null); const exec: jest.Mock<typeof _exec> = _exec as any; diff --git a/lib/workers/branch/schedule.spec.ts b/lib/workers/branch/schedule.spec.ts index fcc6f51536368b985d1d22b6daf24a4ae1d801a9..1a7655a71edff7d8c0ceddc5af706bbd356841da 100644 --- a/lib/workers/branch/schedule.spec.ts +++ b/lib/workers/branch/schedule.spec.ts @@ -1,4 +1,5 @@ import mockDate from 'mockdate'; +import { RenovateConfig } from '../../config'; import * as schedule from './schedule'; describe('workers/branch/schedule', () => { @@ -98,7 +99,7 @@ describe('workers/branch/schedule', () => { }); }); describe('isScheduledNow(config)', () => { - let config; + let config: RenovateConfig; beforeEach(() => { mockDate.set('2017-06-30T10:50:00.000'); // Locally 2017-06-30 10:50am jest.resetAllMocks(); @@ -109,7 +110,7 @@ describe('workers/branch/schedule', () => { expect(res).toBe(true); }); it('returns true if at any time', () => { - config.schedule = 'at any time'; + config.schedule = 'at any time' as never; const res = schedule.isScheduledNow(config); expect(res).toBe(true); }); @@ -140,7 +141,7 @@ describe('workers/branch/schedule', () => { expect(res).toBe(false); }); it('massages string', () => { - config.schedule = 'before 4:00am'; + config.schedule = 'before 4:00am' as never; const res = schedule.isScheduledNow(config); expect(res).toBe(false); }); diff --git a/lib/workers/branch/schedule.ts b/lib/workers/branch/schedule.ts index a81981d79fd4bf42c75b953c9e0bb1f221cb2de5..56f4a5f4e5e6c5ade0ad6f5d05a4d5a5be818c92 100644 --- a/lib/workers/branch/schedule.ts +++ b/lib/workers/branch/schedule.ts @@ -1,9 +1,10 @@ import is from '@sindresorhus/is'; import later from 'later'; import moment from 'moment-timezone'; +import { RenovateConfig } from '../../config'; import { logger } from '../../logger'; -const scheduleMappings = { +const scheduleMappings: Record<string, string> = { 'every month': 'before 3am on the first day of the month', monthly: 'before 3am on the first day of the month', }; @@ -65,14 +66,14 @@ export function hasValidSchedule( return [true, '']; } -export function isScheduledNow(config): boolean { +export function isScheduledNow(config: RenovateConfig): boolean { let configSchedule = config.schedule; logger.debug(`Checking schedule(${configSchedule}, ${config.timezone})`); if ( !configSchedule || configSchedule.length === 0 || configSchedule[0] === '' || - configSchedule === 'at any time' || + configSchedule === ('at any time' as never) || configSchedule[0] === 'at any time' ) { logger.debug('No schedule defined'); diff --git a/lib/workers/common.ts b/lib/workers/common.ts index 53eec7aefacd2159745bf7b9c6caab3e5a2a9c5b..d1c95cbbad90159d38e9de35187b8df05bb22dac 100644 --- a/lib/workers/common.ts +++ b/lib/workers/common.ts @@ -21,6 +21,8 @@ export interface BranchUpgradeConfig Partial<LookupUpdate>, RenovateSharedConfig { artifactErrors?: ArtifactError[]; + autoReplaceStringTemplate?: string; + baseDeps?: PackageDependency[]; branchName: string; commitBody?: string; commitMessage?: string; @@ -31,6 +33,7 @@ export interface BranchUpgradeConfig currentVersion?: string; endpoint?: string; excludeCommitPaths?: string[]; + githubName?: string; group?: GroupConfig; groupName?: string; @@ -47,6 +50,7 @@ export interface BranchUpgradeConfig prTitle?: string; releases?: Release[]; releaseTimestamp?: string; + repoName?: string; sourceDirectory?: string; @@ -87,11 +91,13 @@ export interface BranchConfig extends BranchUpgradeConfig, RenovateAdminConfig, PlatformPrOptions { + automergeComment?: string; automergeType?: string; baseBranch?: string; canBeUnpublished?: boolean; errors?: ValidationMessage[]; hasTypes?: boolean; + masterIssueChecks?: Record<string, string>; releaseTimestamp?: string; res?: ProcessBranchResult; diff --git a/lib/workers/global/autodiscover.spec.ts b/lib/workers/global/autodiscover.spec.ts index 16a9fae2c103628758f72d4fb53462439a50e497..4023c2c4d4b821a211c2d6c8b1589f59bfa88baf 100644 --- a/lib/workers/global/autodiscover.spec.ts +++ b/lib/workers/global/autodiscover.spec.ts @@ -1,3 +1,4 @@ +import { RenovateConfig } from '../../config'; import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms'; import * as platform from '../../platform'; import * as _ghApi from '../../platform/github'; @@ -12,7 +13,7 @@ const hostRules = _hostRules; const ghApi: jest.Mocked<typeof _ghApi> = _ghApi as never; describe('lib/workers/global/autodiscover', () => { - let config; + let config: RenovateConfig; beforeEach(async () => { jest.resetAllMocks(); config = {}; diff --git a/lib/workers/pr/changelog/release-notes.spec.ts b/lib/workers/pr/changelog/release-notes.spec.ts index 5c5846d9178ff8e5328c7d5ece1636429e66a9d8..33f2bf50977cb03b85e708da7b909d6f1187bc2a 100644 --- a/lib/workers/pr/changelog/release-notes.spec.ts +++ b/lib/workers/pr/changelog/release-notes.spec.ts @@ -1,5 +1,6 @@ import fs from 'fs-extra'; import got from '../../../util/got'; +import { ChangeLogNotes } from './common'; import { addReleaseNotes, getReleaseNotes, @@ -186,8 +187,8 @@ describe('workers/pr/release-notes', () => { expect(res).toMatchSnapshot(); }); describe('ReleaseNotes Correctness', () => { - let versionOneNotes; - let versionTwoNotes; + let versionOneNotes: ChangeLogNotes; + let versionTwoNotes: ChangeLogNotes; it('parses yargs 15.3.0', async () => { ghGot .mockResolvedValueOnce({ body: contentsResponse }) diff --git a/lib/workers/pr/index.spec.ts b/lib/workers/pr/index.spec.ts index 73e59842e3053f63fa525625ed796ad4e97bba5c..ef07b1d19eb291b8e74a2337fe92b97dbc95867c 100644 --- a/lib/workers/pr/index.spec.ts +++ b/lib/workers/pr/index.spec.ts @@ -1,9 +1,9 @@ -import { mocked } from '../../../test/util'; +import { mocked, partial } from '../../../test/util'; import { getConfig } from '../../config/defaults'; import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms'; import { Pr, platform as _platform } from '../../platform'; import { BranchStatus } from '../../types'; -import { PrResult } from '../common'; +import { BranchConfig, PrResult } from '../common'; import * as _changelogHelper from './changelog'; import { getChangeLogJSON } from './changelog'; import * as prWorker from '.'; @@ -53,18 +53,15 @@ function setupChangelogMock() { describe('workers/pr', () => { describe('checkAutoMerge(pr, config)', () => { - let config; - let pr; + let config: BranchConfig; + let pr: Pr; beforeEach(() => { - config = { + config = partial<BranchConfig>({ ...defaultConfig, - }; - pr = { - head: { - ref: 'somebranch', - }, + }); + pr = partial<Pr>({ canMerge: true, - }; + }); }); afterEach(() => { jest.clearAllMocks(); @@ -117,7 +114,7 @@ describe('workers/pr', () => { }); }); describe('ensurePr', () => { - let config; + let config: BranchConfig; // TODO fix type const existingPr: Pr = { displayNumber: 'Existing PR', @@ -128,9 +125,9 @@ describe('workers/pr', () => { } as never; beforeEach(() => { setupChangelogMock(); - config = { + config = partial<BranchConfig>({ ...defaultConfig, - }; + }); config.branchName = 'renovate/dummy-1.x'; config.prTitle = 'Update dependency dummy to v1.1.0'; config.depType = 'devDependencies'; @@ -184,7 +181,7 @@ describe('workers/pr', () => { config.logJSON = await getChangeLogJSON(config); config.prCreation = 'status-success'; config.automerge = true; - config.schedule = 'before 5am'; + config.schedule = ['before 5am']; const { prResult, pr } = await prWorker.ensurePr(config); expect(prResult).toEqual(PrResult.Created); expect(pr).toMatchObject({ displayNumber: 'New Pull Request' }); @@ -215,7 +212,7 @@ describe('workers/pr', () => { updateType: 'lockFileMaintenance', prBodyNotes: ['{{#if foo}}'], }, - ]); + ] as never); config.updateType = 'lockFileMaintenance'; config.recreateClosed = true; config.rebaseWhen = 'never'; @@ -232,7 +229,7 @@ describe('workers/pr', () => { config.prCreation = 'status-success'; config.isPin = true; config.updateType = 'pin'; - config.schedule = 'before 5am'; + config.schedule = ['before 5am']; config.timezone = 'some timezone'; config.rebaseWhen = 'behind-base-branch'; config.logJSON = await getChangeLogJSON(config); @@ -374,7 +371,7 @@ describe('workers/pr', () => { platform.getBranchPr.mockResolvedValueOnce(existingPr); config.semanticCommitScope = null; config.automerge = true; - config.schedule = 'before 5am'; + config.schedule = ['before 5am']; config.logJSON = await getChangeLogJSON(config); const { prResult, pr } = await prWorker.ensurePr(config); expect(prResult).toEqual(PrResult.NotUpdated); @@ -389,7 +386,7 @@ describe('workers/pr', () => { platform.getBranchPr.mockResolvedValueOnce(modifiedPr); config.semanticCommitScope = null; config.automerge = true; - config.schedule = 'before 5am'; + config.schedule = ['before 5am']; config.logJSON = await getChangeLogJSON(config); const { prResult, pr } = await prWorker.ensurePr(config); expect(prResult).toEqual(PrResult.NotUpdated); @@ -399,7 +396,7 @@ describe('workers/pr', () => { it('should return modified existing PR', async () => { config.newValue = '1.2.0'; config.automerge = true; - config.schedule = 'before 5am'; + config.schedule = ['before 5am']; config.logJSON = await getChangeLogJSON(config); platform.getBranchPr.mockResolvedValueOnce(existingPr); const { prResult, pr } = await prWorker.ensurePr(config); diff --git a/lib/workers/pr/index.ts b/lib/workers/pr/index.ts index c3259564ec5ed4da84a50639cc4774c7c130e99f..495eb7b0a6c2f3fc903cf781d0132f3002e637a1 100644 --- a/lib/workers/pr/index.ts +++ b/lib/workers/pr/index.ts @@ -21,7 +21,11 @@ function noLeadingAtSymbol(input: string): string { return input.length && input.startsWith('@') ? input.slice(1) : input; } -export async function addAssigneesReviewers(config, pr: Pr): Promise<void> { +// TODO: fix types +export async function addAssigneesReviewers( + config: any, + pr: Pr +): Promise<void> { if (config.assignees.length > 0) { try { let assignees = config.assignees.map(noLeadingAtSymbol); @@ -180,8 +184,8 @@ export async function ensurePr( logger.debug('Branch status success'); } - const processedUpgrades = []; - const commitRepos = []; + const processedUpgrades: string[] = []; + const commitRepos: string[] = []; // Get changelog and then generate template strings for (const upgrade of upgrades) { @@ -234,7 +238,7 @@ export async function ensurePr( Object.assign(config, upgrades[0]); config.hasReleaseNotes = config.upgrades.some((upg) => upg.hasReleaseNotes); - const releaseNoteRepos = []; + const releaseNoteRepos: string[] = []; for (const upgrade of config.upgrades) { if (upgrade.hasReleaseNotes) { if (releaseNoteRepos.includes(upgrade.sourceUrl)) { @@ -347,7 +351,7 @@ export async function ensurePr( if (err.body.errors && err.body.errors.length) { if ( err.body.errors.some( - (error) => + (error: { message?: string }) => error.message && error.message.startsWith('A pull request already exists') ) @@ -422,7 +426,10 @@ export async function ensurePr( return { prResult: PrResult.Error }; } -export async function checkAutoMerge(pr: Pr, config): Promise<boolean> { +export async function checkAutoMerge( + pr: Pr, + config: BranchConfig +): Promise<boolean> { logger.trace({ config }, 'checkAutoMerge'); const { branchName, diff --git a/lib/workers/repository/extract/file-match.ts b/lib/workers/repository/extract/file-match.ts index 04e6ee64f0726a54d0f396e80b5732caf51dd095..921e3f8f539856a2fee1d9d8d7ccd11b94b4272f 100644 --- a/lib/workers/repository/extract/file-match.ts +++ b/lib/workers/repository/extract/file-match.ts @@ -55,7 +55,7 @@ export async function getMatchingFiles( const allFiles = await getFileList(); const fileList = getFilteredFileList(config, allFiles); const { fileMatch, manager } = config; - let matchedFiles = []; + let matchedFiles: string[] = []; for (const match of fileMatch) { logger.debug(`Using file match: ${match} for manager ${manager}`); const re = new RegExp(match); diff --git a/lib/workers/repository/extract/manager-files.ts b/lib/workers/repository/extract/manager-files.ts index c8a37e9b383b4a69ebcd9955e7de1b32bd968696..c3e8880ffccc0c8ca74f20bdb13482d5493d8b53 100644 --- a/lib/workers/repository/extract/manager-files.ts +++ b/lib/workers/repository/extract/manager-files.ts @@ -44,7 +44,7 @@ export async function getManagerPackageFiles( } return allPackageFiles; } - const packageFiles = []; + const packageFiles: PackageFile[] = []; for (const packageFile of fileList) { const content = await readLocalFile(packageFile, 'utf8'); if (content) { diff --git a/lib/workers/repository/finalise/validate.ts b/lib/workers/repository/finalise/validate.ts index 1a0a245824baa378c3c58a760e7c5cfb532d5e8a..3d42669b9ccd1babd0c0594990e203dcc36eca23 100644 --- a/lib/workers/repository/finalise/validate.ts +++ b/lib/workers/repository/finalise/validate.ts @@ -31,7 +31,7 @@ export async function validatePrs(config: RenovateConfig): Promise<void> { logger.debug('branchPrefix: ' + config.branchPrefix); const renovatePrs = await getRenovatePrs(config.branchPrefix); logger.debug({ renovatePrs }, `Found ${renovatePrs.length} Renovate PRs`); - let validations = []; + let validations: { file: string; message: string }[] = []; for (const pr of renovatePrs) { try { const renovateFiles = await getRenovateFiles(pr.number); diff --git a/lib/workers/repository/init/apis.ts b/lib/workers/repository/init/apis.ts index 0e84164b8d1f893463f20dc920a8993126402602..526825540084a7317b864d8b55e79244c31f1df4 100644 --- a/lib/workers/repository/init/apis.ts +++ b/lib/workers/repository/init/apis.ts @@ -1,6 +1,6 @@ import { RenovateConfig } from '../../../config'; import * as npmApi from '../../../datasource/npm'; -import { RepoConfig, platform } from '../../../platform'; +import { RepoConfig, RepoParams, platform } from '../../../platform'; // TODO: fix types export type WorkerPlatformConfig = RepoConfig & @@ -8,7 +8,9 @@ export type WorkerPlatformConfig = RepoConfig & Record<string, any>; // TODO: fix types -async function getPlatformConfig(config): Promise<WorkerPlatformConfig> { +async function getPlatformConfig( + config: RepoParams +): Promise<WorkerPlatformConfig> { const platformConfig = await platform.initRepo(config); return { ...config, @@ -21,7 +23,7 @@ export async function initApis( input: RenovateConfig ): Promise<WorkerPlatformConfig> { let config: WorkerPlatformConfig = { ...input } as never; - config = await getPlatformConfig(config); + config = await getPlatformConfig(config as never); npmApi.resetMemCache(); npmApi.setNpmrc(config.npmrc); delete config.gitPrivateKey; diff --git a/lib/workers/repository/init/base.ts b/lib/workers/repository/init/base.ts index 79d41699cf53ad5be02a88628a22b4dbe85daf28..099efbe2ec8380fdce9e103be3489cf46ea61e8f 100644 --- a/lib/workers/repository/init/base.ts +++ b/lib/workers/repository/init/base.ts @@ -1,4 +1,4 @@ -import { RenovateConfig } from '../../../config'; +import { RenovateConfig, ValidationMessage } from '../../../config'; import { logger } from '../../../logger'; import { platform } from '../../../platform'; @@ -7,7 +7,7 @@ export async function checkBaseBranch( ): Promise<RenovateConfig> { logger.debug('checkBaseBranch()'); logger.debug(`config.repoIsOnboarded=${config.repoIsOnboarded}`); - let error = []; + let error: ValidationMessage[] = []; let baseBranchSha: string; // istanbul ignore else if (config.baseBranch) { diff --git a/lib/workers/repository/init/vulnerability.spec.ts b/lib/workers/repository/init/vulnerability.spec.ts index e7a4a39c30ebeb2f6c10f6fe2183f480da10680c..9388b81a6d877e5ccc2d1d565fce38cd9792167d 100644 --- a/lib/workers/repository/init/vulnerability.spec.ts +++ b/lib/workers/repository/init/vulnerability.spec.ts @@ -1,5 +1,11 @@ -import { RenovateConfig, defaultConfig, platform } from '../../../../test/util'; +import { + RenovateConfig, + defaultConfig, + partial, + platform, +} from '../../../../test/util'; import { REPOSITORY_NO_VULNERABILITY } from '../../../constants/error-messages'; +import { VulnerabilityAlert } from '../../../types'; import { detectVulnerabilityAlerts } from './vulnerability'; let config: RenovateConfig; @@ -33,7 +39,7 @@ describe('workers/repository/init/vulnerability', () => { it('returns alerts', async () => { delete config.vulnerabilityAlerts.enabled; platform.getVulnerabilityAlerts.mockResolvedValue([ - {}, + partial<VulnerabilityAlert>({}), { dismissReason: null, vulnerableManifestFilename: 'package-lock.json', diff --git a/lib/workers/repository/init/vulnerability.ts b/lib/workers/repository/init/vulnerability.ts index 07856b97c798f2692eb4ef5a3745ab7cac62a7bd..8a9c4a7481c6061d05108f0de7db159d4f4e24e6 100644 --- a/lib/workers/repository/init/vulnerability.ts +++ b/lib/workers/repository/init/vulnerability.ts @@ -7,6 +7,7 @@ import * as datasourcePypi from '../../../datasource/pypi'; import * as datasourceRubygems from '../../../datasource/rubygems'; import { logger } from '../../../logger'; import { platform } from '../../../platform'; +import { SecurityAdvisory } from '../../../types'; import * as allVersioning from '../../../versioning'; import * as mavenVersioning from '../../../versioning/maven'; import * as npmVersioning from '../../../versioning/npm'; @@ -14,6 +15,19 @@ import * as pep440Versioning from '../../../versioning/pep440'; import * as rubyVersioning from '../../../versioning/ruby'; import * as semverVersioning from '../../../versioning/semver'; +type CombinedAlert = Record< + string, + Record< + string, + { + advisories: SecurityAdvisory[]; + fileNames: string[]; + firstPatchedVersion?: string; + vulnerableRequirements?: string; + } + > +>; + export async function detectVulnerabilityAlerts( input: RenovateConfig ): Promise<RenovateConfig> { @@ -33,7 +47,7 @@ export async function detectVulnerabilityAlerts( return input; } const config = { ...input }; - const combinedAlerts = {}; + const combinedAlerts: CombinedAlert = {}; for (const alert of alerts) { try { if (alert.dismissReason) { @@ -46,7 +60,7 @@ export async function detectVulnerabilityAlerts( ); continue; // eslint-disable-line no-continue } - const datasourceMapping = { + const datasourceMapping: Record<string, string> = { MAVEN: datasourceMaven.id, NPM: datasourceNpm.id, NUGET: datasourceNuget.id, @@ -74,7 +88,7 @@ export async function detectVulnerabilityAlerts( } const firstPatchedVersion = alert.securityVulnerability.firstPatchedVersion.identifier; - const versionings = { + const versionings: Record<string, string> = { maven: mavenVersioning.id, npm: npmVersioning.id, nuget: semverVersioning.id, @@ -113,7 +127,7 @@ export async function detectVulnerabilityAlerts( const alertPackageRules = []; for (const [datasource, dependencies] of Object.entries(combinedAlerts)) { for (const [depName, val] of Object.entries(dependencies)) { - let prBodyNotes = []; + let prBodyNotes: string[] = []; try { prBodyNotes = ['### GitHub Vulnerability Alerts'].concat( val.advisories.map((advisory) => { diff --git a/lib/workers/repository/master-issue.spec.ts b/lib/workers/repository/master-issue.spec.ts index 423774928780c0d545b8c6fddee522a0cfd4516b..00c39bbcfdd1cd3f27edc5a5af394db5996b1696 100644 --- a/lib/workers/repository/master-issue.spec.ts +++ b/lib/workers/repository/master-issue.spec.ts @@ -3,7 +3,7 @@ import { mock } from 'jest-mock-extended'; import { RenovateConfig, getConfig, platform } from '../../../test/util'; import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms'; import { PR_STATE_NOT_OPEN } from '../../constants/pull-requests'; -import { Pr } from '../../platform'; +import { Platform, Pr } from '../../platform'; import { BranchConfig, BranchUpgradeConfig } from '../common'; import * as masterIssue from './master-issue'; @@ -21,7 +21,7 @@ beforeEach(() => { async function dryRun( branches: BranchConfig[], // eslint-disable-next-line no-shadow - platform, + platform: jest.Mocked<Platform>, ensureIssueClosingCalls = 0, ensureIssueCalls = 0, getBranchPrCalls = 0, diff --git a/lib/workers/repository/onboarding/pr/config-description.spec.ts b/lib/workers/repository/onboarding/pr/config-description.spec.ts index 2a18b25611be58f62104cfa19a828719a148e1a8..fc5dd3f78a24509fa00bcb4d0907a0572b654093 100644 --- a/lib/workers/repository/onboarding/pr/config-description.spec.ts +++ b/lib/workers/repository/onboarding/pr/config-description.spec.ts @@ -1,5 +1,5 @@ import { RenovateConfig, getConfig } from '../../../../../test/util'; - +import { PackageFile } from '../../../../manager/common'; import { getConfigDesc } from './config-description'; describe('workers/repository/onboarding/pr/config-description', () => { @@ -15,7 +15,7 @@ describe('workers/repository/onboarding/pr/config-description', () => { expect(res).toMatchSnapshot(); }); it('returns a full list', () => { - const packageFiles = { + const packageFiles: Record<string, PackageFile[]> = { npm: [], dockerfile: [], }; diff --git a/lib/workers/repository/onboarding/pr/errors-warnings.spec.ts b/lib/workers/repository/onboarding/pr/errors-warnings.spec.ts index e517222f612f30c0508ada4b9a17d02859c37e9f..85c0b439b35c631e44d1c0b5b93b9437c9ee0bb6 100644 --- a/lib/workers/repository/onboarding/pr/errors-warnings.spec.ts +++ b/lib/workers/repository/onboarding/pr/errors-warnings.spec.ts @@ -1,5 +1,5 @@ import { RenovateConfig, getConfig } from '../../../../../test/util'; - +import { PackageFile } from '../../../../manager/common'; import { getDepWarnings, getErrors, getWarnings } from './errors-warnings'; describe('workers/repository/onboarding/pr/errors-warnings', () => { @@ -25,7 +25,7 @@ describe('workers/repository/onboarding/pr/errors-warnings', () => { jest.resetAllMocks(); }); it('returns warning text', () => { - const packageFiles = { + const packageFiles: Record<string, PackageFile[]> = { npm: [ { packageFile: 'package.json', diff --git a/lib/workers/repository/onboarding/pr/errors-warnings.ts b/lib/workers/repository/onboarding/pr/errors-warnings.ts index a53eee19cb193704fe3de6dd1b866d93e7fc32c6..ce84a8d5fcf4d353a3f08f2ec96ce1864ffe6f2f 100644 --- a/lib/workers/repository/onboarding/pr/errors-warnings.ts +++ b/lib/workers/repository/onboarding/pr/errors-warnings.ts @@ -35,8 +35,8 @@ export function getDepWarnings( ): string { let warningText = ''; try { - const warnings = []; - const warningFiles = []; + const warnings: string[] = []; + const warningFiles: string[] = []; for (const files of Object.values(packageFiles || {})) { for (const file of files || []) { if (file.deps) { diff --git a/lib/workers/repository/onboarding/pr/index.spec.ts b/lib/workers/repository/onboarding/pr/index.spec.ts index 17b1a40cb982c7b9a37cc53a2c9f05e86550acf5..d0e87c264cc875a914c8cc37306dd4b795283e56 100644 --- a/lib/workers/repository/onboarding/pr/index.spec.ts +++ b/lib/workers/repository/onboarding/pr/index.spec.ts @@ -1,15 +1,18 @@ -import { RenovateConfig, defaultConfig } from '../../../../../test/util'; +import { + RenovateConfig, + defaultConfig, + partial, + platform, +} from '../../../../../test/util'; +import { PackageFile } from '../../../../manager/common'; +import { Pr } from '../../../../platform'; import { BranchConfig } from '../../../common'; - -const { platform } = require('../../../../platform'); -const { ensureOnboardingPr } = require('.'); - -/** @type any */ +import { ensureOnboardingPr } from '.'; describe('workers/repository/onboarding/pr', () => { describe('ensureOnboardingPr()', () => { let config: RenovateConfig; - let packageFiles; + let packageFiles: Record<string, PackageFile[]>; let branches: BranchConfig[]; beforeEach(() => { jest.resetAllMocks(); @@ -19,10 +22,10 @@ describe('workers/repository/onboarding/pr', () => { warnings: [], description: [], }; - packageFiles = { npm: [{ packageFile: 'package.json' }] }; + packageFiles = { npm: [{ packageFile: 'package.json', deps: [] }] }; branches = []; platform.getPrBody = jest.fn((input) => input); - platform.createPr.mockReturnValue({}); + platform.createPr.mockResolvedValueOnce(partial<Pr>({})); }); let createPrBody: string; it('returns if onboarded', async () => { @@ -35,34 +38,40 @@ describe('workers/repository/onboarding/pr', () => { createPrBody = platform.createPr.mock.calls[0][0].prBody; }); it('returns if PR does not need updating', async () => { - platform.getBranchPr.mockReturnValue({ - title: 'Configure Renovate', - body: createPrBody, - isModified: false, - }); + platform.getBranchPr.mockResolvedValue( + partial<Pr>({ + title: 'Configure Renovate', + body: createPrBody, + isModified: false, + }) + ); await ensureOnboardingPr(config, packageFiles, branches); expect(platform.createPr).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(0); }); it('updates PR', async () => { config.baseBranch = 'some-branch'; - platform.getBranchPr.mockReturnValue({ - title: 'Configure Renovate', - body: createPrBody, - isConflicted: true, - isModified: true, - }); + platform.getBranchPr.mockResolvedValueOnce( + partial<Pr>({ + title: 'Configure Renovate', + body: createPrBody, + isConflicted: true, + isModified: true, + }) + ); await ensureOnboardingPr(config, {}, branches); expect(platform.createPr).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(1); }); it('updates PR', async () => { config.baseBranch = 'some-branch'; - platform.getBranchPr.mockReturnValue({ - title: 'Configure Renovate', - body: createPrBody, - isModified: true, - }); + platform.getBranchPr.mockResolvedValueOnce( + partial<Pr>({ + title: 'Configure Renovate', + body: createPrBody, + isModified: true, + }) + ); await ensureOnboardingPr(config, {}, branches); expect(platform.createPr).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(1); diff --git a/lib/workers/repository/onboarding/pr/index.ts b/lib/workers/repository/onboarding/pr/index.ts index 4501ce7532d565a0693ee8c841eea54e9c6d011c..15d59ce4b7f65944ccba753107f1aeee04fd64bc 100644 --- a/lib/workers/repository/onboarding/pr/index.ts +++ b/lib/workers/repository/onboarding/pr/index.ts @@ -50,7 +50,7 @@ If you need any further assistance then you can also [request help here](${confi ); let prBody = prTemplate; if (packageFiles && Object.entries(packageFiles).length) { - let files = []; + let files: string[] = []; for (const [manager, managerFiles] of Object.entries(packageFiles)) { files = files.concat( managerFiles.map((file) => ` * \`${file.packageFile}\` (${manager})`) @@ -115,7 +115,7 @@ If you need any further assistance then you can also [request help here](${confi return; } logger.debug('Creating onboarding PR'); - const labels = []; + const labels: string[] = []; const useDefaultBranch = true; try { // istanbul ignore if diff --git a/lib/workers/repository/onboarding/pr/pr-list.spec.ts b/lib/workers/repository/onboarding/pr/pr-list.spec.ts index c001bb6f504a0a272497931115bff2aa6ef84049..ceb33f0caf13197d3a9884d313ae67017c000b81 100644 --- a/lib/workers/repository/onboarding/pr/pr-list.spec.ts +++ b/lib/workers/repository/onboarding/pr/pr-list.spec.ts @@ -1,4 +1,5 @@ import { RenovateConfig, getConfig } from '../../../../../test/util'; +import { BranchConfig } from '../../../common'; import { getPrList } from './pr-list'; describe('workers/repository/onboarding/pr/pr-list', () => { @@ -9,7 +10,7 @@ describe('workers/repository/onboarding/pr/pr-list', () => { config = getConfig(); }); it('handles emptyu', () => { - const branches = []; + const branches: BranchConfig[] = []; const res = getPrList(config, branches); expect(res).toMatchSnapshot(); }); diff --git a/lib/workers/repository/onboarding/pr/pr-list.ts b/lib/workers/repository/onboarding/pr/pr-list.ts index 80960b4073bea123befbfeba3e7d57bd1c2b8c0d..0b9463fce5643c0c88f08a8096b9ccdce46deccf 100644 --- a/lib/workers/repository/onboarding/pr/pr-list.ts +++ b/lib/workers/repository/onboarding/pr/pr-list.ts @@ -29,7 +29,7 @@ export function getPrList( prDesc += branch.baseBranch ? ` - Merge into: \`${branch.baseBranch}\`\n` : ''; - const seen = []; + const seen: string[] = []; for (const upgrade of branch.upgrades) { let text = ''; if (upgrade.updateType === 'lockFileMaintenance') { diff --git a/lib/workers/repository/process/deprecated.spec.ts b/lib/workers/repository/process/deprecated.spec.ts index 5946616ae879bf5d10deb50fffc92fea9d90ba23..7d9c79a28f3e21284a065387cce9208c0f0425aa 100644 --- a/lib/workers/repository/process/deprecated.spec.ts +++ b/lib/workers/repository/process/deprecated.spec.ts @@ -1,4 +1,4 @@ -import { platform } from '../../../../test/util'; +import { RenovateConfig, platform } from '../../../../test/util'; import { raiseDeprecationWarnings } from './deprecated'; describe('workers/repository/process/deprecated', () => { @@ -8,14 +8,14 @@ describe('workers/repository/process/deprecated', () => { await raiseDeprecationWarnings(config, {}); }); it('returns if disabled', async () => { - const config = { + const config: RenovateConfig = { repoIsOnboarded: true, suppressNotifications: ['deprecationWarningIssues'], }; await raiseDeprecationWarnings(config, {}); }); it('raises deprecation warnings', async () => { - const config = { + const config: RenovateConfig = { repoIsOnboarded: true, suppressNotifications: [], }; diff --git a/lib/workers/repository/process/fetch.spec.ts b/lib/workers/repository/process/fetch.spec.ts index 2b5310430be7842366a589341e78561de0402d05..d71d727ca6d07d0821a9c6ab611b3642834269cb 100644 --- a/lib/workers/repository/process/fetch.spec.ts +++ b/lib/workers/repository/process/fetch.spec.ts @@ -1,7 +1,7 @@ import { RenovateConfig, getConfig, mocked } from '../../../../test/util'; import * as datasourceMaven from '../../../datasource/maven'; import * as datasourceNpm from '../../../datasource/npm'; -import { ManagerApi } from '../../../manager/common'; +import { ManagerApi, PackageFile } from '../../../manager/common'; import * as _npm from '../../../manager/npm'; import { fetchUpdates } from './fetch'; import * as lookup from './lookup'; @@ -19,7 +19,7 @@ describe('workers/repository/process/fetch', () => { config = getConfig(); }); it('handles empty deps', async () => { - const packageFiles = { + const packageFiles: Record<string, PackageFile[]> = { npm: [{ packageFile: 'package.json', deps: [] }], }; await fetchUpdates(config, packageFiles); @@ -33,7 +33,7 @@ describe('workers/repository/process/fetch', () => { enabled: false, }, ]; - const packageFiles: any = { + const packageFiles: Record<string, PackageFile[]> = { npm: [ { packageFile: 'package.json', @@ -41,7 +41,7 @@ describe('workers/repository/process/fetch', () => { { depName: 'abcd' }, { depName: 'zzzz' }, { depName: 'foo' }, - { depName: 'skipped', skipReason: 'some-reason' }, + { depName: 'skipped', skipReason: 'some-reason' as never }, ], internalPackages: ['zzzz'], }, diff --git a/lib/workers/repository/process/limits.spec.ts b/lib/workers/repository/process/limits.spec.ts index 2ba44289ec8f366e523d50e9bfd483d00558d2a3..f698036f60f4e3d007228c864bc688f92006f8e4 100644 --- a/lib/workers/repository/process/limits.spec.ts +++ b/lib/workers/repository/process/limits.spec.ts @@ -15,7 +15,7 @@ describe('workers/repository/process/limits', () => { config.prHourlyLimit = 2; platform.getPrList.mockResolvedValueOnce([ { - created_at: moment().format(), + createdAt: moment().toISOString(), branchName: null, title: null, state: null, diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts index cf17b9e7c0417a261cb044c3d8af4dcaadb54fda..ecaf7062ed24eb717c1da31ab3fb1d2ad9dd09ff 100644 --- a/lib/workers/repository/process/lookup/index.spec.ts +++ b/lib/workers/repository/process/lookup/index.spec.ts @@ -1,5 +1,5 @@ import nock from 'nock'; -import { getConfig, mocked } from '../../../../../test/util'; +import { getConfig, mocked, partial } from '../../../../../test/util'; import qJson from '../../../../config/npm/__fixtures__/01.json'; import helmetJson from '../../../../config/npm/__fixtures__/02.json'; import coffeelintJson from '../../../../config/npm/__fixtures__/coffeelint.json'; @@ -30,11 +30,12 @@ qJson.latestVersion = '1.4.1'; const docker = mocked(datasourceDocker); const gitSubmodules = mocked(datasourceGitSubmodules); -let config; +let config: lookup.LookupUpdateConfig; describe('workers/repository/process/lookup', () => { beforeEach(() => { - config = getConfig(); + // TODO: fix types + config = partial<lookup.LookupUpdateConfig>(getConfig()); config.manager = 'npm'; config.versioning = npmVersioning.id; config.rangeStrategy = 'replace'; diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts index 2086b5f368d054585f9b324d0882028a264465b9..4a97ca511cded8c426fd6c4859b621c4aa3d3d9c 100644 --- a/lib/workers/repository/process/lookup/index.ts +++ b/lib/workers/repository/process/lookup/index.ts @@ -279,7 +279,7 @@ export async function lookupUpdates( if (vulnerabilityAlert) { filteredVersions = filteredVersions.slice(0, 1); } - const buckets = {}; + const buckets: Record<string, LookupUpdate> = {}; for (const toVersion of filteredVersions) { const update: LookupUpdate = { fromVersion, toVersion } as any; try { @@ -327,14 +327,17 @@ export async function lookupUpdates( version.equals(release.version, toVersion) ); // TODO: think more about whether to just Object.assign this - const releaseFields = [ - 'releaseTimestamp', - 'canBeUnpublished', - 'newDigest', - ]; + const releaseFields: (keyof Pick< + Release, + | 'releaseTimestamp' + | 'canBeUnpublished' + | 'downloadUrl' + | 'checksumUrl' + | 'newDigest' + >)[] = ['releaseTimestamp', 'canBeUnpublished', 'newDigest']; releaseFields.forEach((field) => { if (updateRelease[field] !== undefined) { - update[field] = updateRelease[field]; + update[field] = updateRelease[field] as never; } }); diff --git a/lib/workers/repository/updates/branchify.ts b/lib/workers/repository/updates/branchify.ts index 102333c64be3108fb7cb13b6db90d9f6279d8252..6113b1b0a6af8373327d21188f79a0daa2e8fe1a 100644 --- a/lib/workers/repository/updates/branchify.ts +++ b/lib/workers/repository/updates/branchify.ts @@ -163,7 +163,7 @@ export async function branchifyUpgrades( try { // Here we check if there are updates from the same source repo // that are not grouped into the same branch - const branchUpdates = {}; + const branchUpdates: Record<string, Record<string, string>> = {}; for (const branch of branches) { const { sourceUrl, branchName, depName, toVersion } = branch; if (sourceUrl && toVersion) { diff --git a/lib/workers/repository/updates/generate.spec.ts b/lib/workers/repository/updates/generate.spec.ts index f1c20c273edd9bc628703a34d51c0ccffa200681..fad0842c56f41cc29b522632f11654db7ddb19be 100644 --- a/lib/workers/repository/updates/generate.spec.ts +++ b/lib/workers/repository/updates/generate.spec.ts @@ -370,7 +370,7 @@ describe('workers/repository/updates/generate', () => { expect(res.prTitle).toMatchSnapshot(); }); it('handles @types specially', () => { - const branch = [ + const branch: BranchUpgradeConfig[] = [ { commitBodyTable: true, datasource: datasourceNpm.id, @@ -401,7 +401,7 @@ describe('workers/repository/updates/generate', () => { expect(res.groupName).toBeUndefined(); }); it('handles @types specially (reversed)', () => { - const branch = [ + const branch: BranchUpgradeConfig[] = [ { depName: 'some-dep', groupName: null, @@ -424,7 +424,7 @@ describe('workers/repository/updates/generate', () => { expect(generateBranchConfig(branch)).toMatchSnapshot(); }); it('handles upgrades', () => { - const branch = [ + const branch: BranchUpgradeConfig[] = [ { depName: 'some-dep', branchName: 'some-branch', diff --git a/lib/workers/repository/updates/generate.ts b/lib/workers/repository/updates/generate.ts index 69d323122a01e1a75efbe4dac96c3590068cc7ad..c37f56c146b69f9b1ca78bf8c797c50aca54d994 100644 --- a/lib/workers/repository/updates/generate.ts +++ b/lib/workers/repository/updates/generate.ts @@ -69,9 +69,9 @@ export function generateBranchConfig( const hasGroupName = branchUpgrades[0].groupName !== null; logger.trace(`hasGroupName: ${hasGroupName}`); // Use group settings only if multiple upgrades or lazy grouping is disabled - const depNames = []; - const newValue = []; - const toVersions = []; + const depNames: string[] = []; + const newValue: string[] = []; + const toVersions: string[] = []; branchUpgrades.forEach((upg) => { if (!depNames.includes(upg.depName)) { depNames.push(upg.depName); diff --git a/package.json b/package.json index e60be20aeb0efcd78c5ef9f1006b62f076f3f335..5aab8921fa6d1c38aefa1cb5ce1533af571fd27e 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "test-schema": "babel-node --extensions \".ts,.js\" -- test/json-schema.ts", "test": "run-s lint test-schema type-check jest", "tsc": "tsc", - "type-check": "run-s generate:* \"tsc --noEmit\"", + "type-check": "run-s generate:* \"tsc --noEmit {@}\"", "verify": "node --experimental-modules tools/verify.mjs" }, "repository": { @@ -205,6 +205,7 @@ "@types/lodash": "4.14.150", "@types/luxon": "1.22.0", "@types/markdown-it": "10.0.1", + "@types/markdown-table": "2.0.0", "@types/moment-timezone": "0.5.13", "@types/nock": "10.0.3", "@types/node": "11.15.12", diff --git a/test/execUtil.ts b/test/execUtil.ts index d1ea80aac1cdea5d3745264f0f4a02fc5c015d99..babd4063a1f7c9462a4875a5a3cc3fb4fe523010 100644 --- a/test/execUtil.ts +++ b/test/execUtil.ts @@ -35,7 +35,7 @@ export function mockExecAll( execFn: jest.Mock<typeof _exec>, execResult: ExecResult = defaultExecResult ): ExecSnapshots { - const snapshots = []; + const snapshots: ExecSnapshots = []; execFn.mockImplementation((cmd, options, callback) => { snapshots.push(execSnapshot(cmd, options)); if (execResult instanceof Error) { @@ -51,7 +51,7 @@ export function mockExecSequence( execFn: jest.Mock<typeof _exec>, execResults: ExecResult[] ): ExecSnapshots { - const snapshots = []; + const snapshots: ExecSnapshots = []; execResults.forEach((execResult) => { execFn.mockImplementationOnce((cmd, options, callback) => { snapshots.push(execSnapshot(cmd, options)); diff --git a/tsconfig.app.json b/tsconfig.app.json index 07124cae000fe0a264c63f492b538f073aef9626..4377e2261e05f5214022a2dbdb23283ca75af14a 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -2,6 +2,7 @@ "extends": "./tsconfig", "compilerOptions": { "resolveJsonModule": false, + "noImplicitAny": false, "isolatedModules": true, "sourceMap": true, "inlineSources": true, diff --git a/yarn.lock b/yarn.lock index a2ee17007a178f274055cf8a18b39fbf5d11b4ea..67ffb9f32b3f96f9a2d3233977d604aa25891c31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1545,6 +1545,11 @@ resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== +"@types/markdown-table@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/markdown-table/-/markdown-table-2.0.0.tgz#d2a3458c61ee71c8ee2b40b76c199b85b8dbd70c" + integrity sha512-fVZN/DRjZvjuk+lo7ovlI/ZycS51gpYU5vw5EcFeqkcX6lucQ+UWgEOH2O4KJHkSck4DHAY7D7CkVLD0wzc5qw== + "@types/minimatch@*", "@types/minimatch@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"