renovate 43.64.0 → 43.64.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -12,10 +12,10 @@ import { toSha256 } from "../../../util/hash.js";
|
|
|
12
12
|
import api from "../../versioning/docker/index.js";
|
|
13
13
|
import { getGoogleAuthToken } from "../util.js";
|
|
14
14
|
import { parseGitUrl } from "../../../util/git/url.js";
|
|
15
|
+
import { BearerScheme, parse } from "../../../util/http/www-authenticate.js";
|
|
15
16
|
import { ecrRegex, getECRAuthToken } from "./ecr.js";
|
|
16
17
|
import { googleRegex } from "./google.js";
|
|
17
18
|
import { isNonEmptyString, isString } from "@sindresorhus/is";
|
|
18
|
-
import { parse } from "auth-header";
|
|
19
19
|
|
|
20
20
|
//#region lib/modules/datasource/docker/common.ts
|
|
21
21
|
const dockerDatasourceId = "docker";
|
|
@@ -50,7 +50,6 @@ async function getAuthHeaders(http, registryHost, dockerRepository, apiCheckUrl
|
|
|
50
50
|
}, "Invalid registry response");
|
|
51
51
|
return null;
|
|
52
52
|
}
|
|
53
|
-
const authenticateHeader = parse(apiCheckResponse.headers["www-authenticate"]);
|
|
54
53
|
const rule = find({
|
|
55
54
|
hostType: dockerDatasourceId,
|
|
56
55
|
url: apiCheckUrl
|
|
@@ -93,7 +92,8 @@ async function getAuthHeaders(http, registryHost, dockerRepository, apiCheckUrl
|
|
|
93
92
|
}, `Using ${authType} token for Docker registry`);
|
|
94
93
|
opts.headers = { authorization: `${authType} ${rule.token}` };
|
|
95
94
|
}
|
|
96
|
-
|
|
95
|
+
const authenticateHeader = parse(apiCheckResponse.headers["www-authenticate"]).find((c) => c.scheme === BearerScheme);
|
|
96
|
+
if (!authenticateHeader || !isString(authenticateHeader.params?.realm) || parseUrl(authenticateHeader.params.realm) === null) {
|
|
97
97
|
logger.once.debug(`hostRules: testing direct auth for ${registryHost}`);
|
|
98
98
|
logger.trace({
|
|
99
99
|
registryHost,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","names":["hostRules.find","dockerVersioning"],"sources":["../../../../lib/modules/datasource/docker/common.ts"],"sourcesContent":["import { isNonEmptyString, isString } from '@sindresorhus/is';\nimport { parse } from 'auth-header';\nimport {\n HOST_DISABLED,\n PAGE_NOT_FOUND_ERROR,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { detectPlatform } from '../../../util/common.ts';\nimport { parseGitUrl } from '../../../util/git/url.ts';\nimport { toSha256 } from '../../../util/hash.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport type {\n HttpOptions,\n HttpResponse,\n OutgoingHttpHeaders,\n} from '../../../util/http/types.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { addSecretForSanitizing } from '../../../util/sanitize.ts';\nimport {\n ensureTrailingSlash,\n parseUrl,\n trimTrailingSlash,\n} from '../../../util/url.ts';\nimport { api as dockerVersioning } from '../../versioning/docker/index.ts';\nimport { getGoogleAuthToken } from '../util.ts';\nimport { ecrRegex, getECRAuthToken } from './ecr.ts';\nimport { googleRegex } from './google.ts';\nimport type { OciHelmConfig } from './schema.ts';\nimport type { RegistryRepository } from './types.ts';\n\nexport const dockerDatasourceId = 'docker';\n\nexport const imageUrlLabel = 'org.opencontainers.image.url';\n\nexport const sourceLabel = 'org.opencontainers.image.source';\nexport const sourceLabels = [sourceLabel, 'org.label-schema.vcs-url'] as const;\n\nexport const gitRefLabel = 'org.opencontainers.image.revision';\n\nexport const DOCKER_HUB = 'https://index.docker.io';\n\nexport function isDockerHost(host: string): boolean {\n const regex = regEx(/(?:^|\\.)docker\\.io$/);\n return regex.test(host);\n}\n\nexport async function getAuthHeaders(\n http: Http,\n registryHost: string,\n dockerRepository: string,\n apiCheckUrl = `${registryHost}/v2/`,\n): Promise<OutgoingHttpHeaders | null> {\n try {\n const options = {\n throwHttpErrors: false,\n noAuth: true,\n cacheProvider: memCacheProvider,\n };\n const apiCheckResponse = apiCheckUrl.endsWith('/v2/')\n ? await http.get(apiCheckUrl, options)\n : // use json request, as this will be cached for tags, so it returns json\n // TODO: add cache test\n await http.getJsonUnchecked(apiCheckUrl, options);\n\n if (apiCheckResponse.statusCode === 200) {\n logger.debug(`No registry auth required for ${apiCheckUrl}`);\n return {};\n }\n if (apiCheckResponse.statusCode === 404) {\n logger.debug(`Page Not Found ${apiCheckUrl}`);\n // throw error up to be caught and potentially retried with library/ prefix\n throw new Error(PAGE_NOT_FOUND_ERROR);\n }\n if (\n apiCheckResponse.statusCode !== 401 ||\n !isNonEmptyString(apiCheckResponse.headers['www-authenticate'])\n ) {\n logger.warn(\n { apiCheckUrl, res: apiCheckResponse },\n 'Invalid registry response',\n );\n return null;\n }\n\n const authenticateHeader = parse(\n apiCheckResponse.headers['www-authenticate'],\n );\n\n const rule = hostRules.find({\n hostType: dockerDatasourceId,\n url: apiCheckUrl,\n });\n const opts: HttpOptions = {};\n\n if (ecrRegex.test(registryHost)) {\n logger.once.debug(`hostRules: ecr auth for ${registryHost}`);\n logger.trace(\n { registryHost, dockerRepository },\n `Using ecr auth for Docker registry`,\n );\n const [, region] = coerceArray(ecrRegex.exec(registryHost));\n const auth = await getECRAuthToken(region, rule);\n if (auth) {\n opts.headers = { authorization: `Basic ${auth}` };\n }\n } else if (\n googleRegex.test(registryHost) &&\n typeof rule.username === 'undefined' &&\n typeof rule.password === 'undefined' &&\n typeof rule.token === 'undefined'\n ) {\n logger.once.debug(`hostRules: google auth for ${registryHost}`);\n logger.trace(\n { registryHost, dockerRepository },\n `Using google auth for Docker registry`,\n );\n const auth = await getGoogleAuthToken();\n if (auth) {\n opts.headers = { authorization: `Basic ${auth}` };\n } else {\n logger.once.debug(\n { registryHost, dockerRepository },\n 'Could not get Google access token, using no auth',\n );\n }\n } else if (rule.username && rule.password) {\n logger.once.debug(`hostRules: basic auth for ${registryHost}`);\n logger.trace(\n { registryHost, dockerRepository },\n `Using basic auth for Docker registry`,\n );\n const auth = Buffer.from(`${rule.username}:${rule.password}`).toString(\n 'base64',\n );\n opts.headers = { authorization: `Basic ${auth}` };\n } else if (rule.token) {\n const authType = rule.authType ?? 'Bearer';\n logger.once.debug(\n `hostRules: ${authType} token auth for ${registryHost}`,\n );\n logger.trace(\n { registryHost, dockerRepository },\n `Using ${authType} token for Docker registry`,\n );\n opts.headers = { authorization: `${authType} ${rule.token}` };\n }\n\n // If realm isn't an url, we should directly use auth header\n // Can happen when we get a Basic auth or some other auth type\n // * WWW-Authenticate: Basic realm=\"Artifactory Realm\"\n // * Www-Authenticate: Basic realm=\"https://123456789.dkr.ecr.eu-central-1.amazonaws.com/\",service=\"ecr.amazonaws.com\"\n // * www-authenticate: Bearer realm=\"https://ghcr.io/token\",service=\"ghcr.io\",scope=\"repository:user/image:pull\"\n // * www-authenticate: Bearer realm=\"https://auth.docker.io/token\",service=\"registry.docker.io\"\n if (\n authenticateHeader.scheme.toUpperCase() !== 'BEARER' ||\n !isString(authenticateHeader.params.realm) ||\n parseUrl(authenticateHeader.params.realm) === null\n ) {\n logger.once.debug(`hostRules: testing direct auth for ${registryHost}`);\n logger.trace(\n { registryHost, dockerRepository, authenticateHeader },\n `Invalid realm, testing direct auth`,\n );\n return opts.headers ?? null;\n }\n\n const authUrl = new URL(`${authenticateHeader.params.realm}`);\n\n // repo isn't known to server yet, so causing wrong scope `repository:user/image:pull`\n if (\n isString(authenticateHeader.params.scope) &&\n !apiCheckUrl.endsWith('/v2/')\n ) {\n authUrl.searchParams.append('scope', authenticateHeader.params.scope);\n } else {\n authUrl.searchParams.append(\n 'scope',\n `repository:${dockerRepository}:pull`,\n );\n }\n\n if (isString(authenticateHeader.params.service)) {\n authUrl.searchParams.append('service', authenticateHeader.params.service);\n }\n\n logger.trace(\n { registryHost, dockerRepository, authUrl: authUrl.href },\n `Obtaining docker registry token`,\n );\n opts.noAuth = true;\n opts.cacheProvider = memCacheProvider;\n const authResponse = (\n await http.getJsonUnchecked<{ token?: string; access_token?: string }>(\n authUrl.href,\n opts,\n )\n ).body;\n\n const token = authResponse.token ?? authResponse.access_token;\n /* v8 ignore next 4 -- TODO: add test */\n if (!token) {\n logger.warn('Failed to obtain docker registry token');\n return null;\n }\n // sanitize token\n addSecretForSanitizing(token);\n return {\n authorization: `Bearer ${token}`,\n };\n } catch (err) /* istanbul ignore next */ {\n /* v8 ignore if */\n if (err.host === 'quay.io') {\n // TODO: debug why quay throws errors (#9604)\n return null;\n }\n /* v8 ignore if */\n if (err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Unauthorized docker lookup',\n );\n logger.debug({ err });\n return null;\n }\n /* v8 ignore if */\n if (err.statusCode === 403) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Not allowed to access docker registry',\n );\n logger.debug({ err });\n return null;\n }\n if (err.name === 'RequestError' && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n /* v8 ignore if */\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n /* v8 ignore if */\n if (err.statusCode >= 500 && err.statusCode < 600) {\n throw new ExternalHostError(err);\n }\n if (err.message === PAGE_NOT_FOUND_ERROR) {\n throw err;\n }\n /* v8 ignore if */\n if (err.message === HOST_DISABLED) {\n logger.trace({ registryHost, dockerRepository, err }, 'Host disabled');\n return null;\n }\n logger.warn(\n { registryHost, dockerRepository, err },\n 'Error obtaining docker token',\n );\n return null;\n }\n}\n\nexport function getRegistryRepository(\n packageName: string,\n registryUrl: string,\n): RegistryRepository {\n if (registryUrl !== DOCKER_HUB) {\n const registryEndingWithSlash = ensureTrailingSlash(\n registryUrl.replace(regEx(/^https?:\\/\\//), ''),\n );\n if (packageName.startsWith(registryEndingWithSlash)) {\n let registryHost = trimTrailingSlash(registryUrl);\n if (!regEx(/^https?:\\/\\//).test(registryHost)) {\n registryHost = `https://${registryHost}`;\n }\n let dockerRepository = packageName.replace(registryEndingWithSlash, '');\n const fullUrl = `${registryHost}/${dockerRepository}`;\n const { origin, pathname } = parseUrl(fullUrl)!;\n registryHost = origin;\n dockerRepository = pathname.substring(1);\n return {\n registryHost,\n dockerRepository,\n };\n }\n }\n let registryHost = registryUrl;\n const split = packageName.split('/');\n if (split.length > 1 && (split[0].includes('.') || split[0].includes(':'))) {\n [registryHost] = split;\n split.shift();\n }\n let dockerRepository = split.join('/');\n\n if (!regEx(/^https?:\\/\\//).test(registryHost)) {\n registryHost = `https://${registryHost}`;\n }\n\n const { path, base } =\n regEx(/^(?<base>https:\\/\\/[^/]+)\\/(?<path>.+)$/).exec(registryHost)\n ?.groups ?? {};\n if (base && path) {\n registryHost = base;\n dockerRepository = `${trimTrailingSlash(path)}/${dockerRepository}`;\n }\n\n registryHost = registryHost\n .replace('https://docker.io', 'https://index.docker.io')\n .replace('https://registry-1.docker.io', 'https://index.docker.io');\n\n const opts = hostRules.find({\n hostType: dockerDatasourceId,\n url: registryHost,\n });\n if (opts?.insecureRegistry) {\n registryHost = registryHost.replace('https', 'http');\n }\n if (registryHost.endsWith('.docker.io') && !dockerRepository.includes('/')) {\n dockerRepository = 'library/' + dockerRepository;\n }\n return {\n registryHost,\n dockerRepository,\n };\n}\n\nexport function extractDigestFromResponseBody(\n manifestResponse: HttpResponse,\n): string {\n return 'sha256:' + toSha256(manifestResponse.body);\n}\n\nexport function findLatestStable(tags: string[]): string | null {\n let stable: string | null = null;\n\n for (const tag of tags) {\n if (!dockerVersioning.isValid(tag) || !dockerVersioning.isStable(tag)) {\n continue;\n }\n\n if (!stable || dockerVersioning.isGreaterThan(tag, stable)) {\n stable = tag;\n }\n }\n\n return stable;\n}\n\nconst chartRepo = regEx(/charts?|helm|helm-charts?/i);\n\nfunction isPossibleChartRepo(url: string): boolean {\n if (detectPlatform(url) === null) {\n return false;\n }\n\n const parsed = parseGitUrl(url);\n return chartRepo.test(parsed.name);\n}\n\nexport function findHelmSourceUrl(release: OciHelmConfig): string | null {\n if (release.home && isPossibleChartRepo(release.home)) {\n return release.home;\n }\n\n if (!release.sources?.length) {\n return null;\n }\n\n for (const url of release.sources) {\n if (isPossibleChartRepo(url)) {\n return url;\n }\n }\n\n // fallback\n return release.sources[0];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"common.js","names":["hostRules.find","dockerVersioning"],"sources":["../../../../lib/modules/datasource/docker/common.ts"],"sourcesContent":["import { isNonEmptyString, isString } from '@sindresorhus/is';\nimport {\n HOST_DISABLED,\n PAGE_NOT_FOUND_ERROR,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { detectPlatform } from '../../../util/common.ts';\nimport { parseGitUrl } from '../../../util/git/url.ts';\nimport { toSha256 } from '../../../util/hash.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport type {\n HttpOptions,\n HttpResponse,\n OutgoingHttpHeaders,\n} from '../../../util/http/types.ts';\nimport type { ParamsChallenge } from '../../../util/http/www-authenticate.ts';\nimport { BearerScheme, parse } from '../../../util/http/www-authenticate.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { addSecretForSanitizing } from '../../../util/sanitize.ts';\nimport {\n ensureTrailingSlash,\n parseUrl,\n trimTrailingSlash,\n} from '../../../util/url.ts';\nimport { api as dockerVersioning } from '../../versioning/docker/index.ts';\nimport { getGoogleAuthToken } from '../util.ts';\nimport { ecrRegex, getECRAuthToken } from './ecr.ts';\nimport { googleRegex } from './google.ts';\nimport type { OciHelmConfig } from './schema.ts';\nimport type { RegistryRepository } from './types.ts';\n\nexport const dockerDatasourceId = 'docker';\n\nexport const imageUrlLabel = 'org.opencontainers.image.url';\n\nexport const sourceLabel = 'org.opencontainers.image.source';\nexport const sourceLabels = [sourceLabel, 'org.label-schema.vcs-url'] as const;\n\nexport const gitRefLabel = 'org.opencontainers.image.revision';\n\nexport const DOCKER_HUB = 'https://index.docker.io';\n\nexport function isDockerHost(host: string): boolean {\n const regex = regEx(/(?:^|\\.)docker\\.io$/);\n return regex.test(host);\n}\n\nexport async function getAuthHeaders(\n http: Http,\n registryHost: string,\n dockerRepository: string,\n apiCheckUrl = `${registryHost}/v2/`,\n): Promise<OutgoingHttpHeaders | null> {\n try {\n const options = {\n throwHttpErrors: false,\n noAuth: true,\n cacheProvider: memCacheProvider,\n };\n const apiCheckResponse = apiCheckUrl.endsWith('/v2/')\n ? await http.get(apiCheckUrl, options)\n : // use json request, as this will be cached for tags, so it returns json\n // TODO: add cache test\n await http.getJsonUnchecked(apiCheckUrl, options);\n\n if (apiCheckResponse.statusCode === 200) {\n logger.debug(`No registry auth required for ${apiCheckUrl}`);\n return {};\n }\n if (apiCheckResponse.statusCode === 404) {\n logger.debug(`Page Not Found ${apiCheckUrl}`);\n // throw error up to be caught and potentially retried with library/ prefix\n throw new Error(PAGE_NOT_FOUND_ERROR);\n }\n if (\n apiCheckResponse.statusCode !== 401 ||\n !isNonEmptyString(apiCheckResponse.headers['www-authenticate'])\n ) {\n logger.warn(\n { apiCheckUrl, res: apiCheckResponse },\n 'Invalid registry response',\n );\n return null;\n }\n\n const rule = hostRules.find({\n hostType: dockerDatasourceId,\n url: apiCheckUrl,\n });\n const opts: HttpOptions = {};\n\n if (ecrRegex.test(registryHost)) {\n logger.once.debug(`hostRules: ecr auth for ${registryHost}`);\n logger.trace(\n { registryHost, dockerRepository },\n `Using ecr auth for Docker registry`,\n );\n const [, region] = coerceArray(ecrRegex.exec(registryHost));\n const auth = await getECRAuthToken(region, rule);\n if (auth) {\n opts.headers = { authorization: `Basic ${auth}` };\n }\n } else if (\n googleRegex.test(registryHost) &&\n typeof rule.username === 'undefined' &&\n typeof rule.password === 'undefined' &&\n typeof rule.token === 'undefined'\n ) {\n logger.once.debug(`hostRules: google auth for ${registryHost}`);\n logger.trace(\n { registryHost, dockerRepository },\n `Using google auth for Docker registry`,\n );\n const auth = await getGoogleAuthToken();\n if (auth) {\n opts.headers = { authorization: `Basic ${auth}` };\n } else {\n logger.once.debug(\n { registryHost, dockerRepository },\n 'Could not get Google access token, using no auth',\n );\n }\n } else if (rule.username && rule.password) {\n logger.once.debug(`hostRules: basic auth for ${registryHost}`);\n logger.trace(\n { registryHost, dockerRepository },\n `Using basic auth for Docker registry`,\n );\n const auth = Buffer.from(`${rule.username}:${rule.password}`).toString(\n 'base64',\n );\n opts.headers = { authorization: `Basic ${auth}` };\n } else if (rule.token) {\n const authType = rule.authType ?? 'Bearer';\n logger.once.debug(\n `hostRules: ${authType} token auth for ${registryHost}`,\n );\n logger.trace(\n { registryHost, dockerRepository },\n `Using ${authType} token for Docker registry`,\n );\n opts.headers = { authorization: `${authType} ${rule.token}` };\n }\n\n const challenges = parse(apiCheckResponse.headers['www-authenticate']);\n const authenticateHeader = challenges.find(\n (c): c is ParamsChallenge => c.scheme === BearerScheme,\n );\n\n // If realm isn't an url, we should directly use auth header\n // Can happen when we get a Basic auth or some other auth type\n // * WWW-Authenticate: Basic realm=\"Artifactory Realm\"\n // * Www-Authenticate: Basic realm=\"https://123456789.dkr.ecr.eu-central-1.amazonaws.com/\",service=\"ecr.amazonaws.com\"\n // * www-authenticate: Bearer realm=\"https://ghcr.io/token\",service=\"ghcr.io\",scope=\"repository:user/image:pull\"\n // * www-authenticate: Bearer realm=\"https://auth.docker.io/token\",service=\"registry.docker.io\"\n // * www-authenticate: Bearer realm=\"https://codeberg.org/v2/token\",service=\"container_registry\",scope=\"*\",Basic realm=\"https://codeberg.org/v2\",service=\"container_registry\",scope=\"*\"\n if (\n !authenticateHeader ||\n !isString(authenticateHeader.params?.realm) ||\n parseUrl(authenticateHeader.params.realm) === null\n ) {\n logger.once.debug(`hostRules: testing direct auth for ${registryHost}`);\n logger.trace(\n { registryHost, dockerRepository, authenticateHeader },\n `Invalid realm, testing direct auth`,\n );\n return opts.headers ?? null;\n }\n\n const authUrl = new URL(`${authenticateHeader.params.realm}`);\n\n // repo isn't known to server yet, so causing wrong scope `repository:user/image:pull`\n if (\n isString(authenticateHeader.params.scope) &&\n !apiCheckUrl.endsWith('/v2/')\n ) {\n authUrl.searchParams.append('scope', authenticateHeader.params.scope);\n } else {\n authUrl.searchParams.append(\n 'scope',\n `repository:${dockerRepository}:pull`,\n );\n }\n\n if (isString(authenticateHeader.params.service)) {\n authUrl.searchParams.append('service', authenticateHeader.params.service);\n }\n\n logger.trace(\n { registryHost, dockerRepository, authUrl: authUrl.href },\n `Obtaining docker registry token`,\n );\n opts.noAuth = true;\n opts.cacheProvider = memCacheProvider;\n const authResponse = (\n await http.getJsonUnchecked<{ token?: string; access_token?: string }>(\n authUrl.href,\n opts,\n )\n ).body;\n\n const token = authResponse.token ?? authResponse.access_token;\n /* v8 ignore next 4 -- TODO: add test */\n if (!token) {\n logger.warn('Failed to obtain docker registry token');\n return null;\n }\n // sanitize token\n addSecretForSanitizing(token);\n return {\n authorization: `Bearer ${token}`,\n };\n } catch (err) /* istanbul ignore next */ {\n /* v8 ignore if */\n if (err.host === 'quay.io') {\n // TODO: debug why quay throws errors (#9604)\n return null;\n }\n /* v8 ignore if */\n if (err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Unauthorized docker lookup',\n );\n logger.debug({ err });\n return null;\n }\n /* v8 ignore if */\n if (err.statusCode === 403) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Not allowed to access docker registry',\n );\n logger.debug({ err });\n return null;\n }\n if (err.name === 'RequestError' && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n /* v8 ignore if */\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n /* v8 ignore if */\n if (err.statusCode >= 500 && err.statusCode < 600) {\n throw new ExternalHostError(err);\n }\n if (err.message === PAGE_NOT_FOUND_ERROR) {\n throw err;\n }\n /* v8 ignore if */\n if (err.message === HOST_DISABLED) {\n logger.trace({ registryHost, dockerRepository, err }, 'Host disabled');\n return null;\n }\n logger.warn(\n { registryHost, dockerRepository, err },\n 'Error obtaining docker token',\n );\n return null;\n }\n}\n\nexport function getRegistryRepository(\n packageName: string,\n registryUrl: string,\n): RegistryRepository {\n if (registryUrl !== DOCKER_HUB) {\n const registryEndingWithSlash = ensureTrailingSlash(\n registryUrl.replace(regEx(/^https?:\\/\\//), ''),\n );\n if (packageName.startsWith(registryEndingWithSlash)) {\n let registryHost = trimTrailingSlash(registryUrl);\n if (!regEx(/^https?:\\/\\//).test(registryHost)) {\n registryHost = `https://${registryHost}`;\n }\n let dockerRepository = packageName.replace(registryEndingWithSlash, '');\n const fullUrl = `${registryHost}/${dockerRepository}`;\n const { origin, pathname } = parseUrl(fullUrl)!;\n registryHost = origin;\n dockerRepository = pathname.substring(1);\n return {\n registryHost,\n dockerRepository,\n };\n }\n }\n let registryHost = registryUrl;\n const split = packageName.split('/');\n if (split.length > 1 && (split[0].includes('.') || split[0].includes(':'))) {\n [registryHost] = split;\n split.shift();\n }\n let dockerRepository = split.join('/');\n\n if (!regEx(/^https?:\\/\\//).test(registryHost)) {\n registryHost = `https://${registryHost}`;\n }\n\n const { path, base } =\n regEx(/^(?<base>https:\\/\\/[^/]+)\\/(?<path>.+)$/).exec(registryHost)\n ?.groups ?? {};\n if (base && path) {\n registryHost = base;\n dockerRepository = `${trimTrailingSlash(path)}/${dockerRepository}`;\n }\n\n registryHost = registryHost\n .replace('https://docker.io', 'https://index.docker.io')\n .replace('https://registry-1.docker.io', 'https://index.docker.io');\n\n const opts = hostRules.find({\n hostType: dockerDatasourceId,\n url: registryHost,\n });\n if (opts?.insecureRegistry) {\n registryHost = registryHost.replace('https', 'http');\n }\n if (registryHost.endsWith('.docker.io') && !dockerRepository.includes('/')) {\n dockerRepository = 'library/' + dockerRepository;\n }\n return {\n registryHost,\n dockerRepository,\n };\n}\n\nexport function extractDigestFromResponseBody(\n manifestResponse: HttpResponse,\n): string {\n return 'sha256:' + toSha256(manifestResponse.body);\n}\n\nexport function findLatestStable(tags: string[]): string | null {\n let stable: string | null = null;\n\n for (const tag of tags) {\n if (!dockerVersioning.isValid(tag) || !dockerVersioning.isStable(tag)) {\n continue;\n }\n\n if (!stable || dockerVersioning.isGreaterThan(tag, stable)) {\n stable = tag;\n }\n }\n\n return stable;\n}\n\nconst chartRepo = regEx(/charts?|helm|helm-charts?/i);\n\nfunction isPossibleChartRepo(url: string): boolean {\n if (detectPlatform(url) === null) {\n return false;\n }\n\n const parsed = parseGitUrl(url);\n return chartRepo.test(parsed.name);\n}\n\nexport function findHelmSourceUrl(release: OciHelmConfig): string | null {\n if (release.home && isPossibleChartRepo(release.home)) {\n return release.home;\n }\n\n if (!release.sources?.length) {\n return null;\n }\n\n for (const url of release.sources) {\n if (isPossibleChartRepo(url)) {\n return url;\n }\n }\n\n // fallback\n return release.sources[0];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAmCA,MAAa,qBAAqB;AAElC,MAAa,gBAAgB;AAE7B,MAAa,cAAc;AAC3B,MAAa,eAAe,CAAC,aAAa,2BAA2B;AAErE,MAAa,cAAc;AAE3B,MAAa,aAAa;AAE1B,SAAgB,aAAa,MAAuB;AAElD,QADc,MAAM,sBAAsB,CAC7B,KAAK,KAAK;;AAGzB,eAAsB,eACpB,MACA,cACA,kBACA,cAAc,GAAG,aAAa,OACO;AACrC,KAAI;EACF,MAAM,UAAU;GACd,iBAAiB;GACjB,QAAQ;GACR,eAAe;GAChB;EACD,MAAM,mBAAmB,YAAY,SAAS,OAAO,GACjD,MAAM,KAAK,IAAI,aAAa,QAAQ,GAGpC,MAAM,KAAK,iBAAiB,aAAa,QAAQ;AAErD,MAAI,iBAAiB,eAAe,KAAK;AACvC,UAAO,MAAM,iCAAiC,cAAc;AAC5D,UAAO,EAAE;;AAEX,MAAI,iBAAiB,eAAe,KAAK;AACvC,UAAO,MAAM,kBAAkB,cAAc;AAE7C,SAAM,IAAI,MAAM,qBAAqB;;AAEvC,MACE,iBAAiB,eAAe,OAChC,CAAC,iBAAiB,iBAAiB,QAAQ,oBAAoB,EAC/D;AACA,UAAO,KACL;IAAE;IAAa,KAAK;IAAkB,EACtC,4BACD;AACD,UAAO;;EAGT,MAAM,OAAOA,KAAe;GAC1B,UAAU;GACV,KAAK;GACN,CAAC;EACF,MAAM,OAAoB,EAAE;AAE5B,MAAI,SAAS,KAAK,aAAa,EAAE;AAC/B,UAAO,KAAK,MAAM,2BAA2B,eAAe;AAC5D,UAAO,MACL;IAAE;IAAc;IAAkB,EAClC,qCACD;GACD,MAAM,GAAG,UAAU,YAAY,SAAS,KAAK,aAAa,CAAC;GAC3D,MAAM,OAAO,MAAM,gBAAgB,QAAQ,KAAK;AAChD,OAAI,KACF,MAAK,UAAU,EAAE,eAAe,SAAS,QAAQ;aAGnD,YAAY,KAAK,aAAa,IAC9B,OAAO,KAAK,aAAa,eACzB,OAAO,KAAK,aAAa,eACzB,OAAO,KAAK,UAAU,aACtB;AACA,UAAO,KAAK,MAAM,8BAA8B,eAAe;AAC/D,UAAO,MACL;IAAE;IAAc;IAAkB,EAClC,wCACD;GACD,MAAM,OAAO,MAAM,oBAAoB;AACvC,OAAI,KACF,MAAK,UAAU,EAAE,eAAe,SAAS,QAAQ;OAEjD,QAAO,KAAK,MACV;IAAE;IAAc;IAAkB,EAClC,mDACD;aAEM,KAAK,YAAY,KAAK,UAAU;AACzC,UAAO,KAAK,MAAM,6BAA6B,eAAe;AAC9D,UAAO,MACL;IAAE;IAAc;IAAkB,EAClC,uCACD;AAID,QAAK,UAAU,EAAE,eAAe,SAHnB,OAAO,KAAK,GAAG,KAAK,SAAS,GAAG,KAAK,WAAW,CAAC,SAC5D,SACD,IACgD;aACxC,KAAK,OAAO;GACrB,MAAM,WAAW,KAAK,YAAY;AAClC,UAAO,KAAK,MACV,cAAc,SAAS,kBAAkB,eAC1C;AACD,UAAO,MACL;IAAE;IAAc;IAAkB,EAClC,SAAS,SAAS,4BACnB;AACD,QAAK,UAAU,EAAE,eAAe,GAAG,SAAS,GAAG,KAAK,SAAS;;EAI/D,MAAM,qBADa,MAAM,iBAAiB,QAAQ,oBAAoB,CAChC,MACnC,MAA4B,EAAE,WAAW,aAC3C;AASD,MACE,CAAC,sBACD,CAAC,SAAS,mBAAmB,QAAQ,MAAM,IAC3C,SAAS,mBAAmB,OAAO,MAAM,KAAK,MAC9C;AACA,UAAO,KAAK,MAAM,sCAAsC,eAAe;AACvE,UAAO,MACL;IAAE;IAAc;IAAkB;IAAoB,EACtD,qCACD;AACD,UAAO,KAAK,WAAW;;EAGzB,MAAM,UAAU,IAAI,IAAI,GAAG,mBAAmB,OAAO,QAAQ;AAG7D,MACE,SAAS,mBAAmB,OAAO,MAAM,IACzC,CAAC,YAAY,SAAS,OAAO,CAE7B,SAAQ,aAAa,OAAO,SAAS,mBAAmB,OAAO,MAAM;MAErE,SAAQ,aAAa,OACnB,SACA,cAAc,iBAAiB,OAChC;AAGH,MAAI,SAAS,mBAAmB,OAAO,QAAQ,CAC7C,SAAQ,aAAa,OAAO,WAAW,mBAAmB,OAAO,QAAQ;AAG3E,SAAO,MACL;GAAE;GAAc;GAAkB,SAAS,QAAQ;GAAM,EACzD,kCACD;AACD,OAAK,SAAS;AACd,OAAK,gBAAgB;EACrB,MAAM,gBACJ,MAAM,KAAK,iBACT,QAAQ,MACR,KACD,EACD;EAEF,MAAM,QAAQ,aAAa,SAAS,aAAa;;AAEjD,MAAI,CAAC,OAAO;AACV,UAAO,KAAK,yCAAyC;AACrD,UAAO;;AAGT,yBAAuB,MAAM;AAC7B,SAAO,EACL,eAAe,UAAU,SAC1B;UACM,iCAAgC;;AAEvC,MAAI,IAAI,SAAS,UAEf,QAAO;;AAGT,MAAI,IAAI,eAAe,KAAK;AAC1B,UAAO,MACL;IAAE;IAAc;IAAkB,EAClC,6BACD;AACD,UAAO,MAAM,EAAE,KAAK,CAAC;AACrB,UAAO;;;AAGT,MAAI,IAAI,eAAe,KAAK;AAC1B,UAAO,MACL;IAAE;IAAc;IAAkB,EAClC,wCACD;AACD,UAAO,MAAM,EAAE,KAAK,CAAC;AACrB,UAAO;;AAET,MAAI,IAAI,SAAS,kBAAkB,aAAa,aAAa,CAC3D,OAAM,IAAI,kBAAkB,IAAI;;AAGlC,MAAI,IAAI,eAAe,OAAO,aAAa,aAAa,CACtD,OAAM,IAAI,kBAAkB,IAAI;;AAGlC,MAAI,IAAI,cAAc,OAAO,IAAI,aAAa,IAC5C,OAAM,IAAI,kBAAkB,IAAI;AAElC,MAAI,IAAI,YAAY,qBAClB,OAAM;;AAGR,MAAI,IAAI,YAAY,eAAe;AACjC,UAAO,MAAM;IAAE;IAAc;IAAkB;IAAK,EAAE,gBAAgB;AACtE,UAAO;;AAET,SAAO,KACL;GAAE;GAAc;GAAkB;GAAK,EACvC,+BACD;AACD,SAAO;;;AAIX,SAAgB,sBACd,aACA,aACoB;AACpB,KAAI,gBAAgB,YAAY;EAC9B,MAAM,0BAA0B,oBAC9B,YAAY,QAAQ,MAAM,eAAe,EAAE,GAAG,CAC/C;AACD,MAAI,YAAY,WAAW,wBAAwB,EAAE;GACnD,IAAI,eAAe,kBAAkB,YAAY;AACjD,OAAI,CAAC,MAAM,eAAe,CAAC,KAAK,aAAa,CAC3C,gBAAe,WAAW;GAE5B,IAAI,mBAAmB,YAAY,QAAQ,yBAAyB,GAAG;GAEvE,MAAM,EAAE,QAAQ,aAAa,SADb,GAAG,aAAa,GAAG,mBACW;AAC9C,kBAAe;AACf,sBAAmB,SAAS,UAAU,EAAE;AACxC,UAAO;IACL;IACA;IACD;;;CAGL,IAAI,eAAe;CACnB,MAAM,QAAQ,YAAY,MAAM,IAAI;AACpC,KAAI,MAAM,SAAS,MAAM,MAAM,GAAG,SAAS,IAAI,IAAI,MAAM,GAAG,SAAS,IAAI,GAAG;AAC1E,GAAC,gBAAgB;AACjB,QAAM,OAAO;;CAEf,IAAI,mBAAmB,MAAM,KAAK,IAAI;AAEtC,KAAI,CAAC,MAAM,eAAe,CAAC,KAAK,aAAa,CAC3C,gBAAe,WAAW;CAG5B,MAAM,EAAE,MAAM,SACZ,MAAM,0CAA0C,CAAC,KAAK,aAAa,EAC/D,UAAU,EAAE;AAClB,KAAI,QAAQ,MAAM;AAChB,iBAAe;AACf,qBAAmB,GAAG,kBAAkB,KAAK,CAAC,GAAG;;AAGnD,gBAAe,aACZ,QAAQ,qBAAqB,0BAA0B,CACvD,QAAQ,gCAAgC,0BAA0B;AAMrE,KAJaA,KAAe;EAC1B,UAAU;EACV,KAAK;EACN,CAAC,EACQ,iBACR,gBAAe,aAAa,QAAQ,SAAS,OAAO;AAEtD,KAAI,aAAa,SAAS,aAAa,IAAI,CAAC,iBAAiB,SAAS,IAAI,CACxE,oBAAmB,aAAa;AAElC,QAAO;EACL;EACA;EACD;;AAGH,SAAgB,8BACd,kBACQ;AACR,QAAO,YAAY,SAAS,iBAAiB,KAAK;;AAGpD,SAAgB,iBAAiB,MAA+B;CAC9D,IAAI,SAAwB;AAE5B,MAAK,MAAM,OAAO,MAAM;AACtB,MAAI,CAACC,IAAiB,QAAQ,IAAI,IAAI,CAACA,IAAiB,SAAS,IAAI,CACnE;AAGF,MAAI,CAAC,UAAUA,IAAiB,cAAc,KAAK,OAAO,CACxD,UAAS;;AAIb,QAAO;;AAGT,MAAM,YAAY,MAAM,6BAA6B;AAErD,SAAS,oBAAoB,KAAsB;AACjD,KAAI,eAAe,IAAI,KAAK,KAC1B,QAAO;CAGT,MAAM,SAAS,YAAY,IAAI;AAC/B,QAAO,UAAU,KAAK,OAAO,KAAK;;AAGpC,SAAgB,kBAAkB,SAAuC;AACvE,KAAI,QAAQ,QAAQ,oBAAoB,QAAQ,KAAK,CACnD,QAAO,QAAQ;AAGjB,KAAI,CAAC,QAAQ,SAAS,OACpB,QAAO;AAGT,MAAK,MAAM,OAAO,QAAQ,QACxB,KAAI,oBAAoB,IAAI,CAC1B,QAAO;AAKX,QAAO,QAAQ,QAAQ"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { regEx } from "../regex.js";
|
|
2
|
+
|
|
3
|
+
//#region lib/util/http/www-authenticate.ts
|
|
4
|
+
/**
|
|
5
|
+
* Inspired by https://github.com/alexdutton/www-authenticate
|
|
6
|
+
*/
|
|
7
|
+
const BearerScheme = "bearer";
|
|
8
|
+
const tokenizer = [
|
|
9
|
+
{
|
|
10
|
+
type: "token",
|
|
11
|
+
matcher: regEx(/^([a-zA-Z0-9!#$%&'*+.^_`|~-]+)/)
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
type: "token",
|
|
15
|
+
matcher: regEx(/^"((?:[^"\\]|\\\\|\\")*)"/)
|
|
16
|
+
},
|
|
17
|
+
{ matcher: regEx(/^\s+/) },
|
|
18
|
+
{
|
|
19
|
+
type: "equals",
|
|
20
|
+
matcher: regEx(/^(=)/)
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
type: "comma",
|
|
24
|
+
matcher: regEx(/^(,)/)
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
function tokenize(input) {
|
|
28
|
+
const result = [];
|
|
29
|
+
let remaining = input;
|
|
30
|
+
while (remaining.length > 0) {
|
|
31
|
+
let matched = false;
|
|
32
|
+
for (const t of tokenizer) {
|
|
33
|
+
const match = t.matcher.exec(remaining);
|
|
34
|
+
if (match) {
|
|
35
|
+
matched = true;
|
|
36
|
+
remaining = remaining.slice(match[0].length);
|
|
37
|
+
if (t.type) result.push({
|
|
38
|
+
type: t.type,
|
|
39
|
+
value: match[1]
|
|
40
|
+
});
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!matched) throw new Error(`Failed to parse value`);
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
function groupPairs(tokens) {
|
|
49
|
+
for (let i = 0; i < tokens.length - 2; i++) if (tokens[i].type === "token" && tokens[i + 1].type === "equals" && tokens[i + 2].type === "token") {
|
|
50
|
+
tokens[i] = {
|
|
51
|
+
type: "pair",
|
|
52
|
+
key: tokens[i].value,
|
|
53
|
+
value: tokens[i + 2].value
|
|
54
|
+
};
|
|
55
|
+
tokens.splice(i + 1, 2);
|
|
56
|
+
}
|
|
57
|
+
return tokens;
|
|
58
|
+
}
|
|
59
|
+
function groupChallenges(tokens) {
|
|
60
|
+
const result = [];
|
|
61
|
+
while (tokens.length > 0) {
|
|
62
|
+
let j = 1;
|
|
63
|
+
if (tokens.length === 1) {} else if (tokens[1].type === "comma") {} else if (tokens[1].type === "token") j = 2;
|
|
64
|
+
else {
|
|
65
|
+
while (j < tokens.length && tokens[j].type === "pair") j += 2;
|
|
66
|
+
j--;
|
|
67
|
+
}
|
|
68
|
+
result.push({
|
|
69
|
+
scheme: tokens[0].value,
|
|
70
|
+
tokens: tokens.slice(1, j)
|
|
71
|
+
});
|
|
72
|
+
tokens.splice(0, j + 1);
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
function parse(header) {
|
|
77
|
+
const result = [];
|
|
78
|
+
for (const h of Array.isArray(header) ? header : [header]) {
|
|
79
|
+
let tokens = tokenize(h);
|
|
80
|
+
if (!tokens.length) continue;
|
|
81
|
+
tokens = groupPairs(tokens);
|
|
82
|
+
for (const c of groupChallenges(tokens)) {
|
|
83
|
+
const args = [];
|
|
84
|
+
const params = {};
|
|
85
|
+
for (const t of c.tokens) switch (t.type) {
|
|
86
|
+
case "token":
|
|
87
|
+
args.push(t.value);
|
|
88
|
+
break;
|
|
89
|
+
case "pair":
|
|
90
|
+
params[t.key] = t.value;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
if (args.length) result.push({
|
|
94
|
+
scheme: c.scheme.toLowerCase(),
|
|
95
|
+
params: args[0]
|
|
96
|
+
});
|
|
97
|
+
else if (Object.keys(params).length) result.push({
|
|
98
|
+
scheme: c.scheme.toLowerCase(),
|
|
99
|
+
params
|
|
100
|
+
});
|
|
101
|
+
else result.push({ scheme: c.scheme.toLowerCase() });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
//#endregion
|
|
108
|
+
export { BearerScheme, parse };
|
|
109
|
+
//# sourceMappingURL=www-authenticate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"www-authenticate.js","names":[],"sources":["../../../lib/util/http/www-authenticate.ts"],"sourcesContent":["/**\n * Inspired by https://github.com/alexdutton/www-authenticate\n */\nimport { regEx } from '../regex.ts';\n\ninterface Tokenizer {\n type?: 'token' | 'equals' | 'comma';\n matcher: RegExp;\n}\ninterface ValueToken {\n type: 'token' | 'equals' | 'comma';\n value: string;\n}\n\ninterface PairToken {\n type: 'pair';\n key: string;\n value: string;\n}\n\ntype Token = ValueToken | PairToken;\n\ninterface ChallengeToken {\n scheme: string;\n tokens: Token[];\n}\n\nexport const BearerScheme = 'bearer' as const;\n\nexport interface SimpleChallenge {\n scheme: 'basic';\n params?: string;\n}\nexport interface ParamsChallenge {\n scheme: 'bearer' | 'digest';\n params?: Record<string, string>;\n}\n\nexport interface UnknownChallenge {\n scheme: string;\n params?: unknown;\n}\n\nexport type Challenge = SimpleChallenge | ParamsChallenge | UnknownChallenge;\n\nconst tokenizer: Tokenizer[] = [\n { type: 'token', matcher: regEx(/^([a-zA-Z0-9!#$%&'*+.^_`|~-]+)/) }, // token\n { type: 'token', matcher: regEx(/^\"((?:[^\"\\\\]|\\\\\\\\|\\\\\")*)\"/) }, // quoted-string\n { matcher: regEx(/^\\s+/) }, // whitespace (ignored)\n { type: 'equals', matcher: regEx(/^(=)/) }, // equals\n { type: 'comma', matcher: regEx(/^(,)/) }, // comma\n];\n\nfunction tokenize(input: string): Token[] {\n const result: Token[] = [];\n let remaining = input;\n\n while (remaining.length > 0) {\n let matched = false;\n for (const t of tokenizer) {\n const match = t.matcher.exec(remaining);\n if (match) {\n matched = true;\n remaining = remaining.slice(match[0].length);\n if (t.type) {\n result.push({ type: t.type, value: match[1] });\n }\n break;\n }\n }\n if (!matched) {\n throw new Error(`Failed to parse value`);\n }\n }\n\n return result;\n}\n\nfunction groupPairs(tokens: Token[]): Token[] {\n for (let i = 0; i < tokens.length - 2; i++) {\n if (\n tokens[i].type === 'token' &&\n tokens[i + 1].type === 'equals' &&\n tokens[i + 2].type === 'token'\n ) {\n tokens[i] = {\n type: 'pair',\n key: tokens[i].value,\n value: tokens[i + 2].value,\n };\n tokens.splice(i + 1, 2);\n }\n }\n\n return tokens;\n}\n\nfunction groupChallenges(tokens: Token[]): ChallengeToken[] {\n const result: ChallengeToken[] = [];\n while (tokens.length > 0) {\n let j = 1;\n if (tokens.length === 1) {\n // pass\n } else if (tokens[1].type === 'comma') {\n // pass\n } else if (tokens[1].type === 'token') {\n j = 2;\n } else {\n while (j < tokens.length && tokens[j].type === 'pair') {\n j += 2;\n }\n j--;\n }\n result.push({\n scheme: tokens[0].value,\n tokens: tokens.slice(1, j),\n });\n tokens.splice(0, j + 1);\n }\n\n return result;\n}\n\nexport function parse(header: string | string[]): Challenge[] {\n const result: Challenge[] = [];\n for (const h of Array.isArray(header) ? header : [header]) {\n let tokens = tokenize(h);\n\n if (!tokens.length) {\n continue;\n }\n\n tokens = groupPairs(tokens);\n\n for (const c of groupChallenges(tokens)) {\n const args: string[] = [];\n const params: Record<string, string> = {};\n\n for (const t of c.tokens) {\n switch (t.type) {\n case 'token':\n args.push(t.value);\n break;\n case 'pair':\n params[t.key] = t.value;\n break;\n }\n }\n\n if (args.length) {\n result.push({ scheme: c.scheme.toLowerCase(), params: args[0] });\n } else if (Object.keys(params).length) {\n result.push({ scheme: c.scheme.toLowerCase(), params });\n } else {\n result.push({ scheme: c.scheme.toLowerCase() });\n }\n }\n }\n\n return result;\n}\n"],"mappings":";;;;;;AA2BA,MAAa,eAAe;AAkB5B,MAAM,YAAyB;CAC7B;EAAE,MAAM;EAAS,SAAS,MAAM,iCAAiC;EAAE;CACnE;EAAE,MAAM;EAAS,SAAS,MAAM,4BAA4B;EAAE;CAC9D,EAAE,SAAS,MAAM,OAAO,EAAE;CAC1B;EAAE,MAAM;EAAU,SAAS,MAAM,OAAO;EAAE;CAC1C;EAAE,MAAM;EAAS,SAAS,MAAM,OAAO;EAAE;CAC1C;AAED,SAAS,SAAS,OAAwB;CACxC,MAAM,SAAkB,EAAE;CAC1B,IAAI,YAAY;AAEhB,QAAO,UAAU,SAAS,GAAG;EAC3B,IAAI,UAAU;AACd,OAAK,MAAM,KAAK,WAAW;GACzB,MAAM,QAAQ,EAAE,QAAQ,KAAK,UAAU;AACvC,OAAI,OAAO;AACT,cAAU;AACV,gBAAY,UAAU,MAAM,MAAM,GAAG,OAAO;AAC5C,QAAI,EAAE,KACJ,QAAO,KAAK;KAAE,MAAM,EAAE;KAAM,OAAO,MAAM;KAAI,CAAC;AAEhD;;;AAGJ,MAAI,CAAC,QACH,OAAM,IAAI,MAAM,wBAAwB;;AAI5C,QAAO;;AAGT,SAAS,WAAW,QAA0B;AAC5C,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,IACrC,KACE,OAAO,GAAG,SAAS,WACnB,OAAO,IAAI,GAAG,SAAS,YACvB,OAAO,IAAI,GAAG,SAAS,SACvB;AACA,SAAO,KAAK;GACV,MAAM;GACN,KAAK,OAAO,GAAG;GACf,OAAO,OAAO,IAAI,GAAG;GACtB;AACD,SAAO,OAAO,IAAI,GAAG,EAAE;;AAI3B,QAAO;;AAGT,SAAS,gBAAgB,QAAmC;CAC1D,MAAM,SAA2B,EAAE;AACnC,QAAO,OAAO,SAAS,GAAG;EACxB,IAAI,IAAI;AACR,MAAI,OAAO,WAAW,GAAG,YAEd,OAAO,GAAG,SAAS,SAAS,YAE5B,OAAO,GAAG,SAAS,QAC5B,KAAI;OACC;AACL,UAAO,IAAI,OAAO,UAAU,OAAO,GAAG,SAAS,OAC7C,MAAK;AAEP;;AAEF,SAAO,KAAK;GACV,QAAQ,OAAO,GAAG;GAClB,QAAQ,OAAO,MAAM,GAAG,EAAE;GAC3B,CAAC;AACF,SAAO,OAAO,GAAG,IAAI,EAAE;;AAGzB,QAAO;;AAGT,SAAgB,MAAM,QAAwC;CAC5D,MAAM,SAAsB,EAAE;AAC9B,MAAK,MAAM,KAAK,MAAM,QAAQ,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE;EACzD,IAAI,SAAS,SAAS,EAAE;AAExB,MAAI,CAAC,OAAO,OACV;AAGF,WAAS,WAAW,OAAO;AAE3B,OAAK,MAAM,KAAK,gBAAgB,OAAO,EAAE;GACvC,MAAM,OAAiB,EAAE;GACzB,MAAM,SAAiC,EAAE;AAEzC,QAAK,MAAM,KAAK,EAAE,OAChB,SAAQ,EAAE,MAAV;IACE,KAAK;AACH,UAAK,KAAK,EAAE,MAAM;AAClB;IACF,KAAK;AACH,YAAO,EAAE,OAAO,EAAE;AAClB;;AAIN,OAAI,KAAK,OACP,QAAO,KAAK;IAAE,QAAQ,EAAE,OAAO,aAAa;IAAE,QAAQ,KAAK;IAAI,CAAC;YACvD,OAAO,KAAK,OAAO,CAAC,OAC7B,QAAO,KAAK;IAAE,QAAQ,EAAE,OAAO,aAAa;IAAE;IAAQ,CAAC;OAEvD,QAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,aAAa,EAAE,CAAC;;;AAKrD,QAAO"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "renovate",
|
|
3
3
|
"description": "Automated dependency updates. Flexible so you don't need to be.",
|
|
4
|
-
"version": "43.64.
|
|
4
|
+
"version": "43.64.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"renovate": "dist/renovate.js",
|
|
@@ -105,12 +105,12 @@
|
|
|
105
105
|
"@opentelemetry/context-async-hooks": "2.6.0",
|
|
106
106
|
"@opentelemetry/exporter-trace-otlp-http": "0.213.0",
|
|
107
107
|
"@opentelemetry/instrumentation": "0.213.0",
|
|
108
|
-
"@opentelemetry/instrumentation-bunyan": "0.
|
|
108
|
+
"@opentelemetry/instrumentation-bunyan": "0.58.0",
|
|
109
109
|
"@opentelemetry/instrumentation-http": "0.213.0",
|
|
110
|
-
"@opentelemetry/instrumentation-redis": "0.
|
|
111
|
-
"@opentelemetry/resource-detector-aws": "2.
|
|
112
|
-
"@opentelemetry/resource-detector-azure": "0.
|
|
113
|
-
"@opentelemetry/resource-detector-gcp": "0.
|
|
110
|
+
"@opentelemetry/instrumentation-redis": "0.61.0",
|
|
111
|
+
"@opentelemetry/resource-detector-aws": "2.13.0",
|
|
112
|
+
"@opentelemetry/resource-detector-azure": "0.21.0",
|
|
113
|
+
"@opentelemetry/resource-detector-gcp": "0.48.0",
|
|
114
114
|
"@opentelemetry/resource-detector-github": "0.32.0",
|
|
115
115
|
"@opentelemetry/resources": "2.6.0",
|
|
116
116
|
"@opentelemetry/sdk-trace-base": "2.6.0",
|
|
@@ -131,7 +131,6 @@
|
|
|
131
131
|
"ae-cvss-calculator": "1.0.11",
|
|
132
132
|
"agentkeepalive": "4.6.0",
|
|
133
133
|
"async-mutex": "0.5.0",
|
|
134
|
-
"auth-header": "1.0.0",
|
|
135
134
|
"aws4": "1.13.2",
|
|
136
135
|
"azure-devops-node-api": "15.1.2",
|
|
137
136
|
"bunyan": "1.8.15",
|
|
@@ -226,7 +225,6 @@
|
|
|
226
225
|
"@openpgp/web-stream-tools": "0.3.0",
|
|
227
226
|
"@semantic-release/exec": "7.1.0",
|
|
228
227
|
"@smithy/util-stream": "4.5.16",
|
|
229
|
-
"@types/auth-header": "1.0.6",
|
|
230
228
|
"@types/aws4": "1.11.6",
|
|
231
229
|
"@types/better-sqlite3": "7.6.13",
|
|
232
230
|
"@types/breejs__later": "4.1.5",
|
package/renovate-schema.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"title": "JSON schema for Renovate 43.64.
|
|
2
|
+
"title": "JSON schema for Renovate 43.64.2 config files (https://renovatebot.com/)",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
|
-
"x-renovate-version": "43.64.
|
|
4
|
+
"x-renovate-version": "43.64.2",
|
|
5
5
|
"allowComments": true,
|
|
6
6
|
"type": "object",
|
|
7
7
|
"properties": {
|