From 4b16903ff1868a75a9598dad685fde7a60e2b2bd Mon Sep 17 00:00:00 2001 From: RahulGautamSingh <rahultesnik@gmail.com> Date: Tue, 19 Oct 2021 18:38:34 +0545 Subject: [PATCH] fix: modified regex to use RE2 (#12025) Co-authored-by: Rhys Arkins <rhys@arkins.net> --- lib/config/decrypt.ts | 11 ++++---- lib/config/migration.ts | 32 ++++++++++++++++------ lib/config/presets/index.ts | 10 +++---- lib/config/validation.ts | 10 +++---- lib/datasource/artifactory/index.ts | 3 +- lib/datasource/crate/index.ts | 3 +- lib/datasource/docker/common.ts | 9 +++--- lib/datasource/docker/index.ts | 3 +- lib/datasource/git-refs/index.ts | 9 ++++-- lib/datasource/git-tags/index.ts | 5 +++- lib/datasource/github-releases/digest.ts | 9 +++--- lib/datasource/gitlab-tags/index.ts | 3 +- lib/datasource/go/goproxy.ts | 18 ++++++------ lib/datasource/go/index.ts | 15 ++++++---- lib/datasource/helm/common.ts | 12 +++++--- lib/datasource/maven/index.ts | 2 +- lib/datasource/maven/util.ts | 15 +++++----- lib/datasource/metadata.ts | 9 +++--- lib/datasource/npm/npmrc.ts | 12 ++++---- lib/datasource/nuget/common.ts | 4 ++- lib/datasource/nuget/index.ts | 3 +- lib/datasource/nuget/v2.ts | 3 +- lib/datasource/nuget/v3.ts | 3 +- lib/datasource/packagist/index.ts | 4 +-- lib/datasource/pod/index.ts | 13 +++++---- lib/datasource/pypi/index.ts | 17 ++++++------ lib/datasource/sbt-package/index.ts | 13 +++++---- lib/datasource/sbt-plugin/index.ts | 7 +++-- lib/datasource/sbt-plugin/util.ts | 4 ++- lib/datasource/terraform-module/index.ts | 3 +- lib/datasource/terraform-provider/index.ts | 3 +- lib/logger/cmd-serializer.ts | 2 +- lib/logger/err-serializer.ts | 2 +- lib/logger/pretty-stdout.ts | 2 +- lib/logger/utils.ts | 2 +- lib/util/regex.ts | 7 +++-- 36 files changed, 168 insertions(+), 114 deletions(-) diff --git a/lib/config/decrypt.ts b/lib/config/decrypt.ts index 306945086e..86a51a435b 100644 --- a/lib/config/decrypt.ts +++ b/lib/config/decrypt.ts @@ -3,6 +3,7 @@ import is from '@sindresorhus/is'; import * as openpgp from 'openpgp'; import { logger } from '../logger'; import { maskToken } from '../util/mask'; +import { regEx } from '../util/regex'; import { add } from '../util/sanitize'; import { getGlobalConfig } from './global'; import type { RenovateConfig } from './types'; @@ -18,7 +19,7 @@ export async function tryDecryptPgp( try { const pk = await openpgp.readPrivateKey({ // prettier-ignore - armoredKey: privateKey.replace(/\n[ \t]+/g, '\n'), // little massage to help a common problem + armoredKey: privateKey.replace(regEx(/\n[ \t]+/g), '\n'), // little massage to help a common problem }); const startBlock = '-----BEGIN PGP MESSAGE-----\n\n'; const endBlock = '\n-----END PGP MESSAGE-----'; @@ -95,7 +96,7 @@ export async function tryDecrypt( const { o: org, r: repo, v: value } = decryptedObj; if (is.nonEmptyString(value)) { if (is.nonEmptyString(org)) { - const orgName = org.replace(/\/$/, ''); // Strip trailing slash + const orgName = org.replace(regEx(/\/$/), ''); // Strip trailing slash if (is.nonEmptyString(repo)) { const scopedRepository = `${orgName}/${repo}`; if (scopedRepository === repository) { @@ -171,7 +172,7 @@ export async function decryptConfig( } logger.debug(`Decrypted ${eKey}`); if (eKey === 'npmToken') { - const token = decryptedStr.replace(/\n$/, ''); + const token = decryptedStr.replace(regEx(/\n$/), ''); // TODO #12071 add(token); logger.debug( { decryptedToken: maskToken(token) }, @@ -182,13 +183,13 @@ export async function decryptConfig( if (decryptedConfig.npmrc.includes('${NPM_TOKEN}')) { logger.debug('Replacing ${NPM_TOKEN} with decrypted token'); decryptedConfig.npmrc = decryptedConfig.npmrc.replace( - /\${NPM_TOKEN}/g, + regEx(/\${NPM_TOKEN}/g), token ); } else { logger.debug('Appending _authToken= to end of existing npmrc'); decryptedConfig.npmrc = decryptedConfig.npmrc.replace( - /\n?$/, + regEx(/\n?$/), // TODO #12071 `\n_authToken=${token}\n` ); } diff --git a/lib/config/migration.ts b/lib/config/migration.ts index 81674078f0..e6a3903afe 100644 --- a/lib/config/migration.ts +++ b/lib/config/migration.ts @@ -3,6 +3,7 @@ import is from '@sindresorhus/is'; import { dequal } from 'dequal'; import { logger } from '../logger'; import { clone } from '../util/clone'; +import { regEx } from '../util/regex'; import { getGlobalConfig } from './global'; import { applyMigrations } from './migrations'; import { getOptions } from './options'; @@ -176,9 +177,15 @@ export function migrateConfig( migratedConfig.rangeStrategy = 'replace'; } } else if (is.string(val) && val.includes('{{baseDir}}')) { - migratedConfig[key] = val.replace(/{{baseDir}}/g, '{{packageFileDir}}'); + migratedConfig[key] = val.replace( + regEx(/{{baseDir}}/g), // TODO #12071 + '{{packageFileDir}}' + ); } else if (is.string(val) && val.includes('{{depNameShort}}')) { - migratedConfig[key] = val.replace(/{{depNameShort}}/g, '{{depName}}'); + migratedConfig[key] = val.replace( + regEx(/{{depNameShort}}/g), // TODO #12071 + '{{depName}}' + ); } else if (key === 'gitFs') { delete migratedConfig.gitFs; } else if (key === 'rebaseStalePrs') { @@ -387,21 +394,25 @@ export function migrateConfig( ) { const parsedSchedule = later.parse.text( // We need to massage short hours first before we can parse it - schedules[i].replace(/( \d?\d)((a|p)m)/g, '$1:00$2') + schedules[i].replace(regEx(/( \d?\d)((a|p)m)/g), '$1:00$2') // TODO #12071 ).schedules[0]; // Only migrate if the after time is greater than before, e.g. "after 10pm and before 5am" if (parsedSchedule?.t_a?.[0] > parsedSchedule?.t_b?.[0]) { const toSplit = schedules[i]; schedules[i] = toSplit .replace( - /^(.*?)(after|before) (.*?) and (after|before) (.*?)( |$)(.*)/, + regEx( + /^(.*?)(after|before) (.*?) and (after|before) (.*?)( |$)(.*)/ + ), // TODO #12071 '$1$2 $3 $7' ) .trim(); schedules.push( toSplit .replace( - /^(.*?)(after|before) (.*?) and (after|before) (.*?)( |$)(.*)/, + regEx( + /^(.*?)(after|before) (.*?) and (after|before) (.*?)( |$)(.*)/ + ), // TODO #12071 '$1$4 $5 $7' ) .trim() @@ -426,9 +437,14 @@ export function migrateConfig( schedules[i] = schedules[i].replace(' every day', ''); } if ( - /every (mon|tues|wednes|thurs|fri|satur|sun)day$/.test(schedules[i]) + regEx(/every (mon|tues|wednes|thurs|fri|satur|sun)day$/).test( + schedules[i] + ) // TODO #12071 ) { - schedules[i] = schedules[i].replace(/every ([a-z]*day)$/, 'on $1'); + schedules[i] = schedules[i].replace( + regEx(/every ([a-z]*day)$/), // TODO #12071 + 'on $1' + ); } if (schedules[i].endsWith('days')) { schedules[i] = schedules[i].replace('days', 'day'); @@ -545,7 +561,7 @@ export function migrateConfig( if (is.string(migratedConfig[key])) { for (const [from, to] of Object.entries(migratedTemplates)) { migratedConfig[key] = (migratedConfig[key] as string).replace( - new RegExp(from, 'g'), + regEx(from, 'g'), // TODO #12071 to ); } diff --git a/lib/config/presets/index.ts b/lib/config/presets/index.ts index d3c6bde5a3..f3060acde7 100644 --- a/lib/config/presets/index.ts +++ b/lib/config/presets/index.ts @@ -42,7 +42,7 @@ export function replaceArgs( if (is.string(obj)) { let returnStr = obj; for (const [arg, argVal] of Object.entries(argMapping)) { - const re = regEx(`{{${arg}}}`, 'g'); + const re = regEx(`{{${arg}}}`, 'g'); // TODO #12071 returnStr = returnStr.replace(re, argVal); } return returnStr; @@ -90,7 +90,7 @@ export function parsePreset(input: string): ParsedPreset { ) { presetSource = 'local'; } - str = str.replace(/^npm>/, ''); + str = str.replace(regEx(/^npm>/), ''); presetSource = presetSource || 'npm'; if (str.includes('(')) { params = str @@ -126,7 +126,7 @@ export function parsePreset(input: string): ParsedPreset { presetName = str.slice(1); } else if (str.startsWith('@')) { // scoped namespace - [, packageName] = /(@.*?)(:|$)/.exec(str); + [, packageName] = regEx(/(@.*?)(:|$)/).exec(str); str = str.slice(packageName.length); if (!packageName.includes('/')) { packageName += '/renovate-config'; @@ -138,7 +138,7 @@ export function parsePreset(input: string): ParsedPreset { } } else if (str.includes('//')) { // non-scoped namespace with a subdirectory preset - const re = /^([\w\-./]+?)\/\/(?:([\w\-./]+)\/)?([\w\-.]+)$/; + const re = regEx(/^([\w\-./]+?)\/\/(?:([\w\-./]+)\/)?([\w\-.]+)$/); // Validation if (str.includes(':')) { @@ -150,7 +150,7 @@ export function parsePreset(input: string): ParsedPreset { [, packageName, presetPath, presetName] = re.exec(str); } else { // non-scoped namespace - [, packageName] = /(.*?)(:|$)/.exec(str); + [, packageName] = regEx(/(.*?)(:|$)/).exec(str); presetName = str.slice(packageName.length + 1); if (presetSource === 'npm' && !packageName.startsWith('renovate-config-')) { packageName = `renovate-config-${packageName}`; diff --git a/lib/config/validation.ts b/lib/config/validation.ts index 905b22a165..efe4447047 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -40,7 +40,7 @@ const ignoredNodes = [ function isManagerPath(parentPath: string): boolean { return ( - /^regexManagers\[[0-9]+]$/.test(parentPath) || + regEx(/^regexManagers\[[0-9]+]$/).test(parentPath) || managerList.includes(parentPath) ); } @@ -85,8 +85,8 @@ function getDeprecationMessage(option: string): string { export function getParentName(parentPath: string): string { return parentPath ? parentPath - .replace(/\.?encrypted$/, '') - .replace(/\[\d+\]$/, '') + .replace(regEx(/\.?encrypted$/), '') + .replace(regEx(/\[\d+\]$/), '') .split('.') .pop() : '.'; @@ -253,7 +253,7 @@ export async function validateConfig( } } if (key === 'extends') { - const tzRe = /^:timezone\((.+)\)$/; + const tzRe = regEx(/^:timezone\((.+)\)$/); // TODO #12071 for (const subval of val) { if (is.string(subval)) { if ( @@ -480,7 +480,7 @@ export async function validateConfig( } if ( (selectors.includes(key) || key === 'matchCurrentVersion') && - !/p.*Rules\[\d+\]$/.test(parentPath) && // Inside a packageRule + !regEx(/p.*Rules\[\d+\]$/).test(parentPath) && // Inside a packageRule // TODO #12071 (parentPath || !isPreset) // top level in a preset ) { errors.push({ diff --git a/lib/datasource/artifactory/index.ts b/lib/datasource/artifactory/index.ts index 2c462be9c9..3b8054e905 100644 --- a/lib/datasource/artifactory/index.ts +++ b/lib/datasource/artifactory/index.ts @@ -2,6 +2,7 @@ import { logger } from '../../logger'; import { cache } from '../../util/cache/package/decorator'; import { parse } from '../../util/html'; import { HttpError } from '../../util/http/types'; +import { regEx } from '../../util/regex'; import { joinUrlParts } from '../../util/url'; import { Datasource } from '../datasource'; import type { GetReleasesConfig, Release, ReleaseResult } from '../types'; @@ -108,6 +109,6 @@ export class ArtifactoryDatasource extends Datasource { } private static parseReleaseTimestamp(rawText: string): string { - return rawText.trim().replace(/ ?-$/, ''); + return rawText.trim().replace(regEx(/ ?-$/), ''); // TODO #12071 } } diff --git a/lib/datasource/crate/index.ts b/lib/datasource/crate/index.ts index e66807e199..9eed05c056 100644 --- a/lib/datasource/crate/index.ts +++ b/lib/datasource/crate/index.ts @@ -112,7 +112,6 @@ export class CrateDatasource extends Datasource { this.handleGenericErrors(err); } } - throw new Error(`unsupported crate registry flavor: ${info.flavor}`); } @@ -144,7 +143,7 @@ export class CrateDatasource extends Datasource { * clone the repository. */ private static cacheDirFromUrl(url: URL): string { - const proto = url.protocol.replace(/:$/, ''); + const proto = url.protocol.replace(/:$/, ''); // TODO #12070 const host = url.hostname; const hash = hasha(url.pathname, { algorithm: 'sha256', diff --git a/lib/datasource/docker/common.ts b/lib/datasource/docker/common.ts index a5901a5fc8..38c9ef4361 100644 --- a/lib/datasource/docker/common.ts +++ b/lib/datasource/docker/common.ts @@ -10,6 +10,7 @@ import * as packageCache from '../../util/cache/package'; import * as hostRules from '../../util/host-rules'; import { Http, HttpOptions, HttpResponse } from '../../util/http'; import type { OutgoingHttpHeaders } from '../../util/http/types'; +import { regEx } from '../../util/regex'; import { ensureTrailingSlash, parseUrl, @@ -20,7 +21,7 @@ import { MediaType, RegistryRepository } from './types'; export const id = 'docker'; export const http = new Http(id); -export const ecrRegex = /\d+\.dkr\.ecr\.([-a-z0-9]+)\.amazonaws\.com/; +export const ecrRegex = regEx(/\d+\.dkr\.ecr\.([-a-z0-9]+)\.amazonaws\.com/); const DOCKER_HUB = 'https://index.docker.io'; export const defaultRegistryUrls = [DOCKER_HUB]; @@ -210,11 +211,11 @@ export function getRegistryRepository( ): RegistryRepository { if (registryUrl !== DOCKER_HUB) { const registryEndingWithSlash = ensureTrailingSlash( - registryUrl.replace(/^https?:\/\//, '') + registryUrl.replace(regEx(/^https?:\/\//), '') ); if (lookupName.startsWith(registryEndingWithSlash)) { let registryHost = trimTrailingSlash(registryUrl); - if (!/^https?:\/\//.test(registryHost)) { + if (!regEx(/^https?:\/\//).test(registryHost)) { registryHost = `https://${registryHost}`; } let dockerRepository = lookupName.replace(registryEndingWithSlash, ''); @@ -244,7 +245,7 @@ export function getRegistryRepository( if (registryHost === 'docker.io') { registryHost = 'index.docker.io'; } - if (!/^https?:\/\//.exec(registryHost)) { + if (!regEx(/^https?:\/\//).exec(registryHost)) { registryHost = `https://${registryHost}`; } const opts = hostRules.find({ hostType: id, url: registryHost }); diff --git a/lib/datasource/docker/index.ts b/lib/datasource/docker/index.ts index 2a22c851d2..a4756390b6 100644 --- a/lib/datasource/docker/index.ts +++ b/lib/datasource/docker/index.ts @@ -4,6 +4,7 @@ import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; import * as packageCache from '../../util/cache/package'; import { hasKey } from '../../util/object'; +import { regEx } from '../../util/regex'; import { ensurePathPrefix } from '../../util/url'; import { api as dockerVersioning, @@ -103,7 +104,7 @@ async function getTags( return cachedResult; } - const isQuay = /^https:\/\/quay\.io(?::[1-9][0-9]{0,4})?$/i.test( + const isQuay = regEx(/^https:\/\/quay\.io(?::[1-9][0-9]{0,4})?$/i).test( registryHost ); let tags: string[] | null; diff --git a/lib/datasource/git-refs/index.ts b/lib/datasource/git-refs/index.ts index 7d12032c88..653fc08940 100644 --- a/lib/datasource/git-refs/index.ts +++ b/lib/datasource/git-refs/index.ts @@ -2,6 +2,7 @@ import simpleGit from 'simple-git'; import * as packageCache from '../../util/cache/package'; import { simpleGitConfig } from '../../util/git/config'; import { getRemoteUrlWithToken } from '../../util/git/url'; +import { regEx } from '../../util/regex'; import * as semver from '../../versioning/semver'; import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; import type { RawRefs } from './types'; @@ -38,8 +39,8 @@ export async function getRawRefs( return null; } - const refMatch = /(?<hash>.*?)\s+refs\/(?<type>.*?)\/(?<value>.*)/; - const headMatch = /(?<hash>.*?)\s+HEAD/; + const refMatch = regEx(/(?<hash>.*?)\s+refs\/(?<type>.*?)\/(?<value>.*)/); + const headMatch = regEx(/(?<hash>.*?)\s+HEAD/); const refs = lsRemote .trim() @@ -83,7 +84,9 @@ export async function getReleases({ const uniqueRefs = [...new Set(refs)]; - const sourceUrl = lookupName.replace(/\.git$/, '').replace(/\/$/, ''); + const sourceUrl = lookupName + .replace(regEx(/\.git$/), '') + .replace(regEx(/\/$/), ''); const result: ReleaseResult = { sourceUrl, diff --git a/lib/datasource/git-tags/index.ts b/lib/datasource/git-tags/index.ts index 36ed8dee8f..a742ff7b8e 100644 --- a/lib/datasource/git-tags/index.ts +++ b/lib/datasource/git-tags/index.ts @@ -1,3 +1,4 @@ +import { regEx } from '../../util/regex'; import * as semver from '../../versioning/semver'; import * as gitRefs from '../git-refs'; import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; @@ -22,7 +23,9 @@ export async function getReleases({ newDigest: ref.hash, })); - const sourceUrl = lookupName.replace(/\.git$/, '').replace(/\/$/, ''); + const sourceUrl = lookupName + .replace(regEx(/\.git$/), '') + .replace(regEx(/\/$/), ''); const result: ReleaseResult = { sourceUrl, diff --git a/lib/datasource/github-releases/digest.ts b/lib/datasource/github-releases/digest.ts index 9afdb7e2cd..21b6699989 100644 --- a/lib/datasource/github-releases/digest.ts +++ b/lib/datasource/github-releases/digest.ts @@ -1,5 +1,6 @@ import hasha from 'hasha'; import * as packageCache from '../../util/cache/package'; +import { regEx } from '../../util/regex'; import { cacheNamespace, http } from './common'; import type { DigestAsset, GithubRelease, GithubReleaseAsset } from './types'; @@ -13,7 +14,7 @@ async function findDigestFile( for (const asset of smallAssets) { const res = await http.get(asset.browser_download_url); for (const line of res.body.split('\n')) { - const [lineDigest, lineFn] = line.split(/\s+/, 2); + const [lineDigest, lineFn] = line.split(regEx(/\s+/), 2); // TODO #12071 if (lineDigest === digest) { return { assetName: asset.name, @@ -114,8 +115,8 @@ export async function mapDigestAssetToRelease( digestAsset: DigestAsset, release: GithubRelease ): Promise<string | null> { - const current = digestAsset.currentVersion.replace(/^v/, ''); - const next = release.tag_name.replace(/^v/, ''); + const current = digestAsset.currentVersion.replace(regEx(/^v/), ''); + const next = release.tag_name.replace(regEx(/^v/), ''); const releaseChecksumAssetName = digestAsset.assetName.replace(current, next); const releaseAsset = release.assets.find( (a: GithubReleaseAsset) => a.name === releaseChecksumAssetName @@ -127,7 +128,7 @@ export async function mapDigestAssetToRelease( const releaseFilename = digestAsset.digestedFileName.replace(current, next); const res = await http.get(releaseAsset.browser_download_url); for (const line of res.body.split('\n')) { - const [lineDigest, lineFn] = line.split(/\s+/, 2); + const [lineDigest, lineFn] = line.split(regEx(/\s+/), 2); if (lineFn === releaseFilename) { return lineDigest; } diff --git a/lib/datasource/gitlab-tags/index.ts b/lib/datasource/gitlab-tags/index.ts index fde3a5f869..2098701568 100644 --- a/lib/datasource/gitlab-tags/index.ts +++ b/lib/datasource/gitlab-tags/index.ts @@ -1,5 +1,6 @@ import * as packageCache from '../../util/cache/package'; import { GitlabHttp } from '../../util/http/gitlab'; +import { regEx } from '../../util/regex'; import { joinUrlParts } from '../../util/url'; import type { GetReleasesConfig, ReleaseResult } from '../types'; import type { GitlabTag } from './types'; @@ -22,7 +23,7 @@ export async function getReleases({ registryUrl, lookupName: repo, }: GetReleasesConfig): Promise<ReleaseResult | null> { - const depHost = registryUrl.replace(/\/api\/v4$/, ''); + const depHost = registryUrl.replace(regEx(/\/api\/v4$/), ''); const cachedResult = await packageCache.get<ReleaseResult>( cacheNamespace, diff --git a/lib/datasource/go/goproxy.ts b/lib/datasource/go/goproxy.ts index 84334b919d..b7ef450450 100644 --- a/lib/datasource/go/goproxy.ts +++ b/lib/datasource/go/goproxy.ts @@ -34,9 +34,9 @@ export function parseGoproxy( } let result: GoproxyItem[] = input - .split(/([^,|]*(?:,|\|))/) + .split(/([^,|]*(?:,|\|))/) // TODO: #12070 .filter(Boolean) - .map((s) => s.split(/(?=,|\|)/)) + .map((s) => s.split(/(?=,|\|)/)) // TODO: #12070 .map(([url, separator]) => ({ url, fallback: @@ -62,7 +62,7 @@ export function parseGoproxy( const lexer = moo.states({ main: { separator: { - match: /\s*?,\s*?/, + match: /\s*?,\s*?/, // TODO #12070 value: (_: string) => '|', }, asterisk: { @@ -78,16 +78,16 @@ const lexer = moo.states({ push: 'characterRange', value: (_: string) => '[', }, - char: /[^*?\\[\n]/, + char: /[^*?\\[\n]/, // TODO #12070 escapedChar: { - match: /\\./, + match: /\\./, // TODO #12070 value: (s: string) => s.slice(1), }, }, characterRange: { - char: /[^\\\]\n]/, + char: /[^\\\]\n]/, // TODO #12070 escapedChar: { - match: /\\./, + match: /\\./, // TODO #12070 value: (s: string) => s.slice(1), }, characterRangeEnd: { @@ -121,7 +121,7 @@ export function parseNoproxy( * @see https://golang.org/ref/mod#goproxy-protocol */ export function encodeCase(input: string): string { - return input.replace(/([A-Z])/g, (x) => `!${x.toLowerCase()}`); + return input.replace(regEx(/([A-Z])/g), (x) => `!${x.toLowerCase()}`); } export async function listVersions( @@ -131,7 +131,7 @@ export async function listVersions( const url = `${baseUrl}/${encodeCase(lookupName)}/@v/list`; const { body } = await http.get(url); return body - .split(/\s+/) + .split(regEx(/\s+/)) .filter(Boolean) .filter((x) => x.indexOf('+') === -1); } diff --git a/lib/datasource/go/index.ts b/lib/datasource/go/index.ts index 42581e7c6d..a8be688dbd 100644 --- a/lib/datasource/go/index.ts +++ b/lib/datasource/go/index.ts @@ -16,9 +16,12 @@ export { id } from './common'; export const customRegistrySupport = false; -const gitlabHttpsRegExp = - /^(?<httpsRegExpUrl>https:\/\/[^/]*gitlab\.[^/]*)\/(?<httpsRegExpName>.+?)[/]?$/; -const gitlabRegExp = /^(?<regExpUrl>gitlab\.[^/]*)\/(?<regExpPath>.+?)[/]?$/; +const gitlabHttpsRegExp = regEx( + /^(?<httpsRegExpUrl>https:\/\/[^/]*gitlab\.[^/]*)\/(?<httpsRegExpName>.+?)[/]?$/ +); +const gitlabRegExp = regEx( + /^(?<regExpUrl>gitlab\.[^/]*)\/(?<regExpPath>.+?)[/]?$/ +); const bitbucket = new BitBucketTagsDatasource(); async function getDatasource(goModule: string): Promise<DataSource | null> { @@ -67,7 +70,7 @@ async function getDatasource(goModule: string): Promise<DataSource | null> { datasource: github.id, lookupName: goSourceUrl .replace('https://github.com/', '') - .replace(/\/$/, ''), + .replace(regEx(/\/$/), ''), }; } const gitlabUrl = @@ -129,7 +132,7 @@ async function getDatasource(goModule: string): Promise<DataSource | null> { // split the go module from the URL: host/go/module -> go/module const lookupName = trimTrailingSlash(parsedUrl.pathname) - .replace(/\.git$/, '') + .replace(regEx(/\.git$/), '') .split('/') .slice(-2) .join('/'); @@ -210,7 +213,7 @@ export async function getReleases( * and that tag should be used instead of just va.b.c, although for compatibility * the old behaviour stays the same. */ - const nameParts = lookupName.replace(/\/v\d+$/, '').split('/'); + const nameParts = lookupName.replace(regEx(/\/v\d+$/), '').split('/'); logger.trace({ nameParts, releases: res.releases }, 'go.getReleases'); // If it has more than 3 parts it's a submodule or subgroup (gitlab only) diff --git a/lib/datasource/helm/common.ts b/lib/datasource/helm/common.ts index d6327bffb7..e6aef34e93 100644 --- a/lib/datasource/helm/common.ts +++ b/lib/datasource/helm/common.ts @@ -1,9 +1,13 @@ +import { regEx } from '../../util/regex'; import type { HelmRelease } from './types'; -const chartRepo = /charts?|helm|helm-charts/i; -const githubUrl = - /^(?<url>https:\/\/github\.com\/[^/]+\/(?<repo>[^/]+))(?:\/|$)/; -const githubRelease = /^(https:\/\/github\.com\/[^/]+\/[^/]+)\/releases\//; +const chartRepo = regEx(/charts?|helm|helm-charts/i); +const githubUrl = regEx( + /^(?<url>https:\/\/github\.com\/[^/]+\/(?<repo>[^/]+))(?:\/|$)/ +); +const githubRelease = regEx( + /^(https:\/\/github\.com\/[^/]+\/[^/]+)\/releases\// +); export function findSourceUrl(release: HelmRelease): string { // it's a github release :) diff --git a/lib/datasource/maven/index.ts b/lib/datasource/maven/index.ts index e5399bdd14..034b8d55a0 100644 --- a/lib/datasource/maven/index.ts +++ b/lib/datasource/maven/index.ts @@ -235,7 +235,7 @@ export async function getReleases({ const dependency = getDependencyParts(lookupName); let releases: Release[] = null; const repoForVersions = {}; - const repoUrl = registryUrl.replace(/\/?$/, '/'); + const repoUrl = registryUrl.replace(/\/?$/, '/'); // TODO #12070 logger.debug(`Looking up ${dependency.display} in repository ${repoUrl}`); const metadataVersions = await getVersionsFromMetadata(dependency, repoUrl); if (metadataVersions) { diff --git a/lib/datasource/maven/util.ts b/lib/datasource/maven/util.ts index 18316d73df..c2843b6e9d 100644 --- a/lib/datasource/maven/util.ts +++ b/lib/datasource/maven/util.ts @@ -4,6 +4,7 @@ import { HOST_DISABLED } from '../../constants/error-messages'; import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; import { Http, HttpResponse } from '../../util/http'; +import { regEx } from '../../util/regex'; import type { ReleaseResult } from '../types'; import { MAVEN_REPO, id } from './common'; @@ -120,7 +121,7 @@ export async function isHttpResourceExists( } function containsPlaceholder(str: string): boolean { - return /\${.*?}/g.test(str); + return regEx(/\${.*?}/g).test(str); } export function getMavenUrl( @@ -165,7 +166,7 @@ export async function downloadMavenXml( export function getDependencyParts(lookupName: string): MavenDependency { const [group, name] = lookupName.split(':'); - const dependencyUrl = `${group.replace(/\./g, '/')}/${name}`; + const dependencyUrl = `${group.replace(regEx(/\./g), '/')}/${name}`; return { display: lookupName, group, @@ -198,11 +199,11 @@ export async function getDependencyInfo( const sourceUrl = pomContent.valueWithPath('scm.url'); if (sourceUrl && !containsPlaceholder(sourceUrl)) { result.sourceUrl = sourceUrl - .replace(/^scm:/, '') - .replace(/^git:/, '') - .replace(/^git@github.com:/, 'https://github.com/') - .replace(/^git@github.com\//, 'https://github.com/') - .replace(/\.git$/, ''); + .replace(regEx(/^scm:/), '') + .replace(regEx(/^git:/), '') + .replace(regEx(/^git@github.com:/), 'https://github.com/') + .replace(regEx(/^git@github.com\//), 'https://github.com/') + .replace(regEx(/\.git$/), ''); if (result.sourceUrl.startsWith('//')) { // most likely the result of us stripping scm:, git: etc diff --git a/lib/datasource/metadata.ts b/lib/datasource/metadata.ts index ef41685d97..cd92345a50 100644 --- a/lib/datasource/metadata.ts +++ b/lib/datasource/metadata.ts @@ -3,6 +3,7 @@ import is from '@sindresorhus/is'; import parse from 'github-url-from-git'; import { DateTime } from 'luxon'; import * as hostRules from '../util/host-rules'; +import { regEx } from '../util/regex'; import { validateUrl } from '../util/url'; import type { ReleaseResult } from './types'; @@ -109,7 +110,7 @@ const manualSourceUrls = { function massageGithubUrl(url: string): string { return url .replace('http:', 'https:') - .replace(/^git:\/?\/?/, 'https://') + .replace(regEx(/^git:\/?\/?/), 'https://') .replace('www.github.com', 'github.com') .split('/') .slice(0, 5) @@ -119,9 +120,9 @@ function massageGithubUrl(url: string): string { function massageGitlabUrl(url: string): string { return url .replace('http:', 'https:') - .replace(/^git:\/?\/?/, 'https://') - .replace(/\/tree\/.*$/i, '') - .replace(/\/$/i, '') + .replace(regEx(/^git:\/?\/?/), 'https://') + .replace(regEx(/\/tree\/.*$/i), '') + .replace(regEx(/\/$/i), '') .replace('.git', ''); } diff --git a/lib/datasource/npm/npmrc.ts b/lib/datasource/npm/npmrc.ts index 3faffab849..7ca1d60581 100644 --- a/lib/datasource/npm/npmrc.ts +++ b/lib/datasource/npm/npmrc.ts @@ -7,6 +7,7 @@ import { getGlobalConfig } from '../../config/global'; import { logger } from '../../logger'; import type { OutgoingHttpHeaders } from '../../util/http/types'; import { maskToken } from '../../util/mask'; +import { regEx } from '../../util/regex'; import { add } from '../../util/sanitize'; import type { Npmrc, PackageResolution } from './types'; @@ -23,7 +24,7 @@ function envReplace(value: any, env = process.env): any { return value; } - const ENV_EXPR = /(\\*)\$\{([^}]+)\}/g; + const ENV_EXPR = regEx(/(\\*)\$\{([^}]+)\}/g); return value.replace(ENV_EXPR, (match, esc, envVarName) => { if (env[envVarName] === undefined) { @@ -34,7 +35,7 @@ function envReplace(value: any, env = process.env): any { }); } -const envRe = /(\\*)\$\{([^}]+)\}/; +const envRe = regEx(/(\\*)\$\{([^}]+)\}/); // TODO: better add to host rules (#9588) function sanitize(key: string, val: string): void { if (!val || envRe.test(val)) { @@ -59,7 +60,7 @@ export function setNpmrc(input?: string): void { const existingNpmrc = npmrc; npmrcRaw = input; logger.debug('Setting npmrc'); - npmrc = ini.parse(input.replace(/\\n/g, '\n')); + npmrc = ini.parse(input.replace(regEx(/\\n/g), '\n')); const { exposeAllEnv } = getGlobalConfig(); for (const [key, val] of Object.entries(npmrc)) { if (!exposeAllEnv) { @@ -103,7 +104,7 @@ export function resolvePackage(packageName: string): PackageResolution { } const packageUrl = url.resolve( registryUrl, - encodeURIComponent(packageName).replace(/^%40/, '@') + encodeURIComponent(packageName).replace(regEx(/^%40/), '@') ); const headers: OutgoingHttpHeaders = {}; let authInfo = registryAuthToken(registryUrl, { npmrc, recursive: true }); @@ -111,7 +112,8 @@ export function resolvePackage(packageName: string): PackageResolution { !authInfo && npmrc && npmrc._authToken && - registryUrl.replace(/\/?$/, '/') === npmrc.registry?.replace(/\/?$/, '/') + registryUrl.replace(regEx(/\/?$/), '/') === + npmrc.registry?.replace(/\/?$/, '/') // TODO #12070 ) { authInfo = { type: 'Bearer', token: npmrc._authToken }; } diff --git a/lib/datasource/nuget/common.ts b/lib/datasource/nuget/common.ts index eb1f0d6eb5..b961f477a8 100644 --- a/lib/datasource/nuget/common.ts +++ b/lib/datasource/nuget/common.ts @@ -1,6 +1,8 @@ +import { regEx } from '../../util/regex'; + export const id = 'nuget'; -const buildMetaRe = /\+.+$/g; +const buildMetaRe = regEx(/\+.+$/g); export function removeBuildMeta(version: string): string { return version?.replace(buildMetaRe, ''); diff --git a/lib/datasource/nuget/index.ts b/lib/datasource/nuget/index.ts index c2a9627076..a9d97e6ce2 100644 --- a/lib/datasource/nuget/index.ts +++ b/lib/datasource/nuget/index.ts @@ -1,5 +1,6 @@ import urlApi from 'url'; import { logger } from '../../logger'; +import { regEx } from '../../util/regex'; import * as nugetVersioning from '../../versioning/nuget'; import type { GetReleasesConfig, ReleaseResult } from '../types'; import * as v2 from './v2'; @@ -19,7 +20,7 @@ export function parseRegistryUrl(registryUrl: string): { try { const parsedUrl = urlApi.parse(registryUrl); let protocolVersion = 2; - const protocolVersionRegExp = /#protocolVersion=(2|3)/; + const protocolVersionRegExp = regEx(/#protocolVersion=(2|3)/); const protocolVersionMatch = protocolVersionRegExp.exec(parsedUrl.hash); if (protocolVersionMatch) { parsedUrl.hash = ''; diff --git a/lib/datasource/nuget/v2.ts b/lib/datasource/nuget/v2.ts index 4a4e03e97d..4e8cfb4d54 100644 --- a/lib/datasource/nuget/v2.ts +++ b/lib/datasource/nuget/v2.ts @@ -1,6 +1,7 @@ import { XmlDocument, XmlElement } from 'xmldoc'; import { logger } from '../../logger'; import { Http } from '../../util/http'; +import { regEx } from '../../util/regex'; import type { ReleaseResult } from '../types'; import { id, removeBuildMeta } from './common'; @@ -18,7 +19,7 @@ export async function getReleases( releases: [], }; let pkgUrlList = `${feedUrl.replace( - /\/+$/, + regEx(/\/+$/), '' )}/FindPackagesById()?id=%27${pkgName}%27&$select=Version,IsLatestVersion,ProjectUrl,Published`; do { diff --git a/lib/datasource/nuget/v3.ts b/lib/datasource/nuget/v3.ts index 8ebe08b48d..af461330bc 100644 --- a/lib/datasource/nuget/v3.ts +++ b/lib/datasource/nuget/v3.ts @@ -7,6 +7,7 @@ import { ExternalHostError } from '../../types/errors/external-host-error'; import * as packageCache from '../../util/cache/package'; import { Http } from '../../util/http'; import { HttpError } from '../../util/http/types'; +import { regEx } from '../../util/regex'; import { ensureTrailingSlash } from '../../util/url'; import type { Release, ReleaseResult } from '../types'; import { id, removeBuildMeta } from './common'; @@ -116,7 +117,7 @@ export async function getReleases( feedUrl: string, pkgName: string ): Promise<ReleaseResult | null> { - const baseUrl = feedUrl.replace(/\/*$/, ''); + const baseUrl = feedUrl.replace(regEx(/\/*$/), ''); const url = `${baseUrl}/${pkgName.toLowerCase()}/index.json`; const packageRegistration = await http.getJson<PackageRegistration>(url); const catalogPages = packageRegistration.body.items || []; diff --git a/lib/datasource/packagist/index.ts b/lib/datasource/packagist/index.ts index 4dba8b0347..12bda735ee 100644 --- a/lib/datasource/packagist/index.ts +++ b/lib/datasource/packagist/index.ts @@ -38,7 +38,7 @@ function getHostOpts(url: string): HttpOptions { } async function getRegistryMeta(regUrl: string): Promise<RegistryMeta | null> { - const url = URL.resolve(regUrl.replace(/\/?$/, '/'), 'packages.json'); + const url = URL.resolve(regUrl.replace(/\/?$/, '/'), 'packages.json'); // TODO #12070 const opts = getHostOpts(url); const res = (await http.getJson<PackageMeta>(url, opts)).body; const meta: RegistryMeta = { @@ -124,7 +124,7 @@ function extractDepReleases(versions: RegistryFile): ReleaseResult { dep.sourceUrl = release.source.url; } return { - version: version.replace(/^v/, ''), + version: version.replace(/^v/, ''), // TODO #12070 gitRef: version, releaseTimestamp: release.time, }; diff --git a/lib/datasource/pod/index.ts b/lib/datasource/pod/index.ts index 31b53e167f..a9756383cd 100644 --- a/lib/datasource/pod/index.ts +++ b/lib/datasource/pod/index.ts @@ -6,6 +6,7 @@ import * as packageCache from '../../util/cache/package'; import { Http } from '../../util/http'; import { GithubHttp } from '../../util/http/github'; import type { HttpError } from '../../util/http/types'; +import { regEx } from '../../util/regex'; import type { GetReleasesConfig, ReleaseResult } from '../types'; export const id = 'pod'; @@ -93,8 +94,9 @@ async function requestGithub<T = unknown>( return null; } -const githubRegex = - /^https:\/\/github\.com\/(?<account>[^/]+)\/(?<repo>[^/]+?)(\.git|\/.*)?$/; +const githubRegex = regEx( + /^https:\/\/github\.com\/(?<account>[^/]+)\/(?<repo>[^/]+?)(\.git|\/.*)?$/ +); async function getReleasesFromGithub( lookupName: string, @@ -134,7 +136,8 @@ async function getReleasesFromCDN( for (let idx = 0; idx < lines.length; idx += 1) { const line = lines[idx]; const [name, ...versions] = line.split('/'); - if (name === lookupName.replace(/\/.*$/, '')) { + if (name === lookupName.replace(regEx(/\/.*$/), '')) { + // TODO #12071 const releases = versions.map((version) => ({ version })); return { releases }; } @@ -158,7 +161,7 @@ export async function getReleases({ lookupName, registryUrl, }: GetReleasesConfig): Promise<ReleaseResult | null> { - const podName = lookupName.replace(/\/.*$/, ''); + const podName = lookupName.replace(regEx(/\/.*$/), ''); const cachedResult = await packageCache.get<ReleaseResult>( cacheNamespace, @@ -171,7 +174,7 @@ export async function getReleases({ return cachedResult; } - let baseUrl = registryUrl.replace(/\/+$/, ''); + let baseUrl = registryUrl.replace(regEx(/\/+$/), ''); // In order to not abuse github API limits, query CDN instead if (isDefaultRepo(baseUrl)) { diff --git a/lib/datasource/pypi/index.ts b/lib/datasource/pypi/index.ts index 0ca3756a52..1adf3aa937 100644 --- a/lib/datasource/pypi/index.ts +++ b/lib/datasource/pypi/index.ts @@ -2,13 +2,14 @@ import url from 'url'; import changelogFilenameRegex from 'changelog-filename-regex'; import { logger } from '../../logger'; import { parse } from '../../util/html'; +import { regEx } from '../../util/regex'; import { ensureTrailingSlash } from '../../util/url'; import * as pep440 from '../../versioning/pep440'; import { Datasource } from '../datasource'; import type { GetReleasesConfig, Release, ReleaseResult } from '../types'; import type { PypiJSON, PypiJSONRelease, Releases } from './types'; -const githubRepoPattern = /^https?:\/\/github\.com\/[^\\/]+\/[^\\/]+$/; +const githubRepoPattern = regEx(/^https?:\/\/github\.com\/[^\\/]+\/[^\\/]+$/); export class PypiDatasource extends Datasource { static readonly id = 'pypi'; @@ -65,7 +66,7 @@ export class PypiDatasource extends Datasource { } private static normalizeName(input: string): string { - return input.toLowerCase().replace(/(-|\.)/g, '_'); + return input.toLowerCase().replace(regEx(/(-|\.)/g), '_'); } private async getDependency( @@ -171,18 +172,18 @@ export class PypiDatasource extends Datasource { ): string | null { const srcPrefixes = [ `${packageName}-`, - `${packageName.replace(/-/g, '_')}-`, + `${packageName.replace(regEx(/-/g), '_')}-`, ]; for (const prefix of srcPrefixes) { const suffix = '.tar.gz'; if (text.startsWith(prefix) && text.endsWith(suffix)) { - return text.replace(prefix, '').replace(/\.tar\.gz$/, ''); + return text.replace(prefix, '').replace(regEx(/\.tar\.gz$/), ''); // TODO #12071 } } // pep-0427 wheel packages // {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl. - const wheelPrefix = packageName.replace(/[^\w\d.]+/g, '_') + '-'; + const wheelPrefix = packageName.replace(regEx(/[^\w\d.]+/g), '_') + '-'; const wheelSuffix = '.whl'; if ( text.startsWith(wheelPrefix) && @@ -198,14 +199,14 @@ export class PypiDatasource extends Datasource { private static cleanSimpleHtml(html: string): string { return ( html - .replace(/<\/?pre>/, '') + .replace(regEx(/<\/?pre>/), '') // Certain simple repositories like artifactory don't escape > and < .replace( - /data-requires-python="([^"]*?)>([^"]*?)"/g, + regEx(/data-requires-python="([^"]*?)>([^"]*?)"/g), 'data-requires-python="$1>$2"' ) .replace( - /data-requires-python="([^"]*?)<([^"]*?)"/g, + regEx(/data-requires-python="([^"]*?)<([^"]*?)"/g), 'data-requires-python="$1<$2"' ) ); diff --git a/lib/datasource/sbt-package/index.ts b/lib/datasource/sbt-package/index.ts index c1e5b154d7..dc92514efc 100644 --- a/lib/datasource/sbt-package/index.ts +++ b/lib/datasource/sbt-package/index.ts @@ -1,5 +1,6 @@ import { XmlDocument } from 'xmldoc'; import { logger } from '../../logger'; +import { regEx } from '../../util/regex'; import * as ivyVersioning from '../../versioning/ivy'; import { compare } from '../../versioning/maven/compare'; import { MAVEN_REPO } from '../maven/common'; @@ -13,7 +14,7 @@ export const defaultRegistryUrls = [MAVEN_REPO]; export const defaultVersioning = ivyVersioning.id; export const registryStrategy = 'hunt'; -const ensureTrailingSlash = (str: string): string => str.replace(/\/?$/, '/'); +const ensureTrailingSlash = (str: string): string => str.replace(/\/?$/, '/'); // TODO #12070 export async function getArtifactSubdirs( searchRoot: string, @@ -58,7 +59,7 @@ export async function getPackageReleases( if (artifactSubdirs) { const releases: string[] = []; const parseReleases = (content: string): string[] => - parseIndexDir(content, (x) => !/^\.+$/.test(x)); + parseIndexDir(content, (x) => !regEx(/^\.+$/).test(x)); for (const searchSubdir of artifactSubdirs) { const { body: content } = await downloadHttpProtocol( ensureTrailingSlash(`${searchRoot}/${searchSubdir}`), @@ -123,10 +124,10 @@ export async function getUrls( const sourceUrl = pomXml.valueWithPath('scm.url'); if (sourceUrl) { result.sourceUrl = sourceUrl - .replace(/^scm:/, '') - .replace(/^git:/, '') - .replace(/^git@github.com:/, 'https://github.com/') - .replace(/\.git$/, ''); + .replace(regEx(/^scm:/), '') // TODO #12071 + .replace(regEx(/^git:/), '') // TODO #12071 + .replace(regEx(/^git@github.com:/), 'https://github.com/') // TODO #12071 + .replace(regEx(/\.git$/), ''); // TODO #12071 } return result; diff --git a/lib/datasource/sbt-plugin/index.ts b/lib/datasource/sbt-plugin/index.ts index 12d6481b17..c069dd07d1 100644 --- a/lib/datasource/sbt-plugin/index.ts +++ b/lib/datasource/sbt-plugin/index.ts @@ -1,4 +1,5 @@ import { logger } from '../../logger'; +import { regEx } from '../../util/regex'; import * as ivyVersioning from '../../versioning/ivy'; import { compare } from '../../versioning/maven/compare'; import { downloadHttpProtocol } from '../maven/util'; @@ -17,7 +18,7 @@ export const defaultRegistryUrls = [SBT_PLUGINS_REPO]; export const defaultVersioning = ivyVersioning.id; export const registryStrategy = 'hunt'; -const ensureTrailingSlash = (str: string): string => str.replace(/\/?$/, '/'); +const ensureTrailingSlash = (str: string): string => str.replace(/\/?$/, '/'); // TODO #12071 async function resolvePluginReleases( rootUrl: string, @@ -26,7 +27,7 @@ async function resolvePluginReleases( ): Promise<string[]> { const searchRoot = `${rootUrl}/${artifact}`; const parse = (content: string): string[] => - parseIndexDir(content, (x) => !/^\.+$/.test(x)); + parseIndexDir(content, (x) => !regEx(/^\.+$/).test(x)); const { body: indexContent } = await downloadHttpProtocol( ensureTrailingSlash(searchRoot), 'sbt' @@ -35,7 +36,7 @@ async function resolvePluginReleases( const releases: string[] = []; const scalaVersionItems = parse(indexContent); const scalaVersions = scalaVersionItems.map((x) => - x.replace(/^scala_/, '') + x.replace(regEx(/^scala_/), '') ); const searchVersions = scalaVersions.includes(scalaVersion) ? [scalaVersion] diff --git a/lib/datasource/sbt-plugin/util.ts b/lib/datasource/sbt-plugin/util.ts index 195d5c243a..3bbb5a2525 100644 --- a/lib/datasource/sbt-plugin/util.ts +++ b/lib/datasource/sbt-plugin/util.ts @@ -1,9 +1,11 @@ +import { regEx } from '../../util/regex'; + export const SBT_PLUGINS_REPO = 'https://dl.bintray.com/sbt/sbt-plugin-releases'; export function parseIndexDir( content: string, - filterFn = (x: string): boolean => !/^\.+/.test(x) + filterFn = (x: string): boolean => !regEx(/^\.+/).test(x) ): string[] { const unfiltered = content.match(/(?<=href=['"])[^'"]*(?=\/['"])/g) || []; return unfiltered.filter(filterFn); diff --git a/lib/datasource/terraform-module/index.ts b/lib/datasource/terraform-module/index.ts index 3c2a9eca2b..84f287d57b 100644 --- a/lib/datasource/terraform-module/index.ts +++ b/lib/datasource/terraform-module/index.ts @@ -2,6 +2,7 @@ import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; import { cache } from '../../util/cache/package/decorator'; import type { HttpError } from '../../util/http/types'; +import { regEx } from '../../util/regex'; import * as hashicorpVersioning from '../../versioning/hashicorp'; import type { GetReleasesConfig, ReleaseResult } from '../types'; import { TerraformDatasource } from './base'; @@ -103,7 +104,7 @@ export class TerraformModuleDatasource extends TerraformDatasource { } else { registry = registryUrl; } - if (!/^https?:\/\//.test(registry)) { + if (!regEx(/^https?:\/\//).test(registry)) { registry = `https://${registry}`; } const repository = split.join('/'); diff --git a/lib/datasource/terraform-provider/index.ts b/lib/datasource/terraform-provider/index.ts index 1500d3b8af..268a98dd59 100644 --- a/lib/datasource/terraform-provider/index.ts +++ b/lib/datasource/terraform-provider/index.ts @@ -2,6 +2,7 @@ import pMap from 'p-map'; import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; import { cache } from '../../util/cache/package/decorator'; +import { regEx } from '../../util/regex'; import { parseUrl } from '../../util/url'; import * as hashicorpVersioning from '../../versioning/hashicorp'; import { TerraformDatasource } from '../terraform-module/base'; @@ -23,7 +24,7 @@ export class TerraformProviderDatasource extends TerraformDatasource { 'https://releases.hashicorp.com', ]; - static repositoryRegex = /^hashicorp\/(?<lookupName>\S+)$/; + static repositoryRegex = regEx(/^hashicorp\/(?<lookupName>\S+)$/); constructor() { super(TerraformProviderDatasource.id); diff --git a/lib/logger/cmd-serializer.ts b/lib/logger/cmd-serializer.ts index ba656b9d48..ea7741c52b 100644 --- a/lib/logger/cmd-serializer.ts +++ b/lib/logger/cmd-serializer.ts @@ -3,7 +3,7 @@ export default function cmdSerializer( cmd: string | string[] ): string | string[] { if (typeof cmd === 'string') { - return cmd.replace(/https:\/\/[^@]*@/g, 'https://**redacted**@'); + return cmd.replace(/https:\/\/[^@]*@/g, 'https://**redacted**@'); // TODO #12070 } return cmd; } diff --git a/lib/logger/err-serializer.ts b/lib/logger/err-serializer.ts index 82b8b2963e..23d81cc111 100644 --- a/lib/logger/err-serializer.ts +++ b/lib/logger/err-serializer.ts @@ -12,7 +12,7 @@ export default function errSerializer(err: Error): any { const val = response[field]; if (is.string(val)) { response[field] = val.replace( - /https:\/\/[^@]*?@/g, + /https:\/\/[^@]*?@/g, // TODO #12070 #12071 'https://**redacted**@' ); } diff --git a/lib/logger/pretty-stdout.ts b/lib/logger/pretty-stdout.ts index df7b6a0921..fc97db214c 100644 --- a/lib/logger/pretty-stdout.ts +++ b/lib/logger/pretty-stdout.ts @@ -37,7 +37,7 @@ const levels: Record<number, string> = { export function indent(str: string, leading = false): string { const prefix = leading ? ' ' : ''; - return prefix + str.split(/\r?\n/).join('\n '); + return prefix + str.split(/\r?\n/).join('\n '); // TODO #12070 } export function getMeta(rec: BunyanRecord): string { diff --git a/lib/logger/utils.ts b/lib/logger/utils.ts index 34e7085c10..0f9abe39c5 100644 --- a/lib/logger/utils.ts +++ b/lib/logger/utils.ts @@ -160,7 +160,7 @@ export function withSanitizer(streamConfig: bunyan.Stream): bunyan.Stream { const result = streamConfig.type === 'raw' ? raw - : JSON.stringify(raw, bunyan.safeCycles()).replace(/\n?$/, '\n'); + : JSON.stringify(raw, bunyan.safeCycles()).replace(/\n?$/, '\n'); // TODO #12070 stream.write(result, enc, cb); }; diff --git a/lib/util/regex.ts b/lib/util/regex.ts index 1ece8cf47c..78d4814227 100644 --- a/lib/util/regex.ts +++ b/lib/util/regex.ts @@ -1,5 +1,6 @@ import is from '@sindresorhus/is'; import { CONFIG_VALIDATION } from '../constants/error-messages'; +// eslint-disable-next-line import/no-cycle import { logger } from '../logger'; let RegEx: RegExpConstructor; @@ -16,13 +17,13 @@ try { RegEx = RegExp; } -export function regEx(pattern: string, flags?: string): RegExp { +export function regEx(pattern: string | RegExp, flags?: string): RegExp { try { return new RegEx(pattern, flags); } catch (err) { const error = new Error(CONFIG_VALIDATION); - error.validationSource = pattern; - error.validationError = `Invalid regular expression: ${pattern}`; + error.validationSource = pattern.toString(); + error.validationError = `Invalid regular expression: ${pattern.toString()}`; throw error; } } -- GitLab