From 5723be1ac5c776cff5c549457bd3cc238c54b5cf Mon Sep 17 00:00:00 2001 From: Michael Kriese <michael.kriese@visualon.de> Date: Fri, 11 Feb 2022 11:02:30 +0100 Subject: [PATCH] refactor: add strict null checks (#14169) --- lib/config/decrypt.ts | 6 +- lib/config/presets/internal/index.ts | 2 +- lib/config/secrets.ts | 11 ++- lib/config/types.ts | 2 +- lib/platform/bitbucket-server/types.ts | 12 ++++ lib/platform/bitbucket-server/utils.spec.ts | 38 ++++++++++ lib/platform/bitbucket-server/utils.ts | 27 +++---- lib/platform/bitbucket/comments.ts | 2 +- lib/platform/github/massage-markdown-links.ts | 10 +-- lib/platform/github/user.ts | 4 +- lib/platform/types.ts | 4 +- lib/types/base.ts | 1 + lib/types/index.ts | 2 + lib/util/git/auth.ts | 8 ++- lib/util/git/author.ts | 10 +-- lib/util/git/types.ts | 2 +- lib/util/ignore.ts | 2 +- lib/util/index.spec.ts | 2 +- lib/util/merge-confidence/index.ts | 25 +++---- lib/workers/branch/automerge.ts | 2 +- lib/workers/branch/index.spec.ts | 13 +++- lib/workers/branch/reuse.spec.ts | 1 + lib/workers/branch/schedule.ts | 30 ++++---- lib/workers/global/config/parse/cli.spec.ts | 6 +- lib/workers/global/config/parse/cli.ts | 5 +- lib/workers/global/config/parse/env.spec.ts | 8 +-- lib/workers/global/config/parse/env.ts | 16 +++-- lib/workers/global/config/parse/file.ts | 2 +- lib/workers/global/config/parse/types.ts | 4 ++ lib/workers/pr/body/updates-table.ts | 6 +- .../repository/extract/file-match.spec.ts | 2 +- lib/workers/repository/finalise/prune.spec.ts | 3 - lib/workers/repository/result.ts | 8 +-- lib/workers/repository/stats.ts | 5 ++ tools/docs/config.ts | 5 +- tsconfig.strict.json | 71 +------------------ 36 files changed, 177 insertions(+), 180 deletions(-) create mode 100644 lib/platform/bitbucket-server/utils.spec.ts create mode 100644 lib/workers/global/config/parse/types.ts diff --git a/lib/config/decrypt.ts b/lib/config/decrypt.ts index 550e503800..65099de4aa 100644 --- a/lib/config/decrypt.ts +++ b/lib/config/decrypt.ts @@ -49,7 +49,7 @@ export function tryDecryptPublicKeyDefault( privateKey: string, encryptedStr: string ): string | null { - let decryptedStr: string = null; + let decryptedStr: string | null = null; try { decryptedStr = crypto .privateDecrypt(privateKey, Buffer.from(encryptedStr, 'base64')) @@ -65,7 +65,7 @@ export function tryDecryptPublicKeyPKCS1( privateKey: string, encryptedStr: string ): string | null { - let decryptedStr: string = null; + let decryptedStr: string | null = null; try { decryptedStr = crypto .privateDecrypt( @@ -87,7 +87,7 @@ export async function tryDecrypt( encryptedStr: string, repository: string ): Promise<string | null> { - let decryptedStr: string = null; + let decryptedStr: string | null = null; if (privateKey?.startsWith('-----BEGIN PGP PRIVATE KEY BLOCK-----')) { const decryptedObjStr = await tryDecryptPgp(privateKey, encryptedStr); if (decryptedObjStr) { diff --git a/lib/config/presets/internal/index.ts b/lib/config/presets/internal/index.ts index b0dd3dcbe4..e96253c9c3 100644 --- a/lib/config/presets/internal/index.ts +++ b/lib/config/presets/internal/index.ts @@ -35,7 +35,7 @@ export function getPreset({ packageName: pkgName, presetName, }: PresetConfig): Preset | undefined { - return groups[pkgName] + return groups[pkgName] && presetName ? groups[pkgName][presetName] : /* istanbul ignore next */ undefined; } diff --git a/lib/config/secrets.ts b/lib/config/secrets.ts index e69df90e43..74d2be9878 100644 --- a/lib/config/secrets.ts +++ b/lib/config/secrets.ts @@ -102,17 +102,13 @@ function replaceSecretsinObject( if (is.array(value)) { for (const [arrayIndex, arrayItem] of value.entries()) { if (is.plainObject(arrayItem)) { - config[key][arrayIndex] = replaceSecretsinObject( + value[arrayIndex] = replaceSecretsinObject( arrayItem, secrets, deleteSecrets ); } else if (is.string(arrayItem)) { - config[key][arrayIndex] = replaceSecretsInString( - key, - arrayItem, - secrets - ); + value[arrayIndex] = replaceSecretsInString(key, arrayItem, secrets); } } } @@ -131,5 +127,6 @@ export function applySecretsToConfig( addSecretForSanitizing(String(secret)); } } - return replaceSecretsinObject(config, secrets, deleteSecrets); + // TODO: fix types (#9610) + return replaceSecretsinObject(config, secrets as never, deleteSecrets); } diff --git a/lib/config/types.ts b/lib/config/types.ts index 0beac92cdd..e792be3aa0 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -61,7 +61,7 @@ export interface RenovateSharedConfig { repositoryCache?: RepositoryCacheConfig; schedule?: string[]; semanticCommits?: 'auto' | 'enabled' | 'disabled'; - semanticCommitScope?: string; + semanticCommitScope?: string | null; semanticCommitType?: string; suppressNotifications?: string[]; timezone?: string; diff --git a/lib/platform/bitbucket-server/types.ts b/lib/platform/bitbucket-server/types.ts index 9efb9caf76..fe5d4f2f74 100644 --- a/lib/platform/bitbucket-server/types.ts +++ b/lib/platform/bitbucket-server/types.ts @@ -1,3 +1,4 @@ +import type { HTTPError, Response } from 'got'; import type { Pr } from '../types'; export interface BbsConfig { @@ -57,3 +58,14 @@ export interface BbsRestRepo { export interface BbsRestBranch { displayId: string; } + +export interface BitbucketErrorResponse { + errors?: { + exceptionName?: string; + reviewerErrors?: { context?: string }[]; + }[]; +} + +export interface BitbucketError extends HTTPError { + readonly response: Response<BitbucketErrorResponse>; +} diff --git a/lib/platform/bitbucket-server/utils.spec.ts b/lib/platform/bitbucket-server/utils.spec.ts new file mode 100644 index 0000000000..445f61a649 --- /dev/null +++ b/lib/platform/bitbucket-server/utils.spec.ts @@ -0,0 +1,38 @@ +import type { Response } from 'got'; +import { partial } from '../../../test/util'; +import type { BitbucketError, BitbucketErrorResponse } from './types'; +import { + BITBUCKET_INVALID_REVIEWERS_EXCEPTION, + getInvalidReviewers, +} from './utils'; + +describe('platform/bitbucket-server/utils', () => { + function createError(body: Partial<BitbucketErrorResponse> = undefined) { + return partial<BitbucketError>({ + response: partial<Response<BitbucketErrorResponse>>({ body }), + }); + } + + it('getInvalidReviewers', () => { + expect( + getInvalidReviewers( + createError({ + errors: [ + { + exceptionName: BITBUCKET_INVALID_REVIEWERS_EXCEPTION, + reviewerErrors: [{ context: 'dummy' }, {}], + }, + ], + }) + ) + ).toStrictEqual(['dummy']); + expect(getInvalidReviewers(createError())).toStrictEqual([]); + expect( + getInvalidReviewers( + createError({ + errors: [{ exceptionName: BITBUCKET_INVALID_REVIEWERS_EXCEPTION }], + }) + ) + ).toStrictEqual([]); + }); +}); diff --git a/lib/platform/bitbucket-server/utils.ts b/lib/platform/bitbucket-server/utils.ts index cc248e8896..ba35cf8ebd 100644 --- a/lib/platform/bitbucket-server/utils.ts +++ b/lib/platform/bitbucket-server/utils.ts @@ -1,6 +1,6 @@ // SEE for the reference https://github.com/renovatebot/renovate/blob/c3e9e572b225085448d94aa121c7ec81c14d3955/lib/platform/bitbucket/utils.js import url from 'url'; -import type { HTTPError, Response } from 'got'; +import is from '@sindresorhus/is'; import { PrState } from '../../types'; import type { HttpOptions, @@ -8,9 +8,9 @@ import type { HttpResponse, } from '../../util/http'; import { BitbucketServerHttp } from '../../util/http/bitbucket-server'; -import type { BbsPr, BbsRestPr } from './types'; +import type { BbsPr, BbsRestPr, BitbucketError } from './types'; -const BITBUCKET_INVALID_REVIEWERS_EXCEPTION = +export const BITBUCKET_INVALID_REVIEWERS_EXCEPTION = 'com.atlassian.bitbucket.pull.InvalidPullRequestReviewersException'; const bitbucketServerHttp = new BitbucketServerHttp(); @@ -127,19 +127,8 @@ export interface BitbucketStatus { state: BitbucketBranchState; } -interface BitbucketErrorResponse { - errors?: { - exceptionName?: string; - reviewerErrors?: { context?: string }[]; - }[]; -} - -interface BitbucketError extends HTTPError { - readonly response: Response<BitbucketErrorResponse>; -} - export function isInvalidReviewersResponse(err: BitbucketError): boolean { - const errors = err?.response?.body?.errors || []; + const errors = err?.response?.body?.errors ?? []; return ( errors.length > 0 && errors.every( @@ -149,12 +138,14 @@ export function isInvalidReviewersResponse(err: BitbucketError): boolean { } export function getInvalidReviewers(err: BitbucketError): string[] { - const errors = err?.response?.body?.errors || []; - let invalidReviewers = []; + const errors = err?.response?.body?.errors ?? []; + let invalidReviewers: string[] = []; for (const error of errors) { if (error.exceptionName === BITBUCKET_INVALID_REVIEWERS_EXCEPTION) { invalidReviewers = invalidReviewers.concat( - error.reviewerErrors?.map(({ context }) => context) || [] + error.reviewerErrors + ?.map(({ context }) => context) + .filter(is.nonEmptyString) ?? [] ); } } diff --git a/lib/platform/bitbucket/comments.ts b/lib/platform/bitbucket/comments.ts index 159ed3e109..afce16d4dc 100644 --- a/lib/platform/bitbucket/comments.ts +++ b/lib/platform/bitbucket/comments.ts @@ -131,7 +131,7 @@ export async function ensureCommentRemoval( const byContent = (comment: Comment): boolean => comment.content.raw.trim() === content; - let commentId: number | null = null; + let commentId: number | undefined = undefined; if (topic) { commentId = comments.find(byTopic)?.id; diff --git a/lib/platform/github/massage-markdown-links.ts b/lib/platform/github/massage-markdown-links.ts index 84391ff764..01249af34e 100644 --- a/lib/platform/github/massage-markdown-links.ts +++ b/lib/platform/github/massage-markdown-links.ts @@ -20,8 +20,8 @@ function massageLink(input: string): string { function collectLinkPosition(input: string, matches: UrlMatch[]): Plugin { const transformer = (tree: Content): void => { - const startOffset: number = tree.position.start.offset; - const endOffset: number = tree.position.end.offset; + const startOffset: number = tree.position?.start.offset ?? 0; + const endOffset: number = tree.position?.end.offset ?? 0; if (tree.type === 'link') { const substr = input.slice(startOffset, endOffset); @@ -39,7 +39,7 @@ function collectLinkPosition(input: string, matches: UrlMatch[]): Plugin { const urlMatches = [...tree.value.matchAll(globalUrlReg)]; for (const match of urlMatches) { const [url] = match; - const start = startOffset + match.index; + const start = startOffset + (match.index ?? 0); const end = start + url.length; const newUrl = massageLink(url); matches.push({ start, end, replaceTo: `[${url}](${newUrl})` }); @@ -56,7 +56,7 @@ function collectLinkPosition(input: string, matches: UrlMatch[]): Plugin { export function massageMarkdownLinks(content: string): string { try { - const rightSpaces = content.replace(content.trimRight(), ''); + const rightSpaces = content.replace(content.trimEnd(), ''); const matches: UrlMatch[] = []; remark().use(collectLinkPosition(content, matches)).processSync(content); const result = matches.reduceRight((acc, { start, end, replaceTo }) => { @@ -64,7 +64,7 @@ export function massageMarkdownLinks(content: string): string { const rightPart = acc.slice(end); return leftPart + replaceTo + rightPart; }, content); - return result.trimRight() + rightSpaces; + return result.trimEnd() + rightSpaces; } catch (err) /* istanbul ignore next */ { logger.warn({ err }, `Unable to massage markdown text`); return content; diff --git a/lib/platform/github/user.ts b/lib/platform/github/user.ts index fb7f2a08d1..24a5b93f6c 100644 --- a/lib/platform/github/user.ts +++ b/lib/platform/github/user.ts @@ -37,7 +37,7 @@ export async function getUserDetails( } } -let userEmail: string; +let userEmail: string | null; export async function getUserEmail( endpoint: string, @@ -49,7 +49,7 @@ export async function getUserEmail( token, }) ).body; - userEmail = emails?.[0].email || null; + userEmail = emails?.[0].email ?? null; return userEmail; } catch (err) { logger.debug( diff --git a/lib/platform/types.ts b/lib/platform/types.ts index 6a65a04d8f..581e779041 100644 --- a/lib/platform/types.ts +++ b/lib/platform/types.ts @@ -56,7 +56,7 @@ export interface Pr { hasAssignees?: boolean; hasReviewers?: boolean; labels?: string[]; - number?: number; + number: number; reviewers?: string[]; sha?: string; sourceRepo?: string; @@ -127,7 +127,7 @@ export interface MergePRConfig { } export interface EnsureCommentConfig { number: number; - topic: string; + topic: string | null; content: string; } diff --git a/lib/types/base.ts b/lib/types/base.ts index 4fa51018b8..daa6d1f03c 100644 --- a/lib/types/base.ts +++ b/lib/types/base.ts @@ -7,4 +7,5 @@ export interface ModuleApi { export type RenovatePackageJson = PackageJson & { 'engines-next': Record<string, string>; + version: string; }; diff --git a/lib/types/index.ts b/lib/types/index.ts index f85b78de34..a447eb060e 100644 --- a/lib/types/index.ts +++ b/lib/types/index.ts @@ -5,3 +5,5 @@ export * from './branch-status'; export * from './vulnerability-alert'; export * from './pr-state'; export * from './base'; + +export type AutoMergeType = 'branch' | 'pr' | 'pr-comment'; diff --git a/lib/util/git/auth.ts b/lib/util/git/auth.ts index 512a1ebe17..dcc5d4e253 100644 --- a/lib/util/git/auth.ts +++ b/lib/util/git/auth.ts @@ -23,14 +23,16 @@ export function getGitAuthenticatedEnvironmentVariables( // check if the environmentVariables already contain a GIT_CONFIG_COUNT or if the process has one const gitConfigCountEnvVariable = - environmentVariables?.GIT_CONFIG_COUNT || process.env.GIT_CONFIG_COUNT; + environmentVariables?.GIT_CONFIG_COUNT ?? process.env.GIT_CONFIG_COUNT; let gitConfigCount = 0; if (gitConfigCountEnvVariable) { // passthrough the gitConfigCountEnvVariable environment variable as start value of the index count gitConfigCount = parseInt(gitConfigCountEnvVariable, 10); if (Number.isNaN(gitConfigCount)) { logger.warn( - `Found GIT_CONFIG_COUNT env variable, but couldn't parse the value to an integer: ${process.env.GIT_CONFIG_COUNT}. Ignoring it.` + `Found GIT_CONFIG_COUNT env variable, but couldn't parse the value to an integer: ${String( + process.env.GIT_CONFIG_COUNT + )}. Ignoring it.` ); gitConfigCount = 0; } @@ -63,7 +65,7 @@ export function getGitAuthenticatedEnvironmentVariables( function getAuthenticationRulesWithToken( url: string, - hostType: string, + hostType: string | undefined, authToken: string ): AuthenticationRule[] { let token = authToken; diff --git a/lib/util/git/author.ts b/lib/util/git/author.ts index 26860683b6..8690538d6a 100644 --- a/lib/util/git/author.ts +++ b/lib/util/git/author.ts @@ -4,7 +4,7 @@ import { regEx } from '../regex'; import type { GitAuthor } from './types'; export function parseGitAuthor(input: string): GitAuthor | null { - let result: GitAuthor = null; + let result: GitAuthor | null = null; if (!input) { return null; } @@ -13,7 +13,7 @@ export function parseGitAuthor(input: string): GitAuthor | null { if (result) { return result; } - let massagedInput; + let massagedInput: string | undefined; let massagedBotEmail = false; if (input.includes('<') && input.includes('>')) { // try wrapping the name part in quotations @@ -21,7 +21,7 @@ export function parseGitAuthor(input: string): GitAuthor | null { } if (input.includes('[bot]@')) { // invalid github app/bot addresses - massagedInput = (massagedInput || input).replace('[bot]@', '@'); + massagedInput = (massagedInput ?? input).replace('[bot]@', '@'); massagedBotEmail = true; } if (!massagedInput) { @@ -30,11 +30,11 @@ export function parseGitAuthor(input: string): GitAuthor | null { const parsed = addrs.parseOneAddress(massagedInput) as addrs.ParsedMailbox; if (parsed?.address) { result = { - name: parsed.name || input.replace(regEx(/@.*/), ''), + name: parsed.name ?? input.replace(regEx(/@.*/), ''), address: parsed.address, }; if (massagedBotEmail) { - result.address = result.address.replace('@', '[bot]@'); + result.address = result.address?.replace('@', '[bot]@'); } return result; } diff --git a/lib/util/git/types.ts b/lib/util/git/types.ts index c09dce923e..9879eee87a 100644 --- a/lib/util/git/types.ts +++ b/lib/util/git/types.ts @@ -3,7 +3,7 @@ import type { GitOptions } from '../../types/git'; export type { DiffResult, StatusResult } from 'simple-git'; export interface GitAuthor { - name?: string; + name?: string | null; address?: string; } diff --git a/lib/util/ignore.ts b/lib/util/ignore.ts index fc16a2e137..507e321c13 100644 --- a/lib/util/ignore.ts +++ b/lib/util/ignore.ts @@ -2,7 +2,7 @@ import { logger } from '../logger'; import { regEx } from './regex'; export function isSkipComment(comment?: string): boolean { - if (regEx(/^(renovate|pyup):/).test(comment)) { + if (comment && regEx(/^(renovate|pyup):/).test(comment)) { const command = comment.split('#')[0].split(':')[1].trim(); if (command === 'ignore') { return true; diff --git a/lib/util/index.spec.ts b/lib/util/index.spec.ts index 5f541ec3d5..80844cd6b8 100644 --- a/lib/util/index.spec.ts +++ b/lib/util/index.spec.ts @@ -7,7 +7,7 @@ describe('util/index', () => { expect(sampleSize(array, 2)).toHaveLength(2); }); it('returns full array for undefined number', () => { - expect(sampleSize(array, undefined)).toEqual(array); + expect(sampleSize(array, undefined as never)).toEqual(array); }); it('returns full array for null number', () => { expect(sampleSize(array, null)).toBeEmptyArray(); diff --git a/lib/util/merge-confidence/index.ts b/lib/util/merge-confidence/index.ts index ec29993be7..a36dbb620f 100644 --- a/lib/util/merge-confidence/index.ts +++ b/lib/util/merge-confidence/index.ts @@ -29,18 +29,19 @@ export function satisfiesConfidenceLevel( return confidenceLevels[confidence] >= confidenceLevels[minimumConfidence]; } -const updateTypeConfidenceMapping: Record<UpdateType, MergeConfidence> = { - pin: 'high', - digest: 'neutral', - bump: 'neutral', - lockFileMaintenance: 'neutral', - lockfileUpdate: 'neutral', - rollback: 'neutral', - replacement: 'neutral', - major: null, - minor: null, - patch: null, -}; +const updateTypeConfidenceMapping: Record<UpdateType, MergeConfidence | null> = + { + pin: 'high', + digest: 'neutral', + bump: 'neutral', + lockFileMaintenance: 'neutral', + lockfileUpdate: 'neutral', + rollback: 'neutral', + replacement: 'neutral', + major: null, + minor: null, + patch: null, + }; export async function getMergeConfidenceLevel( datasource: string, diff --git a/lib/workers/branch/automerge.ts b/lib/workers/branch/automerge.ts index c2d53a1fc5..c2d51b11b5 100644 --- a/lib/workers/branch/automerge.ts +++ b/lib/workers/branch/automerge.ts @@ -34,7 +34,7 @@ export async function tryBranchAutomerge( logger.debug(`Automerging branch`); try { if (GlobalConfig.get('dryRun')) { - logger.info('DRY-RUN: Would automerge branch' + config.branchName); + logger.info(`DRY-RUN: Would automerge branch ${config.branchName}`); } else { await mergeBranch(config.branchName); } diff --git a/lib/workers/branch/index.spec.ts b/lib/workers/branch/index.spec.ts index ca83c4e0bb..2286cb6a58 100644 --- a/lib/workers/branch/index.spec.ts +++ b/lib/workers/branch/index.spec.ts @@ -1,4 +1,11 @@ -import { defaultConfig, fs, git, mocked, platform } from '../../../test/util'; +import { + defaultConfig, + fs, + git, + mocked, + partial, + platform, +} from '../../../test/util'; import { GlobalConfig } from '../../config/global'; import type { RepoGlobalConfig } from '../../config/types'; import { @@ -92,12 +99,12 @@ describe('workers/branch/index', () => { platform.massageMarkdown.mockImplementation((prBody) => prBody); prWorker.ensurePr.mockResolvedValue({ - pr: { + pr: partial<Pr>({ title: '', sourceBranch: '', state: '', body: '', - }, + }), }); GlobalConfig.set(adminConfig); sanitize.sanitize.mockImplementation((input) => input); diff --git a/lib/workers/branch/reuse.spec.ts b/lib/workers/branch/reuse.spec.ts index 9ffc2b0fcf..7f0f19bb20 100644 --- a/lib/workers/branch/reuse.spec.ts +++ b/lib/workers/branch/reuse.spec.ts @@ -9,6 +9,7 @@ jest.mock('../../util/git'); describe('workers/branch/reuse', () => { describe('shouldReuseExistingBranch(config)', () => { const pr: Pr = { + number: 42, sourceBranch: 'master', state: PrState.Open, title: 'any', diff --git a/lib/workers/branch/schedule.ts b/lib/workers/branch/schedule.ts index 8dd9efc6ab..1984e57225 100644 --- a/lib/workers/branch/schedule.ts +++ b/lib/workers/branch/schedule.ts @@ -13,9 +13,7 @@ const scheduleMappings: Record<string, string> = { monthly: 'before 3am on the first day of the month', }; -export function hasValidTimezone( - timezone: string -): [boolean] | [boolean, string] { +export function hasValidTimezone(timezone: string): [true] | [false, string] { if (!DateTime.local().setZone(timezone).isValid) { return [false, `Invalid schedule: Unsupported timezone ${timezone}`]; } @@ -24,8 +22,8 @@ export function hasValidTimezone( export function hasValidSchedule( schedule: string[] | null | 'at any time' -): [boolean] | [boolean, string] { - let message: string; +): [true] | [false, string] { + let message = ''; if ( !schedule || schedule === 'at any time' || @@ -65,7 +63,8 @@ export function hasValidSchedule( } if ( !parsedSchedule.schedules.some( - (s) => s.M || s.d !== undefined || s.D || s.t_a !== undefined || s.t_b + (s) => + !!s.M || s.d !== undefined || !!s.D || s.t_a !== undefined || !!s.t_b ) ) { message = `Invalid schedule: "${scheduleText}" has no months, days of week or time of day`; @@ -78,12 +77,17 @@ export function hasValidSchedule( // If any fail then we invalidate the whole thing return [false, message]; } - return [true, '']; + return [true]; } function cronMatches(cron: string, now: DateTime): boolean { const parsedCron = parseCron(cron); + // istanbul ignore if: doesn't return undefined but type will include undefined + if (!parsedCron) { + return false; + } + if (parsedCron.hours.indexOf(now.hour) === -1) { // Hours mismatch return false; @@ -129,9 +133,9 @@ export function isScheduledNow(config: RenovateConfig): boolean { ); configSchedule = [configSchedule]; } - const [validSchedule, errorMessage] = hasValidSchedule(configSchedule); - if (!validSchedule) { - logger.warn(errorMessage); + const validSchedule = hasValidSchedule(configSchedule); + if (!validSchedule[0]) { + logger.warn(validSchedule[1]); return true; } let now = DateTime.local(); @@ -139,9 +143,9 @@ export function isScheduledNow(config: RenovateConfig): boolean { // Adjust the time if repo is in a different timezone to renovate if (config.timezone) { logger.debug({ timezone: config.timezone }, 'Found timezone'); - const [validTimezone, error] = hasValidTimezone(config.timezone); - if (!validTimezone) { - logger.warn(error); + const validTimezone = hasValidTimezone(config.timezone); + if (!validTimezone[0]) { + logger.warn(validTimezone[1]); return true; } logger.debug('Adjusting now for timezone'); diff --git a/lib/workers/global/config/parse/cli.spec.ts b/lib/workers/global/config/parse/cli.spec.ts index cc9aa78092..41114a2980 100644 --- a/lib/workers/global/config/parse/cli.spec.ts +++ b/lib/workers/global/config/parse/cli.spec.ts @@ -1,7 +1,7 @@ -import type { RenovateOptions } from '../../../../config/types'; import * as datasourceDocker from '../../../../datasource/docker'; import getArgv from './__fixtures__/argv'; import * as cli from './cli'; +import type { ParseConfigOptions } from './types'; describe('workers/global/config/parse/cli', () => { let argv: string[]; @@ -10,13 +10,13 @@ describe('workers/global/config/parse/cli', () => { }); describe('.getCliName(definition)', () => { it('generates CLI value', () => { - const option: Partial<RenovateOptions> = { + const option: ParseConfigOptions = { name: 'oneTwoThree', }; expect(cli.getCliName(option)).toBe('--one-two-three'); }); it('generates returns empty if CLI false', () => { - const option: Partial<RenovateOptions> = { + const option: ParseConfigOptions = { name: 'oneTwoThree', cli: false, }; diff --git a/lib/workers/global/config/parse/cli.ts b/lib/workers/global/config/parse/cli.ts index e62b0a80b7..6152d96181 100644 --- a/lib/workers/global/config/parse/cli.ts +++ b/lib/workers/global/config/parse/cli.ts @@ -1,10 +1,11 @@ import { Command } from 'commander'; import { getOptions } from '../../../../config/options'; -import type { AllConfig, RenovateOptions } from '../../../../config/types'; +import type { AllConfig } from '../../../../config/types'; import { pkg } from '../../../../expose.cjs'; import { regEx } from '../../../../util/regex'; +import type { ParseConfigOptions } from './types'; -export function getCliName(option: Partial<RenovateOptions>): string { +export function getCliName(option: ParseConfigOptions): string { if (option.cli === false) { return ''; } diff --git a/lib/workers/global/config/parse/env.spec.ts b/lib/workers/global/config/parse/env.spec.ts index 725685ad2f..b30a09b4e8 100644 --- a/lib/workers/global/config/parse/env.spec.ts +++ b/lib/workers/global/config/parse/env.spec.ts @@ -1,7 +1,7 @@ -import type { RenovateOptions } from '../../../../config/types'; import { PlatformId } from '../../../../constants'; import { logger } from '../../../../logger'; import * as env from './env'; +import type { ParseConfigOptions } from './types'; describe('workers/global/config/parse/env', () => { describe('.getConfig(env)', () => { @@ -228,21 +228,21 @@ describe('workers/global/config/parse/env', () => { }); describe('.getEnvName(definition)', () => { it('returns empty', () => { - const option: Partial<RenovateOptions> = { + const option: ParseConfigOptions = { name: 'foo', env: false, }; expect(env.getEnvName(option)).toBe(''); }); it('returns existing env', () => { - const option: Partial<RenovateOptions> = { + const option: ParseConfigOptions = { name: 'foo', env: 'FOO', }; expect(env.getEnvName(option)).toBe('FOO'); }); it('generates RENOVATE_ env', () => { - const option: Partial<RenovateOptions> = { + const option: ParseConfigOptions = { name: 'oneTwoThree', }; expect(env.getEnvName(option)).toBe('RENOVATE_ONE_TWO_THREE'); diff --git a/lib/workers/global/config/parse/env.ts b/lib/workers/global/config/parse/env.ts index ca96985431..212ea2f4df 100644 --- a/lib/workers/global/config/parse/env.ts +++ b/lib/workers/global/config/parse/env.ts @@ -1,8 +1,9 @@ import is from '@sindresorhus/is'; import { getOptions } from '../../../../config/options'; -import type { AllConfig, RenovateOptions } from '../../../../config/types'; +import type { AllConfig } from '../../../../config/types'; import { PlatformId } from '../../../../constants'; import { logger } from '../../../../logger'; +import type { ParseConfigOptions } from './types'; function normalizePrefixes( env: NodeJS.ProcessEnv, @@ -21,7 +22,7 @@ function normalizePrefixes( return result; } -export function getEnvName(option: Partial<RenovateOptions>): string { +export function getEnvName(option: ParseConfigOptions): string { if (option.env === false) { return ''; } @@ -82,27 +83,28 @@ export function getConfig(inputEnv: NodeJS.ProcessEnv): AllConfig { options.forEach((option) => { if (option.env !== false) { const envName = getEnvName(option); - if (env[envName]) { + const envVal = env[envName]; + if (envVal) { if (option.type === 'array' && option.subType === 'object') { try { - const parsed = JSON.parse(env[envName]); + const parsed = JSON.parse(envVal); if (is.array(parsed)) { config[option.name] = parsed; } else { logger.debug( - { val: env[envName], envName }, + { val: envVal, envName }, 'Could not parse object array' ); } } catch (err) { logger.debug( - { val: env[envName], envName }, + { val: envVal, envName }, 'Could not parse environment variable' ); } } else { const coerce = coersions[option.type]; - config[option.name] = coerce(env[envName]); + config[option.name] = coerce(envVal); } } } diff --git a/lib/workers/global/config/parse/file.ts b/lib/workers/global/config/parse/file.ts index 66f195e0a1..4c8bdffabf 100644 --- a/lib/workers/global/config/parse/file.ts +++ b/lib/workers/global/config/parse/file.ts @@ -33,7 +33,7 @@ export async function getParsedContent(file: string): Promise<RenovateConfig> { } export async function getConfig(env: NodeJS.ProcessEnv): Promise<AllConfig> { - let configFile = env.RENOVATE_CONFIG_FILE || 'config.js'; + let configFile = env.RENOVATE_CONFIG_FILE ?? 'config.js'; if (!upath.isAbsolute(configFile)) { configFile = `${process.cwd()}/${configFile}`; } diff --git a/lib/workers/global/config/parse/types.ts b/lib/workers/global/config/parse/types.ts new file mode 100644 index 0000000000..53712baef5 --- /dev/null +++ b/lib/workers/global/config/parse/types.ts @@ -0,0 +1,4 @@ +import type { RenovateOptions } from '../../../../config/types'; + +export type ParseConfigOptions = Partial<RenovateOptions> & + Pick<RenovateOptions, 'name'>; diff --git a/lib/workers/pr/body/updates-table.ts b/lib/workers/pr/body/updates-table.ts index bb4aebe8d8..a76abe07fd 100644 --- a/lib/workers/pr/body/updates-table.ts +++ b/lib/workers/pr/body/updates-table.ts @@ -5,13 +5,13 @@ import type { BranchConfig } from '../../types'; type TableDefinition = { header: string; - value: string; + value: string | undefined; }; function getTableDefinition(config: BranchConfig): TableDefinition[] { const res: TableDefinition[] = []; - for (const header of config.prBodyColumns) { - const value = config.prBodyDefinitions[header]; + for (const header of config.prBodyColumns ?? []) { + const value = config.prBodyDefinitions?.[header]; res.push({ header, value }); } return res; diff --git a/lib/workers/repository/extract/file-match.spec.ts b/lib/workers/repository/extract/file-match.spec.ts index b23a5115bc..991dd90f51 100644 --- a/lib/workers/repository/extract/file-match.spec.ts +++ b/lib/workers/repository/extract/file-match.spec.ts @@ -44,7 +44,7 @@ describe('workers/repository/extract/file-match', () => { describe('getMatchingFiles()', () => { const config: RenovateConfig = { includePaths: [], - ignoredPaths: [], + ignorePaths: [], manager: 'npm', fileMatch: ['(^|/)package.json$'], }; diff --git a/lib/workers/repository/finalise/prune.spec.ts b/lib/workers/repository/finalise/prune.spec.ts index a57909be0e..1374351bbc 100644 --- a/lib/workers/repository/finalise/prune.spec.ts +++ b/lib/workers/repository/finalise/prune.spec.ts @@ -81,7 +81,6 @@ describe('workers/repository/finalise/prune', () => { }); it('does nothing on prune stale branches disabled', async () => { config.branchList = ['renovate/a', 'renovate/b']; - config.dryRun = false; config.pruneStaleBranches = false; git.getBranchList.mockReturnValueOnce( config.branchList.concat(['renovate/c']) @@ -94,7 +93,6 @@ describe('workers/repository/finalise/prune', () => { }); it('posts comment if someone pushed to PR', async () => { config.branchList = ['renovate/a', 'renovate/b']; - config.dryRun = false; git.getBranchList.mockReturnValueOnce( config.branchList.concat(['renovate/c']) ); @@ -136,7 +134,6 @@ describe('workers/repository/finalise/prune', () => { }); it('delete branch no PR', async () => { config.branchList = ['renovate/a', 'renovate/b']; - config.dryRun = false; git.getBranchList.mockReturnValueOnce( config.branchList.concat(['renovate/c']) ); diff --git a/lib/workers/repository/result.ts b/lib/workers/repository/result.ts index 9039eeab97..29faa3b545 100644 --- a/lib/workers/repository/result.ts +++ b/lib/workers/repository/result.ts @@ -23,8 +23,8 @@ type ProcessStatus = 'disabled' | 'enabled' | 'onboarding' | 'unknown'; export interface ProcessResult { res: string; status: ProcessStatus; - enabled: boolean; - onboarded: boolean; + enabled: boolean | undefined; + onboarded: boolean | undefined; } export function processResult( @@ -49,8 +49,8 @@ export function processResult( ]; const enabledStatuses = [CONFIG_SECRETS_EXPOSED, CONFIG_VALIDATION]; let status: ProcessStatus; - let enabled: boolean; - let onboarded: boolean; + let enabled: boolean | undefined; + let onboarded: boolean | undefined; // istanbul ignore next if (disabledStatuses.includes(res)) { status = 'disabled'; diff --git a/lib/workers/repository/stats.ts b/lib/workers/repository/stats.ts index cf46588261..8a145ea8b1 100644 --- a/lib/workers/repository/stats.ts +++ b/lib/workers/repository/stats.ts @@ -35,6 +35,11 @@ export function printRequestStats(): void { `${method.toUpperCase()} ${url} ${duration} ${queueDuration}` ); const { hostname } = URL.parse(url); + + // istanbul ignore if: TODO: fix types (#9610) + if (!hostname) { + return; + } requestHosts[hostname] = requestHosts[hostname] || []; requestHosts[hostname].push(httpRequest); } diff --git a/tools/docs/config.ts b/tools/docs/config.ts index a06fa355b5..e617cf9254 100644 --- a/tools/docs/config.ts +++ b/tools/docs/config.ts @@ -66,14 +66,15 @@ export async function generateConfig(dist: string, bot = false): Promise<void> { options .filter((option) => option.releaseStatus !== 'unpublished') .forEach((option) => { + // TODO: fix types (#9610) const el: Record<string, any> = { ...option }; let headerIndex = configOptionsRaw.indexOf(`## ${option.name}`); if (headerIndex === -1) { headerIndex = configOptionsRaw.indexOf(`### ${option.name}`); } if (bot) { - el.cli = getCliName(el); - el.env = getEnvName(el); + el.cli = getCliName(option); + el.env = getEnvName(option); if (el.cli === '') { el.cli = `N/A`; } diff --git a/tsconfig.strict.json b/tsconfig.strict.json index b94fc530cb..ae95fad7e3 100644 --- a/tsconfig.strict.json +++ b/tsconfig.strict.json @@ -17,31 +17,12 @@ // TODO: fixme "**/*.spec.ts", - "bin/create-json-schema.js", "lib/config-validator.ts", - "lib/config/decrypt.ts", "lib/config/defaults.ts", "lib/config/index.ts", "lib/config/massage.ts", "lib/config/migrate-validate.ts", "lib/config/migration.ts", - "lib/config/migrations/base/abstract-migration.ts", - "lib/config/migrations/base/remove-property-migration.ts", - "lib/config/migrations/base/rename-property-migration.ts", - "lib/config/migrations/custom/binary-source-migration.ts", - "lib/config/migrations/custom/composer-ignore-platform-reqs-migration.ts", - "lib/config/migrations/custom/enabled-managers-migration.ts", - "lib/config/migrations/custom/go-mod-tidy-migration.ts", - "lib/config/migrations/custom/ignore-node-modules-migration.ts", - "lib/config/migrations/custom/pin-versions-migration.ts", - "lib/config/migrations/custom/raise-deprecation-warnings-migration.ts", - "lib/config/migrations/custom/rebase-conflicted-prs-migration.ts", - "lib/config/migrations/custom/rebase-stale-prs-migration.ts", - "lib/config/migrations/custom/required-status-checks-migration.ts", - "lib/config/migrations/custom/semantic-commits-migration.ts", - "lib/config/migrations/custom/trust-level-migration.ts", - "lib/config/migrations/custom/upgrade-in-range-migration.ts", - "lib/config/migrations/custom/version-strategy-migration.ts", "lib/config/options/index.ts", "lib/config/presets/azure/index.ts", "lib/config/presets/bitbucket-server/index.ts", @@ -50,31 +31,12 @@ "lib/config/presets/github/index.ts", "lib/config/presets/gitlab/index.ts", "lib/config/presets/index.ts", - "lib/config/presets/internal/compatibility.ts", - "lib/config/presets/internal/config.ts", - "lib/config/presets/internal/default.ts", - "lib/config/presets/internal/docker.ts", - "lib/config/presets/internal/group.ts", - "lib/config/presets/internal/helpers.ts", - "lib/config/presets/internal/index.ts", - "lib/config/presets/internal/monorepo.ts", - "lib/config/presets/internal/npm.ts", - "lib/config/presets/internal/packages.ts", - "lib/config/presets/internal/preview.ts", - "lib/config/presets/internal/regex-managers.ts", - "lib/config/presets/internal/replacements.ts", - "lib/config/presets/internal/schedule.ts", - "lib/config/presets/internal/workarounds.ts", "lib/config/presets/local/common.ts", "lib/config/presets/local/index.ts", "lib/config/presets/npm/index.ts", - "lib/config/presets/types.ts", "lib/config/presets/util.ts", - "lib/config/secrets.ts", - "lib/config/types.ts", "lib/config/utils.ts", "lib/config/validation-helpers/managers.ts", - "lib/config/validation-helpers/types.ts", "lib/config/validation.ts", "lib/datasource/adoptium-java/index.ts", "lib/datasource/api.ts", @@ -344,38 +306,20 @@ "lib/platform/azure/azure-helper.ts", "lib/platform/azure/index.ts", "lib/platform/azure/util.ts", - "lib/platform/bitbucket-server/index.ts", - "lib/platform/bitbucket-server/utils.ts", - "lib/platform/bitbucket/comments.ts", "lib/platform/bitbucket/index.ts", - "lib/platform/bitbucket/utils.ts", + "lib/platform/bitbucket-server/index.ts", "lib/platform/commit.ts", - "lib/platform/gitea/gitea-helper.ts", "lib/platform/gitea/index.ts", - "lib/platform/gitea/utils.ts", "lib/platform/github/index.ts", - "lib/platform/github/massage-markdown-links.ts", - "lib/platform/github/user.ts", - "lib/platform/gitlab/http.ts", "lib/platform/gitlab/index.ts", - "lib/platform/gitlab/merge-request.ts", "lib/platform/index.ts", "lib/renovate.ts", "lib/util/exec/buildpack.ts", "lib/util/exec/docker/index.ts", "lib/util/exec/index.ts", - "lib/util/git/auth.ts", - "lib/util/git/author.ts", - "lib/util/git/config.ts", - "lib/util/git/conflicts-cache.ts", - "lib/util/git/error.ts", "lib/util/git/index.ts", "lib/util/git/private-key.ts", - "lib/util/git/types.ts", "lib/util/git/url.ts", - "lib/util/host-rules.ts", - "lib/util/ignore.ts", - "lib/util/merge-confidence/index.ts", "lib/util/package-rules.ts", "lib/workers/branch/artifacts.ts", "lib/workers/branch/auto-replace.ts", @@ -390,7 +334,6 @@ "lib/workers/branch/schedule.ts", "lib/workers/branch/status-checks.ts", "lib/workers/global/autodiscover.ts", - "lib/workers/global/config/parse/__fixtures__/argv.ts", "lib/workers/global/config/parse/cli.ts", "lib/workers/global/config/parse/env.ts", "lib/workers/global/config/parse/file.ts", @@ -398,16 +341,11 @@ "lib/workers/global/config/parse/index.ts", "lib/workers/global/index.ts", "lib/workers/global/initialize.ts", - "lib/workers/global/limits.ts", "lib/workers/pr/automerge.ts", "lib/workers/pr/body/changelogs.ts", "lib/workers/pr/body/config-description.ts", "lib/workers/pr/body/controls.ts", - "lib/workers/pr/body/footer.ts", - "lib/workers/pr/body/header.ts", "lib/workers/pr/body/index.ts", - "lib/workers/pr/body/notes.ts", - "lib/workers/pr/body/updates-table.ts", "lib/workers/pr/changelog/github/index.ts", "lib/workers/pr/changelog/gitlab/index.ts", "lib/workers/pr/changelog/index.ts", @@ -419,7 +357,6 @@ "lib/workers/pr/index.ts", "lib/workers/repository/cache.ts", "lib/workers/repository/changelog/index.ts", - "lib/workers/repository/configured.ts", "lib/workers/repository/dependency-dashboard.ts", "lib/workers/repository/error-config.ts", "lib/workers/repository/error.ts", @@ -463,16 +400,10 @@ "lib/workers/repository/process/lookup/update-type.ts", "lib/workers/repository/process/sort.ts", "lib/workers/repository/process/write.ts", - "lib/workers/repository/result.ts", - "lib/workers/repository/stats.ts", "lib/workers/repository/updates/branch-name.ts", "lib/workers/repository/updates/branchify.ts", "lib/workers/repository/updates/flatten.ts", "lib/workers/repository/updates/generate.ts", - "lib/workers/types.ts", - "test/fixtures.ts", - "test/setup.ts", - "test/to-migrate.ts", "test/util.ts", "tools/docs/config.ts", "tools/docs/datasources.ts", -- GitLab