diff --git a/.eslintrc.js b/.eslintrc.js index 3c1c75d30fbc93b8cbb397478c3b40ab61a0f37b..8fb34b3e6e17e2087f2f63fc25f406b7d86863a3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -42,6 +42,7 @@ module.exports = { 'prefer-destructuring': 0, 'prefer-template': 0, 'no-underscore-dangle': 0, + // 'no-unused-vars': 2, 'sort-imports': [ 'error', @@ -104,8 +105,9 @@ module.exports = { '@typescript-eslint/ban-types': 1, }, settings: { - // https://github.com/benmosher/eslint-plugin-import/issues/1618 - 'import/internal-regex': '^type\\-fest$', + 'import/parsers': { + '@typescript-eslint/parser': ['.ts'], + }, }, overrides: [ { @@ -130,6 +132,8 @@ module.exports = { rules: { '@typescript-eslint/explicit-function-return-type': 0, + '@typescript-eslint/explicit-module-boundary-types': 0, + '@typescript-eslint/restrict-template-expressions': 0, }, }, ], diff --git a/lib/manager/gradle/__testutil__/gradle.ts b/lib/manager/gradle/__testutil__/gradle.ts index 63e603c27fc2209616c343e4a1a481b81580900f..444accb9a872d1466f6e4b3644d10e7aee56698b 100644 --- a/lib/manager/gradle/__testutil__/gradle.ts +++ b/lib/manager/gradle/__testutil__/gradle.ts @@ -49,7 +49,7 @@ function determineJavaVersion(): number { throw Error( `This test suite needs Java and ${failIfNoJavaEnv} is set. Result of java -version: -${error}` +${error.toString()}` ); } cachedJavaVersion = parseJavaVersion(javaVersionCommand.stderr); @@ -60,13 +60,16 @@ ${error}` class WithGradle { private gradleSupportsThisJavaVersion: boolean; - constructor(private gradleVersion: number) { + constructor(gradleVersion: number) { const javaVersion = determineJavaVersion(); if (gradleJavaVersionSupport[gradleVersion] === undefined) { throw Error(`Unknown gradle version '${gradleVersion}'!`); } - const supportedJavaVersions = gradleJavaVersionSupport[gradleVersion]; + const supportedJavaVersions = gradleJavaVersionSupport[gradleVersion] as { + min: number; + max: number; + }; this.gradleSupportsThisJavaVersion = javaVersion >= supportedJavaVersions.min && javaVersion <= supportedJavaVersions.max; diff --git a/lib/manager/npm/extract/common.ts b/lib/manager/npm/extract/common.ts index b271b010a7695688884f5b278220c13a19805e83..da1f53429549cb72d95ececfdf7ef45962bf42c9 100644 --- a/lib/manager/npm/extract/common.ts +++ b/lib/manager/npm/extract/common.ts @@ -1,5 +1,4 @@ -// eslint-disable-next-line import/no-unresolved -import { PackageJson } from 'type-fest'; +import type { PackageJson } from 'type-fest'; export type NpmPackageDependeny = PackageJson.Dependency; diff --git a/lib/platform/azure/azure-helper.ts b/lib/platform/azure/azure-helper.ts index 7f9f7dea8efcb469d0ecaf2e7d577e51f76a3429..44b11e3e0c3307ffa776b8691cc1d72560bcdd7e 100644 --- a/lib/platform/azure/azure-helper.ts +++ b/lib/platform/azure/azure-helper.ts @@ -4,10 +4,10 @@ import { GitPullRequestMergeStrategy, GitRef, } from 'azure-devops-node-api/interfaces/GitInterfaces'; -import { Options } from 'simple-git'; import { logger } from '../../logger'; import { HostRule, PrState } from '../../types'; +import { GitOptions } from '../../types/git'; import * as azureApi from './azure-got-wrapper'; import { AzurePr } from './types'; @@ -17,7 +17,7 @@ function toBase64(from: string): string { return Buffer.from(from).toString('base64'); } -export function getStorageExtraCloneOpts(config: HostRule): Options { +export function getStorageExtraCloneOpts(config: HostRule): GitOptions { let header: string; const headerName = 'AUTHORIZATION'; if (!config.token && config.username && config.password) { diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts index db369c992b4b5b3100dec6165fee813b77ec25d7..48c7312bdf1c614d85bb00863bf64ca9fbfed112 100644 --- a/lib/platform/azure/index.ts +++ b/lib/platform/azure/index.ts @@ -53,7 +53,10 @@ interface User { let config: Config = {} as any; -const defaults: any = { +const defaults: { + endpoint?: string; + hostType: string; +} = { hostType: PLATFORM_TYPE_AZURE, }; @@ -252,8 +255,8 @@ export async function findPr({ prsFiltered = prsFiltered.filter((item) => item.state === state); break; } - } catch (error) { - logger.error('findPr ' + error); + } catch (err) { + logger.error({ err }, 'findPr error'); } if (prsFiltered.length === 0) { return null; @@ -595,7 +598,7 @@ export async function addAssignees( issueNo: number, assignees: string[] ): Promise<void> { - logger.trace(`addAssignees(${issueNo}, ${assignees})`); + logger.trace(`addAssignees(${issueNo}, [${assignees.join(', ')}])`); const ids = await getUserIds(assignees); await ensureComment({ number: issueNo, @@ -613,7 +616,7 @@ export async function addReviewers( prNo: number, reviewers: string[] ): Promise<void> { - logger.trace(`addReviewers(${prNo}, ${reviewers})`); + logger.trace(`addReviewers(${prNo}, [${reviewers.join(', ')}])`); const azureApiGit = await azureApi.gitApi(); const ids = await getUserIds(reviewers); diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts index a4336e79cb3051f48b8c98a44f1fe6a11b22d1af..12b8b999c3e85d362774e1f8a254fdb6dc7ac898 100644 --- a/lib/platform/bitbucket-server/index.ts +++ b/lib/platform/bitbucket-server/index.ts @@ -1,6 +1,7 @@ import url, { URLSearchParams } from 'url'; import is from '@sindresorhus/is'; import delay from 'delay'; +import type { PartialDeep } from 'type-fest'; import { REPOSITORY_CHANGED, REPOSITORY_DISABLED, @@ -10,6 +11,7 @@ import { import { PLATFORM_TYPE_BITBUCKET_SERVER } from '../../constants/platforms'; import { logger } from '../../logger'; import { BranchStatus, PrState } from '../../types'; +import { GitProtocol } from '../../types/git'; import * as git from '../../util/git'; import { deleteBranch } from '../../util/git'; import * as hostRules from '../../util/host-rules'; @@ -40,7 +42,7 @@ import { import { smartTruncate } from '../utils/pr-body'; 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: @@ -55,7 +57,10 @@ let config: BbsConfig = {} as any; const bitbucketServerHttp = new BitbucketServerHttp(); -const defaults: any = { +const defaults: { + endpoint?: string; + hostType: string; +} = { hostType: PLATFORM_TYPE_BITBUCKET_SERVER, }; @@ -143,7 +148,7 @@ export async function initRepo({ `./rest/api/1.0/projects/${projectKey}/repos/${repositorySlug}/browse/renovate.json?limit=20000` ); if (!body.isLastPage) { - logger.warn('Renovate config to big: ' + body.size); + logger.warn({ size: body.size }, `Renovate config to big`); } else { renovateConfig = JSON.parse(body.lines.join()); } @@ -169,9 +174,9 @@ export async function initRepo({ config.bbUseDefaultReviewers = true; } - const { host, pathname } = url.parse(defaults.endpoint!); + const { host, pathname } = url.parse(defaults.endpoint); const gitUrl = git.getUrl({ - protocol: defaults.endpoint!.split(':')[0], + protocol: defaults.endpoint.split(':')[0] as GitProtocol, auth: `${opts.username}:${opts.password}`, host: `${host}${pathname}${ pathname.endsWith('/') ? '' : /* istanbul ignore next */ '/' @@ -562,7 +567,7 @@ export /* istanbul ignore next */ function ensureIssueClosing( } export function addAssignees(iid: number, assignees: string[]): Promise<void> { - logger.debug(`addAssignees(${iid}, ${assignees})`); + logger.debug(`addAssignees(${iid}, [${assignees.join(', ')}])`); // 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 @@ -573,7 +578,7 @@ export async function addReviewers( prNo: number, reviewers: string[] ): Promise<void> { - logger.debug(`Adding reviewers ${reviewers} to #${prNo}`); + logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${prNo}`); try { const pr = await getPr(prNo); @@ -602,7 +607,10 @@ export async function addReviewers( } else if (err.statusCode === 409) { throw new Error(REPOSITORY_CHANGED); } else { - logger.fatal({ err }, `Failed to add reviewers ${reviewers} to #${prNo}`); + logger.fatal( + { err }, + `Failed to add reviewers '${reviewers.join(', ')}' to #${prNo}` + ); throw err; } } diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts index 57c02fe2c0c2a813657cb52c6df46bff712d9680..0dcd312d5c022bb91822fbe1bfaee81c7338c5b0 100644 --- a/lib/platform/bitbucket/index.ts +++ b/lib/platform/bitbucket/index.ts @@ -40,7 +40,7 @@ const BITBUCKET_PROD_ENDPOINT = 'https://api.bitbucket.org/'; let config: utils.Config = {} as any; -let endpoint_ = BITBUCKET_PROD_ENDPOINT; +const defaults = { endpoint: BITBUCKET_PROD_ENDPOINT }; export function initPlatform({ endpoint, @@ -56,9 +56,9 @@ export function initPlatform({ logger.warn( `Init: Bitbucket Cloud endpoint should generally be ${BITBUCKET_PROD_ENDPOINT} but is being configured to a different value. Did you mean to use Bitbucket Server?` ); - endpoint_ = endpoint; + defaults.endpoint = endpoint; } - setBaseUrl(endpoint_); + setBaseUrl(defaults.endpoint); // TODO: Add a connection check that endpoint/username/password combination are valid const platformConfig: PlatformResult = { endpoint: endpoint || BITBUCKET_PROD_ENDPOINT, @@ -90,7 +90,7 @@ export async function initRepo({ logger.debug(`initRepo("${repository}")`); const opts = hostRules.find({ hostType: PLATFORM_TYPE_BITBUCKET, - url: endpoint_, + url: defaults.endpoint, }); config = { repository, @@ -138,7 +138,7 @@ export async function initRepo({ throw err; } - const { hostname } = URL.parse(endpoint_); + const { hostname } = URL.parse(defaults.endpoint); // Converts API hostnames to their respective HTTP git hosts: // `api.bitbucket.org` to `bitbucket.org` @@ -531,7 +531,9 @@ export async function ensureIssue({ } catch (err) /* istanbul ignore next */ { if (err.message.startsWith('Repository has no issue tracker.')) { logger.debug( - `Issues are disabled, so could not create issue: ${err.message}` + `Issues are disabled, so could not create issue: ${ + err.message as string + }` ); } else { logger.warn({ err }, 'Could not ensure issue'); @@ -596,7 +598,7 @@ export async function addReviewers( prId: number, reviewers: string[] ): Promise<void> { - logger.debug(`Adding reviewers ${reviewers} to #${prId}`); + logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${prId}`); const { title } = await getPr(prId); diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts index 574c7423a57c6d88d8d61f4bd1d48d53dbc3a35b..8ee46283700f148fc162b276d6f95290a4707c5f 100644 --- a/lib/platform/gitea/index.ts +++ b/lib/platform/gitea/index.ts @@ -49,7 +49,7 @@ interface GiteaRepoConfig { labelList: Promise<helper.Label[]> | null; } -const defaults: any = { +const defaults = { hostType: PLATFORM_TYPE_GITEA, endpoint: 'https://gitea.com/api/v1/', }; @@ -796,7 +796,9 @@ const platform: Platform = { }, async addAssignees(number: number, assignees: string[]): Promise<void> { - logger.debug(`Updating assignees ${assignees} on Issue #${number}`); + logger.debug( + `Updating assignees '${assignees?.join(', ')}' on Issue #${number}` + ); await helper.updateIssue(config.repository, number, { assignees, }); @@ -805,7 +807,9 @@ const platform: Platform = { addReviewers(number: number, reviewers: string[]): Promise<void> { // Adding reviewers to a PR through API is not supported by Gitea as of today // See tracking issue: https://github.com/go-gitea/gitea/issues/5733 - logger.debug(`Updating reviewers ${reviewers} on Pull Request #${number}`); + logger.debug( + `Updating reviewers '${reviewers?.join(', ')}' on Pull Request #${number}` + ); logger.warn('Unimplemented in Gitea: Reviewers'); return Promise.resolve(); }, diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index 8138ac1cc541842f59b556441f2b79aeacab2f29..cc110fa87e0b26eca87aff204258c1e1a37cab65 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -47,8 +47,10 @@ import { CombinedBranchStatus, Comment, GhBranchStatus, + GhGraphQlPr, GhPr, GhRepo, + GhRestPr, LocalRepoConfig, PrList, } from './types'; @@ -498,9 +500,13 @@ async function getClosedPrs(): Promise<PrList> { } } `; - const nodes = await githubApi.queryRepoField<any>(query, 'pullRequests', { - paginate: false, - }); + const nodes = await githubApi.queryRepoField<GhGraphQlPr>( + query, + 'pullRequests', + { + paginate: false, + } + ); const prNumbers: number[] = []; // istanbul ignore if if (!nodes?.length) { @@ -513,12 +519,10 @@ async function getClosedPrs(): Promise<PrList> { pr.state = pr.state.toLowerCase(); pr.branchName = pr.headRefName; delete pr.headRefName; - pr.comments = pr.comments.nodes.map( - (comment: { databaseId: number; body: string }) => ({ - id: comment.databaseId, - body: comment.body, - }) - ); + pr.comments = pr.comments.nodes.map((comment) => ({ + id: comment.databaseId, + body: comment.body, + })); pr.body = 'dummy body'; // just in case config.closedPrList[pr.number] = pr; prNumbers.push(pr.number); @@ -598,10 +602,14 @@ async function getOpenPrs(): Promise<PrList> { } } `; - const nodes = await githubApi.queryRepoField<any>(query, 'pullRequests', { - paginate: false, - acceptHeader: 'application/vnd.github.merge-info-preview+json', - }); + const nodes = await githubApi.queryRepoField<GhGraphQlPr>( + query, + 'pullRequests', + { + paginate: false, + acceptHeader: 'application/vnd.github.merge-info-preview+json', + } + ); const prNumbers: number[] = []; // istanbul ignore if if (!nodes?.length) { @@ -636,9 +644,7 @@ async function getOpenPrs(): Promise<PrList> { pr.isConflicted = false; } if (pr.labels) { - pr.labels = pr.labels.nodes.map( - (label: { name: string }) => label.name - ); + pr.labels = pr.labels.nodes.map((label) => label.name); } pr.hasAssignees = !!(pr.assignees?.totalCount > 0); delete pr.assignees; @@ -681,7 +687,7 @@ export async function getPr(prNo: number): Promise<Pr | null> { 'PR not found in open or closed PRs list - trying to fetch it directly' ); const pr = ( - await githubApi.getJson<any>( + await githubApi.getJson<GhRestPr>( `repos/${config.parentRepo || config.repository}/pulls/${prNo}` ) ).body; @@ -805,7 +811,7 @@ async function getStatus( // Returns the combined status for a branch. export async function getBranchStatus( branchName: string, - requiredStatusChecks: any + requiredStatusChecks: any[] | undefined ): Promise<BranchStatus> { logger.debug(`getBranchStatus(${branchName})`); if (!requiredStatusChecks) { @@ -1036,7 +1042,7 @@ export async function findIssue(title: string): Promise<Issue | null> { if (!issue) { return null; } - logger.debug('Found issue ' + issue.number); + logger.debug(`Found issue ${issue.number}`); const issueBody = ( await githubApi.getJson<{ body: string }>( `repos/${config.parentRepo || config.repository}/issues/${issue.number}` @@ -1090,7 +1096,7 @@ export async function ensureIssue({ } for (const i of issues) { if (i.state === 'open' && i.number !== issue.number) { - logger.warn('Closing duplicate issue ' + i.number); + logger.warn(`Closing duplicate issue ${i.number}`); await closeIssue(i.number); } } @@ -1139,7 +1145,9 @@ export async function ensureIssue({ } catch (err) /* istanbul ignore next */ { if (err.body?.message?.startsWith('Issues are disabled for this repo')) { logger.debug( - `Issues are disabled, so could not create issue: ${err.message}` + `Issues are disabled, so could not create issue: ${ + (err as Error).message + }` ); } else { logger.warn({ err }, 'Could not ensure issue'); @@ -1163,7 +1171,7 @@ export async function addAssignees( issueNo: number, assignees: string[] ): Promise<void> { - logger.debug(`Adding assignees ${assignees} to #${issueNo}`); + logger.debug(`Adding assignees '${assignees.join(', ')}' to #${issueNo}`); const repository = config.parentRepo || config.repository; await githubApi.postJson(`repos/${repository}/issues/${issueNo}/assignees`, { body: { @@ -1176,7 +1184,7 @@ export async function addReviewers( prNo: number, reviewers: string[] ): Promise<void> { - logger.debug(`Adding reviewers ${reviewers} to #${prNo}`); + logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${prNo}`); const userReviewers = reviewers.filter((e) => !e.startsWith('team:')); const teamReviewers = reviewers @@ -1203,7 +1211,7 @@ async function addLabels( issueNo: number, labels: string[] | null ): Promise<void> { - logger.debug(`Adding labels ${labels} to #${issueNo}`); + logger.debug(`Adding labels '${labels?.join(', ')}' to #${issueNo}`); const repository = config.parentRepo || config.repository; if (is.array(labels) && labels.length) { await githubApi.postJson(`repos/${repository}/issues/${issueNo}/labels`, { @@ -1507,7 +1515,7 @@ export async function mergePr( config.parentRepo || config.repository }/pulls/${prNo}/merge`; const options = { - body: {} as any, + body: {} as { merge_method?: string }, }; let automerged = false; if (config.mergeMethod) { @@ -1611,16 +1619,14 @@ export async function getVulnerabilityAlerts(): Promise<VulnerabilityAlert[]> { } } }`; - let alerts = []; + let alerts: VulnerabilityAlert[] = []; try { - const vulnerabilityAlerts = await githubApi.queryRepoField<{ node: any }>( - query, - 'vulnerabilityAlerts', - { - paginate: false, - acceptHeader: 'application/vnd.github.vixen-preview+json', - } - ); + const vulnerabilityAlerts = await githubApi.queryRepoField<{ + node: VulnerabilityAlert; + }>(query, 'vulnerabilityAlerts', { + paginate: false, + acceptHeader: 'application/vnd.github.vixen-preview+json', + }); if (vulnerabilityAlerts?.length) { alerts = vulnerabilityAlerts.map((edge) => edge.node); if (alerts.length) { diff --git a/lib/platform/github/types.ts b/lib/platform/github/types.ts index 04cb7785e75ad414a6d867f6fe305ac2aabc513d..d2e868c1f19c89956f3aca204990279bb03b4ed0 100644 --- a/lib/platform/github/types.ts +++ b/lib/platform/github/types.ts @@ -22,6 +22,24 @@ export interface Comment { export interface GhPr extends Pr { comments: Comment[]; + mergeable: boolean; +} + +export interface GhRestPr extends GhPr { + head: { ref: string; sha: string }; + mergeable_state: string; +} + +export interface GhGraphQlPr extends GhPr { + commits: any; + reviewRequests: any; + assignees: any; + mergeStateStatus: string; + reviews: any; + baseRefName: string; + headRefName: string; + comments: Comment[] & { nodes?: { databaseId: number; body: string }[] }; + labels: string[] & { nodes?: { name: string }[] }; } export interface LocalRepoConfig { diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index 3308fab02d3c66eab3bd0e29d95912800d765321..d069d8a0ccb48557325ff2d6fe7fbccf30d86e4c 100644 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -1,6 +1,5 @@ import URL, { URLSearchParams } from 'url'; import is from '@sindresorhus/is'; - import delay from 'delay'; import { configFileNames } from '../../config/app-strings'; import { RenovateConfig } from '../../config/common'; @@ -40,29 +39,17 @@ import { VulnerabilityAlert, } from '../common'; import { smartTruncate } from '../utils/pr-body'; +import { GitlabComment, GitlabIssue, MergeMethod, RepoResponse } from './types'; const gitlabApi = new GitlabHttp(); -type MergeMethod = 'merge' | 'rebase_merge' | 'ff'; -type RepoResponse = { - archived: boolean; - mirror: boolean; - default_branch: string; - empty_repo: boolean; - http_url_to_repo: string; - forked_from_project: boolean; - repository_access_level: 'disabled' | 'private' | 'enabled'; - merge_requests_access_level: 'disabled' | 'private' | 'enabled'; - merge_method: MergeMethod; - path_with_namespace: string; -}; const defaultConfigFile = configFileNames[0]; let config: { repository: string; localDir: string; email: string; prList: any[]; - issueList: any[]; + issueList: GitlabIssue[]; optimizeForDisabled: boolean; mergeMethod: MergeMethod; } = {} as any; @@ -610,7 +597,7 @@ export async function setBranchStatus({ // Issue -export async function getIssueList(): Promise<any[]> { +export async function getIssueList(): Promise<GitlabIssue[]> { if (!config.issueList) { const query = new URLSearchParams({ per_page: '100', @@ -641,7 +628,7 @@ export async function findIssue(title: string): Promise<Issue | null> { logger.debug(`findIssue(${title})`); try { const issueList = await getIssueList(); - const issue = issueList.find((i: { title: string }) => i.title === title); + const issue = issueList.find((i) => i.title === title); if (!issue) { return null; } @@ -669,9 +656,9 @@ export async function ensureIssue({ const description = getPrBody(sanitize(body)); try { const issueList = await getIssueList(); - let issue = issueList.find((i: { title: string }) => i.title === title); + let issue = issueList.find((i) => i.title === title); if (!issue) { - issue = issueList.find((i: { title: string }) => i.title === reuseTitle); + issue = issueList.find((i) => i.title === reuseTitle); } if (issue) { const existingDescription = ( @@ -703,7 +690,7 @@ export async function ensureIssue({ } } catch (err) /* istanbul ignore next */ { if (err.message.startsWith('Issues are disabled for this repo')) { - logger.debug(`Could not create issue: ${err.message}`); + logger.debug(`Could not create issue: ${(err as Error).message}`); } else { logger.warn({ err }, 'Could not ensure issue'); } @@ -731,7 +718,7 @@ export async function addAssignees( iid: number, assignees: string[] ): Promise<void> { - logger.debug(`Adding assignees ${assignees} to #${iid}`); + logger.debug(`Adding assignees '${assignees.join(', ')}' to #${iid}`); try { let assigneeId = ( await gitlabApi.getJson<{ id: number }[]>( @@ -763,7 +750,7 @@ export async function addAssignees( } export function addReviewers(iid: number, reviewers: string[]): Promise<void> { - logger.debug(`addReviewers('${iid}, '${reviewers})`); + logger.debug(`addReviewers('${iid}, [${reviewers.join(', ')}])`); logger.warn('Unimplemented in GitLab: approvals'); return Promise.resolve(); } @@ -883,11 +870,6 @@ export async function ensureComment({ return true; } -type GitlabComment = { - body: string; - id: number; -}; - export async function ensureCommentRemoval({ number: issueNo, topic, diff --git a/lib/platform/gitlab/types.ts b/lib/platform/gitlab/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..fda51a9ffcf971f962233184b70dad01c6c7992e --- /dev/null +++ b/lib/platform/gitlab/types.ts @@ -0,0 +1,24 @@ +export interface GitlabIssue { + iid: number; + title: string; +} + +export interface GitlabComment { + body: string; + id: number; +} + +export type MergeMethod = 'merge' | 'rebase_merge' | 'ff'; + +export type RepoResponse = { + archived: boolean; + mirror: boolean; + default_branch: string; + empty_repo: boolean; + http_url_to_repo: string; + forked_from_project: boolean; + repository_access_level: 'disabled' | 'private' | 'enabled'; + merge_requests_access_level: 'disabled' | 'private' | 'enabled'; + merge_method: MergeMethod; + path_with_namespace: string; +}; diff --git a/lib/types/git.ts b/lib/types/git.ts index 073995d025d4e5ef602759ef3710e7a46a0d1cbe..e6e25ed4cd70c606d4b4e179deb9e2598a869415 100644 --- a/lib/types/git.ts +++ b/lib/types/git.ts @@ -3,3 +3,7 @@ export type GitTreeNode = { path: string; mode: string; }; + +export type GitProtocol = 'ssh' | 'http' | 'https'; + +export type GitOptions = Record<string, null | string | number>; diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 8b6be5db69781bad1316f9ab17e5c968e065f121..12af27d96f4d367bd58e9d2dccbafbeee22f6271 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -3,7 +3,6 @@ import URL from 'url'; import fs from 'fs-extra'; import Git, { DiffResult as DiffResult_, - Options, ResetMode, SimpleGit, StatusResult as StatusResult_, @@ -17,6 +16,7 @@ import { } from '../../constants/error-messages'; import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; +import { GitOptions, GitProtocol } from '../../types/git'; import * as limits from '../../workers/global/limits'; import { writePrivateKey } from './private-key'; @@ -34,7 +34,7 @@ interface StorageConfig { localDir: string; currentBranch?: string; url: string; - extraCloneOpts?: Options; + extraCloneOpts?: GitOptions; gitAuthorName?: string; gitAuthorEmail?: string; } @@ -214,10 +214,10 @@ export async function syncGit(): Promise<void> { const cloneStart = Date.now(); try { // clone only the default branch - let opts = ['--depth=2']; + const opts = ['--depth=2']; if (config.extraCloneOpts) { - opts = opts.concat( - Object.entries(config.extraCloneOpts).map((e) => `${e[0]}=${e[1]}`) + opts.push( + ...Object.entries(config.extraCloneOpts).map((e) => `${e[0]}=${e[1]}`) ); } await git.clone(config.url, '.', opts); @@ -661,7 +661,7 @@ export function getUrl({ host, repository, }: { - protocol?: 'ssh' | 'http' | 'https'; + protocol?: GitProtocol; auth?: string; hostname?: string; host?: string; diff --git a/lib/workers/common.ts b/lib/workers/common.ts index 7ba92997535b56f789f5ed33ef686f302ba5d9b6..b0673050a363b2b42789e392bde2a876d2aa842e 100644 --- a/lib/workers/common.ts +++ b/lib/workers/common.ts @@ -1,3 +1,4 @@ +import type { Merge } from 'type-fest'; import { GroupConfig, RenovateAdminConfig, @@ -15,7 +16,6 @@ import { import { PlatformPrOptions } from '../platform'; import { File } from '../util/git'; import { ChangeLogResult } from './pr/changelog/common'; -import { Merge } from 'type-fest'; export interface BranchUpgradeConfig extends Merge<RenovateConfig, PackageDependency>, diff --git a/lib/workers/repository/updates/branchify.ts b/lib/workers/repository/updates/branchify.ts index 2d2320e7030d8fc88108ba74f51fd6f382801889..f3d20fd4d51d9a9a2862034600c3fee261486c34 100644 --- a/lib/workers/repository/updates/branchify.ts +++ b/lib/workers/repository/updates/branchify.ts @@ -1,5 +1,6 @@ import { clean as cleanGitRef } from 'clean-git-ref'; import slugify from 'slugify'; +import type { Merge } from 'type-fest'; import { RenovateConfig, ValidationMessage } from '../../../config'; import { addMeta, logger, removeMeta } from '../../../logger'; import * as template from '../../../util/template'; @@ -7,7 +8,6 @@ import { BranchConfig, BranchUpgradeConfig } from '../../common'; import { embedChangelogs } from '../changelog'; import { flattenUpdates } from './flatten'; import { generateBranchConfig } from './generate'; -import { Merge } from 'type-fest'; /** * Clean git branch name diff --git a/test/httpMock.ts b/test/httpMock.ts index dfc1295284c4b15e8f4c4044238e7b1be1d05f80..1317d730986f95e1a4126186e40d626483a8a94d 100644 --- a/test/httpMock.ts +++ b/test/httpMock.ts @@ -82,7 +82,12 @@ function simplifyGraphqlAST(tree: any): any { return tree; } -function onMissing(req: any, opts: any): void /* istanbul ignore next */ { +type TestRequest = { + method: string; + href: string; +}; + +function onMissing(req: TestRequest, opts?: TestRequest): void { if (!opts) { missingLog.push(` ${req.method} ${req.href}`); } else { diff --git a/test/newline-snapshot-serializer.ts b/test/newline-snapshot-serializer.ts index 86d72856e0e4c59159449fbbe1721e05739c213f..adbd6741563406276668149150d5cd586b8e87b6 100644 --- a/test/newline-snapshot-serializer.ts +++ b/test/newline-snapshot-serializer.ts @@ -1,9 +1,11 @@ let prev: string; -export function print(val: any): string { +// this does not work as intended +// see https://jestjs.io/docs/en/configuration#snapshotserializers-arraystring +export function print(val: string): string { return JSON.stringify(val); } -export function test(val: any): boolean { +export function test(val: string): boolean { if (['prBody', 'prTitle'].some((str) => str === prev)) { return typeof val === 'string' && val.includes('\n'); } diff --git a/test/util.ts b/test/util.ts index 8b4b2170345ea5d2e6525b7a247cdf7bc1438f05..4dd6fe791c3aefd6486ce25443037de4df8903c0 100644 --- a/test/util.ts +++ b/test/util.ts @@ -1,5 +1,5 @@ import crypto from 'crypto'; -import { expect, jest } from '@jest/globals'; +import { expect } from '@jest/globals'; import { RenovateConfig as _RenovateConfig } from '../lib/config'; import { getConfig } from '../lib/config/defaults'; import { platform as _platform } from '../lib/platform'; diff --git a/test/website-docs.spec.ts b/test/website-docs.spec.ts index b199495d11a831f048a536050e910d9b69f2eb6f..68c9bbaf17d491054163b73820f47e1dba31ebc6 100644 --- a/test/website-docs.spec.ts +++ b/test/website-docs.spec.ts @@ -84,7 +84,7 @@ describe('docs', () => { on an error, it throws a custom message. */ expect.extend({ - toContainOption<T>(received: T[], argument: T) { + toContainOption<T extends string>(received: T[], argument: T) { if (received.includes(argument)) { return { message: (): string => diff --git a/tools/eslint-gh-reporter.ts b/tools/eslint-gh-reporter.ts index b11e65dbb7bf031abe9fc0d19a45362123cb8367..4d9ab6452770a578779d59569c8263bb134ab764 100644 --- a/tools/eslint-gh-reporter.ts +++ b/tools/eslint-gh-reporter.ts @@ -38,7 +38,7 @@ const formatter: CLIEngine.Formatter = (results) => { } } } catch (e) { - error(`Unexpected error: ${e}`); + error(`Unexpected error: ${(e as Error).toString()}`); } return ''; }; diff --git a/tools/jest-gh-reporter.ts b/tools/jest-gh-reporter.ts index de6c33b362e5dda001c080fbad78df127237ffbb..3112a8c88364199dcbbb37c13aa6b3d354235643 100644 --- a/tools/jest-gh-reporter.ts +++ b/tools/jest-gh-reporter.ts @@ -67,7 +67,7 @@ class GitHubReporter extends BaseReporter { } } } catch (e) { - error(`Unexpected error: ${e}`); + error(`Unexpected error: ${(e as Error).toString()}`); } } } diff --git a/tsconfig.json b/tsconfig.json index 3f4ddb1d0689c2d64a2ffa63304aaf42b82f98b4..78c477e57071f45ea79fd767ec074cbf4509039a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,6 +11,7 @@ "esModuleInterop": true, "resolveJsonModule": false, "isolatedModules": true, + "noUnusedLocals": true, "lib": ["es2018"], "types": ["node", "jest"], "allowJs": true,