renovate 44.67.1 → 44.68.0
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.
- package/dist/modules/datasource/apk/index.js +2 -2
- package/dist/modules/datasource/apk/index.js.map +1 -1
- package/dist/modules/datasource/docker/common.js +8 -8
- package/dist/modules/datasource/docker/common.js.map +1 -1
- package/dist/modules/datasource/docker/index.js +3 -2
- package/dist/modules/datasource/docker/index.js.map +1 -1
- package/dist/modules/manager/deno/compat.js +1 -0
- package/dist/modules/manager/deno/compat.js.map +1 -1
- package/dist/modules/manager/dockerfile/extract.js +2 -1
- package/dist/modules/manager/dockerfile/extract.js.map +1 -1
- package/dist/modules/manager/fingerprint.generated.js +3 -3
- package/dist/modules/manager/fingerprint.generated.js.map +1 -1
- package/dist/modules/manager/npm/update/locked-dependency/yarn-lock/replace.js +1 -1
- package/dist/modules/manager/npm/update/locked-dependency/yarn-lock/replace.js.map +1 -1
- package/package.json +1 -1
- package/renovate-schema.json +2 -2
|
@@ -2,7 +2,7 @@ import { logger } from "../../../logger/index.js";
|
|
|
2
2
|
import { joinUrlParts } from "../../../util/url.js";
|
|
3
3
|
import { ExternalHostError } from "../../../types/errors/external-host-error.js";
|
|
4
4
|
import { cachePathExists, createCacheWriteStream, ensureCacheDir, pipeline, rmCache } from "../../../util/fs/index.js";
|
|
5
|
-
import
|
|
5
|
+
import "../../versioning/apk/index.js";
|
|
6
6
|
import { withCache } from "../../../util/cache/package/with-cache.js";
|
|
7
7
|
import { RequestError } from "../../../util/http/got.js";
|
|
8
8
|
import "../../../util/http/index.js";
|
|
@@ -34,7 +34,7 @@ function groupPackagesByName(packages) {
|
|
|
34
34
|
}
|
|
35
35
|
var ApkDatasource = class ApkDatasource extends Datasource {
|
|
36
36
|
static id = "apk";
|
|
37
|
-
defaultVersioning =
|
|
37
|
+
defaultVersioning = "apk";
|
|
38
38
|
/**
|
|
39
39
|
* Alpine APK repositories are laid out as
|
|
40
40
|
* `{base}/{branch}/{component}/{arch}/APKINDEX.tar.gz`, and `/etc/apk/repositories`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["looseVersioning","fs.ensureCacheDir","fs.createCacheWriteStream","fs.pipeline","tarExtract","fs.cachePathExists","HttpError","fs.rmCache"],"sources":["../../../../lib/modules/datasource/apk/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { isNonEmptyObject } from '@sindresorhus/is';\nimport { extract as tarExtract } from 'tar';\nimport upath from 'upath';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport * as fs from '../../../util/fs/index.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { joinUrlParts } from '../../../util/url.ts';\nimport { id as looseVersioning } from '../../versioning/loose/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\nimport { parseApkIndexFile } from './parser.ts';\nimport type { ApkPackage } from './types.ts';\nimport { constructComponentUrls } from './url.ts';\n\nexport const apkDatasourceId = 'apk';\n\nconst defaultConfig = {\n commitMessageTopic: '{{{depName}}} APK package',\n commitMessageExtra:\n 'to {{#if isMajor}}{{{prettyNewMajor}}}{{else}}{{{prettyNewVersion}}}{{/if}}',\n};\n\n/**\n * Groups packages by name so that a lookup does not scan the whole index.\n *\n * An index holds thousands of packages, and a name can appear more than once\n * when the component serves multiple versions of it.\n */\nfunction groupPackagesByName(\n packages: ApkPackage[],\n): Record<string, ApkPackage[]> {\n const packagesByName: Record<string, ApkPackage[]> = {};\n\n for (const pkg of packages) {\n packagesByName[pkg.name] ??= [];\n packagesByName[pkg.name].push(pkg);\n }\n\n return packagesByName;\n}\n\nexport class ApkDatasource extends Datasource {\n static readonly id = apkDatasourceId;\n\n override readonly defaultVersioning = looseVersioning;\n\n /**\n * Alpine APK repositories are laid out as\n * `{base}/{branch}/{component}/{arch}/APKINDEX.tar.gz`, and `/etc/apk/repositories`\n * holds one entry per component.\n *\n * For Renovate, the path segments are encoded as query parameters so that a single\n * registry URL can cover multiple components.\n *\n * The following query parameter is required:\n * - arch: e.g. x86_64, aarch64, armv7\n *\n * The following query parameters are optional, as repositories such as Wolfi serve\n * their index directly below the repository root:\n * - branch: latest-stable, v3.19, edge or any other Alpine branch\n * - components: comma separated list of components, e.g. main,community,testing\n */\n override readonly defaultRegistryUrls = [\n 'https://dl-cdn.alpinelinux.org/alpine?branch=latest-stable&components=main&arch=x86_64',\n ];\n\n override readonly defaultConfig = defaultConfig;\n\n override readonly customRegistrySupport = true;\n\n override readonly registryStrategy = 'merge';\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `buildDate` field in the results.';\n\n constructor() {\n super(ApkDatasource.id);\n }\n\n /**\n * Gets all available packages from a single APK component, keyed by package name\n */\n private async _getPackages(\n componentUrl: string,\n ): Promise<Record<string, ApkPackage[]>> {\n logger.debug(`Fetching APK packages from ${componentUrl}`);\n\n const extractId = randomUUID();\n const cacheDir = await fs.ensureCacheDir(upath.join('apk', extractId));\n const tarFile = upath.join(cacheDir, 'APKINDEX.tar.gz');\n const extractedFile = upath.join(cacheDir, 'APKINDEX');\n\n try {\n const indexUrl = joinUrlParts(componentUrl, 'APKINDEX.tar.gz');\n logger.debug(`Attempting to download ${indexUrl}`);\n const readStream = this.http.stream(indexUrl);\n const writeStream = fs.createCacheWriteStream(tarFile);\n await fs.pipeline(readStream, writeStream);\n\n await tarExtract({\n file: tarFile,\n cwd: cacheDir,\n filter: (path) => upath.basename(path) === 'APKINDEX',\n });\n\n if (!(await fs.cachePathExists(extractedFile))) {\n logger.warn({ componentUrl }, 'APKINDEX file not found in tar archive');\n return {};\n }\n\n logger.debug('Successfully extracted APKINDEX content');\n\n let packages: ApkPackage[] = [];\n try {\n packages = await parseApkIndexFile(extractedFile);\n } catch (err) {\n logger.warn({ componentUrl, err }, 'Error parsing APK index file');\n return {};\n }\n\n logger.debug(\n { componentUrl, packageCount: packages.length },\n 'Successfully parsed APK index',\n );\n\n return groupPackagesByName(packages);\n } catch (err) {\n if (err instanceof HttpError) {\n const statusCode = err.response?.statusCode;\n if (statusCode === 429 || (statusCode && statusCode >= 500)) {\n throw new ExternalHostError(err);\n }\n // The caller logs the failure once for the component it was skipping\n throw err;\n }\n\n logger.warn(\n { componentUrl, err },\n 'Error extracting APK index from tar.gz',\n );\n return {};\n } finally {\n await fs.rmCache(cacheDir);\n }\n }\n\n private getPackages(\n componentUrl: string,\n ): Promise<Record<string, ApkPackage[]>> {\n return withCache(\n {\n namespace: `datasource-${ApkDatasource.id}`,\n key: componentUrl,\n ttlMinutes: 60,\n fallback: true,\n // Soft failures resolve to an empty index, which must not be cached as a valid one\n shouldCacheResult: isNonEmptyObject,\n },\n () => this._getPackages(componentUrl),\n );\n }\n\n /**\n * Gets releases for a specific package from APK repositories\n */\n async getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore if -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n logger.debug(`Getting APK releases for ${packageName} from ${registryUrl}`);\n\n const componentUrls = constructComponentUrls(registryUrl);\n let result: ReleaseResult | null = null;\n // A package can be served by more than one component, so the same version\n // must not be reported twice\n const seenVersions = new Set<string>();\n\n for (const componentUrl of componentUrls) {\n try {\n const packages = await this.getPackages(componentUrl);\n const matchingPackages = packages[packageName];\n\n if (!matchingPackages) {\n logger.debug(\n { packageName, componentUrl },\n 'No matching packages found',\n );\n continue;\n }\n\n const releases: Release[] = [];\n for (const pkg of matchingPackages) {\n if (seenVersions.has(pkg.version)) {\n continue;\n }\n seenVersions.add(pkg.version);\n releases.push({\n version: pkg.version,\n releaseTimestamp: pkg.buildDate\n ? asTimestamp(pkg.buildDate * 1000)\n : undefined,\n });\n }\n\n logger.trace(\n {\n packageName,\n componentUrl,\n releaseCount: releases.length,\n releases,\n },\n 'Found APK releases',\n );\n\n result ??= { releases: [], registryUrl };\n result.homepage ??= matchingPackages.find((pkg) => pkg.url)?.url;\n result.releases.push(...releases);\n } catch (err) {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n { packageName, componentUrl, err },\n 'Skipping APK component due to an error',\n );\n }\n }\n\n return result;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["fs.ensureCacheDir","fs.createCacheWriteStream","fs.pipeline","tarExtract","fs.cachePathExists","HttpError","fs.rmCache"],"sources":["../../../../lib/modules/datasource/apk/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { isNonEmptyObject } from '@sindresorhus/is';\nimport { extract as tarExtract } from 'tar';\nimport upath from 'upath';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport * as fs from '../../../util/fs/index.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { joinUrlParts } from '../../../util/url.ts';\nimport { id as apkVersioning } from '../../versioning/apk/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\nimport { parseApkIndexFile } from './parser.ts';\nimport type { ApkPackage } from './types.ts';\nimport { constructComponentUrls } from './url.ts';\n\nexport const apkDatasourceId = 'apk';\n\nconst defaultConfig = {\n commitMessageTopic: '{{{depName}}} APK package',\n commitMessageExtra:\n 'to {{#if isMajor}}{{{prettyNewMajor}}}{{else}}{{{prettyNewVersion}}}{{/if}}',\n};\n\n/**\n * Groups packages by name so that a lookup does not scan the whole index.\n *\n * An index holds thousands of packages, and a name can appear more than once\n * when the component serves multiple versions of it.\n */\nfunction groupPackagesByName(\n packages: ApkPackage[],\n): Record<string, ApkPackage[]> {\n const packagesByName: Record<string, ApkPackage[]> = {};\n\n for (const pkg of packages) {\n packagesByName[pkg.name] ??= [];\n packagesByName[pkg.name].push(pkg);\n }\n\n return packagesByName;\n}\n\nexport class ApkDatasource extends Datasource {\n static readonly id = apkDatasourceId;\n\n override readonly defaultVersioning = apkVersioning;\n\n /**\n * Alpine APK repositories are laid out as\n * `{base}/{branch}/{component}/{arch}/APKINDEX.tar.gz`, and `/etc/apk/repositories`\n * holds one entry per component.\n *\n * For Renovate, the path segments are encoded as query parameters so that a single\n * registry URL can cover multiple components.\n *\n * The following query parameter is required:\n * - arch: e.g. x86_64, aarch64, armv7\n *\n * The following query parameters are optional, as repositories such as Wolfi serve\n * their index directly below the repository root:\n * - branch: latest-stable, v3.19, edge or any other Alpine branch\n * - components: comma separated list of components, e.g. main,community,testing\n */\n override readonly defaultRegistryUrls = [\n 'https://dl-cdn.alpinelinux.org/alpine?branch=latest-stable&components=main&arch=x86_64',\n ];\n\n override readonly defaultConfig = defaultConfig;\n\n override readonly customRegistrySupport = true;\n\n override readonly registryStrategy = 'merge';\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `buildDate` field in the results.';\n\n constructor() {\n super(ApkDatasource.id);\n }\n\n /**\n * Gets all available packages from a single APK component, keyed by package name\n */\n private async _getPackages(\n componentUrl: string,\n ): Promise<Record<string, ApkPackage[]>> {\n logger.debug(`Fetching APK packages from ${componentUrl}`);\n\n const extractId = randomUUID();\n const cacheDir = await fs.ensureCacheDir(upath.join('apk', extractId));\n const tarFile = upath.join(cacheDir, 'APKINDEX.tar.gz');\n const extractedFile = upath.join(cacheDir, 'APKINDEX');\n\n try {\n const indexUrl = joinUrlParts(componentUrl, 'APKINDEX.tar.gz');\n logger.debug(`Attempting to download ${indexUrl}`);\n const readStream = this.http.stream(indexUrl);\n const writeStream = fs.createCacheWriteStream(tarFile);\n await fs.pipeline(readStream, writeStream);\n\n await tarExtract({\n file: tarFile,\n cwd: cacheDir,\n filter: (path) => upath.basename(path) === 'APKINDEX',\n });\n\n if (!(await fs.cachePathExists(extractedFile))) {\n logger.warn({ componentUrl }, 'APKINDEX file not found in tar archive');\n return {};\n }\n\n logger.debug('Successfully extracted APKINDEX content');\n\n let packages: ApkPackage[] = [];\n try {\n packages = await parseApkIndexFile(extractedFile);\n } catch (err) {\n logger.warn({ componentUrl, err }, 'Error parsing APK index file');\n return {};\n }\n\n logger.debug(\n { componentUrl, packageCount: packages.length },\n 'Successfully parsed APK index',\n );\n\n return groupPackagesByName(packages);\n } catch (err) {\n if (err instanceof HttpError) {\n const statusCode = err.response?.statusCode;\n if (statusCode === 429 || (statusCode && statusCode >= 500)) {\n throw new ExternalHostError(err);\n }\n // The caller logs the failure once for the component it was skipping\n throw err;\n }\n\n logger.warn(\n { componentUrl, err },\n 'Error extracting APK index from tar.gz',\n );\n return {};\n } finally {\n await fs.rmCache(cacheDir);\n }\n }\n\n private getPackages(\n componentUrl: string,\n ): Promise<Record<string, ApkPackage[]>> {\n return withCache(\n {\n namespace: `datasource-${ApkDatasource.id}`,\n key: componentUrl,\n ttlMinutes: 60,\n fallback: true,\n // Soft failures resolve to an empty index, which must not be cached as a valid one\n shouldCacheResult: isNonEmptyObject,\n },\n () => this._getPackages(componentUrl),\n );\n }\n\n /**\n * Gets releases for a specific package from APK repositories\n */\n async getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore if -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n logger.debug(`Getting APK releases for ${packageName} from ${registryUrl}`);\n\n const componentUrls = constructComponentUrls(registryUrl);\n let result: ReleaseResult | null = null;\n // A package can be served by more than one component, so the same version\n // must not be reported twice\n const seenVersions = new Set<string>();\n\n for (const componentUrl of componentUrls) {\n try {\n const packages = await this.getPackages(componentUrl);\n const matchingPackages = packages[packageName];\n\n if (!matchingPackages) {\n logger.debug(\n { packageName, componentUrl },\n 'No matching packages found',\n );\n continue;\n }\n\n const releases: Release[] = [];\n for (const pkg of matchingPackages) {\n if (seenVersions.has(pkg.version)) {\n continue;\n }\n seenVersions.add(pkg.version);\n releases.push({\n version: pkg.version,\n releaseTimestamp: pkg.buildDate\n ? asTimestamp(pkg.buildDate * 1000)\n : undefined,\n });\n }\n\n logger.trace(\n {\n packageName,\n componentUrl,\n releaseCount: releases.length,\n releases,\n },\n 'Found APK releases',\n );\n\n result ??= { releases: [], registryUrl };\n result.homepage ??= matchingPackages.find((pkg) => pkg.url)?.url;\n result.releases.push(...releases);\n } catch (err) {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n { packageName, componentUrl, err },\n 'Skipping APK component due to an error',\n );\n }\n }\n\n return result;\n }\n}\n"],"mappings":"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"}
|
|
@@ -53,7 +53,7 @@ async function getAuthHeaders(http, registryHost, dockerRepository, apiCheckUrl
|
|
|
53
53
|
apiCheckUrl,
|
|
54
54
|
res: apiCheckResponse
|
|
55
55
|
}, "Invalid registry response");
|
|
56
|
-
return
|
|
56
|
+
return;
|
|
57
57
|
}
|
|
58
58
|
const rule = find({
|
|
59
59
|
hostType: dockerDatasourceId,
|
|
@@ -105,7 +105,7 @@ async function getAuthHeaders(http, registryHost, dockerRepository, apiCheckUrl
|
|
|
105
105
|
dockerRepository,
|
|
106
106
|
authenticateHeader
|
|
107
107
|
}, `Invalid realm, testing direct auth`);
|
|
108
|
-
return opts.headers ??
|
|
108
|
+
return opts.headers ?? void 0;
|
|
109
109
|
}
|
|
110
110
|
const authUrl = parseUrl(`${authenticateHeader.params.realm}`);
|
|
111
111
|
if (isString(authenticateHeader.params.scope) && !apiCheckUrl.endsWith("/v2/")) authUrl.searchParams.append("scope", authenticateHeader.params.scope);
|
|
@@ -123,13 +123,13 @@ async function getAuthHeaders(http, registryHost, dockerRepository, apiCheckUrl
|
|
|
123
123
|
/* v8 ignore next -- TODO: add test */
|
|
124
124
|
if (!token) {
|
|
125
125
|
logger.warn("Failed to obtain docker registry token");
|
|
126
|
-
return
|
|
126
|
+
return;
|
|
127
127
|
}
|
|
128
128
|
addSecretForSanitizing(token);
|
|
129
129
|
return { authorization: `Bearer ${token}` };
|
|
130
130
|
} catch (err) /* istanbul ignore next */ {
|
|
131
131
|
/* v8 ignore if -- quay.io errors are swallowed pending #9604, not reproduced in specs */
|
|
132
|
-
if (err.host === "quay.io") return
|
|
132
|
+
if (err.host === "quay.io") return;
|
|
133
133
|
/* v8 ignore if -- registry auth rejection is logged and swallowed, not mocked in specs */
|
|
134
134
|
if (err.statusCode === 401) {
|
|
135
135
|
logger.debug({
|
|
@@ -137,7 +137,7 @@ async function getAuthHeaders(http, registryHost, dockerRepository, apiCheckUrl
|
|
|
137
137
|
dockerRepository
|
|
138
138
|
}, "Unauthorized docker lookup");
|
|
139
139
|
logger.debug({ err });
|
|
140
|
-
return
|
|
140
|
+
return;
|
|
141
141
|
}
|
|
142
142
|
/* v8 ignore if -- registry permission rejection is logged and swallowed, not mocked in specs */
|
|
143
143
|
if (err.statusCode === 403) {
|
|
@@ -146,7 +146,7 @@ async function getAuthHeaders(http, registryHost, dockerRepository, apiCheckUrl
|
|
|
146
146
|
dockerRepository
|
|
147
147
|
}, "Not allowed to access docker registry");
|
|
148
148
|
logger.debug({ err });
|
|
149
|
-
return
|
|
149
|
+
return;
|
|
150
150
|
}
|
|
151
151
|
if (err.name === "RequestError" && isDockerHost(registryHost)) throw new ExternalHostError(err);
|
|
152
152
|
/* v8 ignore if -- Docker Hub rate limiting maps to ExternalHostError, not mocked in specs */
|
|
@@ -161,14 +161,14 @@ async function getAuthHeaders(http, registryHost, dockerRepository, apiCheckUrl
|
|
|
161
161
|
dockerRepository,
|
|
162
162
|
err
|
|
163
163
|
}, "Host disabled");
|
|
164
|
-
return
|
|
164
|
+
return;
|
|
165
165
|
}
|
|
166
166
|
logger.warn({
|
|
167
167
|
registryHost,
|
|
168
168
|
dockerRepository,
|
|
169
169
|
err
|
|
170
170
|
}, "Error obtaining docker token");
|
|
171
|
-
return
|
|
171
|
+
return;
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
function getRegistryRepository(packageName, registryUrl) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","names":["hostRules.find","dockerVersioning"],"sources":["../../../../lib/modules/datasource/docker/common.ts"],"sourcesContent":["import { isNonEmptyString, isString, isUndefined } 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 { coerceObject } from '../../../util/object.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, isECRMaxResultsResponse } from './ecr.ts';\nimport { googleRegex } from './google.ts';\nimport type { OciHelmConfig } from './schema.ts';\nimport { RegistryAuthToken } 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 // Some ECR-compatible private registries (e.g. corporate Docker proxies) reject\n // n>1000 with 405 even on the auth-probe request. Fall back to probing the base\n // /v2/ endpoint so getAuthHeaders can still obtain a valid token; the main fetch\n // loop already retries with n=1000 when it encounters this same error.\n if (isECRMaxResultsResponse(apiCheckResponse)) {\n logger.debug(\n { apiCheckUrl },\n 'Registry rejected n>1000 on auth probe; retrying auth check via base /v2/ endpoint',\n );\n return getAuthHeaders(http, registryHost, dockerRepository);\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 isUndefined(rule.username) &&\n isUndefined(rule.password) &&\n isUndefined(rule.token)\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 // already guarded by above clause\n const authUrl = parseUrl(`${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.getJson(authUrl.href, opts, RegistryAuthToken)\n ).body;\n\n const token = authResponse.token ?? authResponse.access_token;\n /* v8 ignore next -- 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 -- quay.io errors are swallowed pending #9604, not reproduced in specs */\n if (err.host === 'quay.io') {\n // TODO: debug why quay throws errors (#9604)\n return null;\n }\n /* v8 ignore if -- registry auth rejection is logged and swallowed, not mocked in specs */\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 -- registry permission rejection is logged and swallowed, not mocked in specs */\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 -- Docker Hub rate limiting maps to ExternalHostError, not mocked in specs */\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n /* v8 ignore if -- registry server errors map to ExternalHostError, not mocked in specs */\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 -- hostRules-disabled host is swallowed silently, not mocked in specs */\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 parsedFullUrl = parseUrl(fullUrl);\n if (!parsedFullUrl) {\n return { registryHost, dockerRepository };\n }\n registryHost = parsedFullUrl.origin;\n dockerRepository = parsedFullUrl.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 } = coerceObject(\n regEx(/^(?<base>https:\\/\\/[^/]+)\\/(?<path>.+)$/).exec(registryHost)?.groups,\n );\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, isUndefined } 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 { coerceObject } from '../../../util/object.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, isECRMaxResultsResponse } from './ecr.ts';\nimport { googleRegex } from './google.ts';\nimport type { OciHelmConfig } from './schema.ts';\nimport { RegistryAuthToken } 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 | undefined> {\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 // Some ECR-compatible private registries (e.g. corporate Docker proxies) reject\n // n>1000 with 405 even on the auth-probe request. Fall back to probing the base\n // /v2/ endpoint so getAuthHeaders can still obtain a valid token; the main fetch\n // loop already retries with n=1000 when it encounters this same error.\n if (isECRMaxResultsResponse(apiCheckResponse)) {\n logger.debug(\n { apiCheckUrl },\n 'Registry rejected n>1000 on auth probe; retrying auth check via base /v2/ endpoint',\n );\n return getAuthHeaders(http, registryHost, dockerRepository);\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 undefined;\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 isUndefined(rule.username) &&\n isUndefined(rule.password) &&\n isUndefined(rule.token)\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 ?? undefined;\n }\n\n // already guarded by above clause\n const authUrl = parseUrl(`${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.getJson(authUrl.href, opts, RegistryAuthToken)\n ).body;\n\n const token = authResponse.token ?? authResponse.access_token;\n /* v8 ignore next -- TODO: add test */\n if (!token) {\n logger.warn('Failed to obtain docker registry token');\n return undefined;\n }\n // sanitize token\n addSecretForSanitizing(token);\n return {\n authorization: `Bearer ${token}`,\n };\n } catch (err) /* istanbul ignore next */ {\n /* v8 ignore if -- quay.io errors are swallowed pending #9604, not reproduced in specs */\n if (err.host === 'quay.io') {\n // TODO: debug why quay throws errors (#9604)\n return undefined;\n }\n /* v8 ignore if -- registry auth rejection is logged and swallowed, not mocked in specs */\n if (err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Unauthorized docker lookup',\n );\n logger.debug({ err });\n return undefined;\n }\n /* v8 ignore if -- registry permission rejection is logged and swallowed, not mocked in specs */\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 undefined;\n }\n if (err.name === 'RequestError' && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n /* v8 ignore if -- Docker Hub rate limiting maps to ExternalHostError, not mocked in specs */\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n /* v8 ignore if -- registry server errors map to ExternalHostError, not mocked in specs */\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 -- hostRules-disabled host is swallowed silently, not mocked in specs */\n if (err.message === HOST_DISABLED) {\n logger.trace({ registryHost, dockerRepository, err }, 'Host disabled');\n return undefined;\n }\n logger.warn(\n { registryHost, dockerRepository, err },\n 'Error obtaining docker token',\n );\n return undefined;\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 parsedFullUrl = parseUrl(fullUrl);\n if (!parsedFullUrl) {\n return { registryHost, dockerRepository };\n }\n registryHost = parsedFullUrl.origin;\n dockerRepository = parsedFullUrl.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 } = coerceObject(\n regEx(/^(?<base>https:\\/\\/[^/]+)\\/(?<path>.+)$/).exec(registryHost)?.groups,\n );\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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"}
|
|
@@ -364,7 +364,7 @@ var DockerDatasource = class DockerDatasource extends Datasource {
|
|
|
364
364
|
const headers = await getAuthHeaders(this.http, registryHost, dockerRepository, url);
|
|
365
365
|
if (!headers) {
|
|
366
366
|
logger.debug("Failed to get authHeaders for getTags lookup");
|
|
367
|
-
return
|
|
367
|
+
return;
|
|
368
368
|
}
|
|
369
369
|
let page = 0;
|
|
370
370
|
const pages = [
|
|
@@ -482,7 +482,8 @@ var DockerDatasource = class DockerDatasource extends Datasource {
|
|
|
482
482
|
getTags(registryHost, dockerRepository) {
|
|
483
483
|
return withCache({
|
|
484
484
|
namespace: "datasource-docker-tags",
|
|
485
|
-
key: `${registryHost}:${dockerRepository}
|
|
485
|
+
key: `${registryHost}:${dockerRepository}`,
|
|
486
|
+
cacheable: registryHost === DOCKER_HUB
|
|
486
487
|
}, () => this._getTags(registryHost, dockerRepository));
|
|
487
488
|
}
|
|
488
489
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["dockerVersioningId","HttpError"],"sources":["../../../../lib/modules/datasource/docker/index.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { PAGE_NOT_FOUND_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { hasKey } from '../../../util/object.ts';\nimport { type AsyncResult, Result } from '../../../util/result.ts';\nimport { isDockerDigest } from '../../../util/string-match.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport {\n ensurePathPrefix,\n joinUrlParts,\n parseLinkHeader,\n parseUrl,\n} from '../../../util/url.ts';\nimport { id as dockerVersioningId } from '../../versioning/docker/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type {\n DigestConfig,\n GetReleasesConfig,\n Release,\n ReleaseResult,\n} from '../types.ts';\nimport {\n isArtifactoryServer,\n isCrossOriginPaginationAllowed,\n resolvePaginationUrl,\n} from '../util.ts';\nimport {\n DOCKER_HUB,\n dockerDatasourceId,\n extractDigestFromResponseBody,\n findHelmSourceUrl,\n findLatestStable,\n getAuthHeaders,\n getRegistryRepository,\n gitRefLabel,\n imageUrlLabel,\n isDockerHost,\n sourceLabel,\n sourceLabels,\n} from './common.ts';\nimport { DockerHubCache } from './dockerhub-cache.ts';\nimport { ecrPublicRegex, ecrRegex, isECRMaxResultsError } from './ecr.ts';\nimport type {\n DistributionManifest,\n Manifest,\n OciImageManifest,\n} from './schema.ts';\nimport {\n DockerHubTagsPage,\n ManifestJson,\n OciHelmConfig,\n OciImageConfig,\n QuayTagsResponse,\n RegistryTagsList,\n} from './schema.ts';\n\nconst defaultConfig = {\n commitMessageTopic: '{{{depName}}} Docker tag',\n commitMessageExtra:\n 'to {{#if isPinDigest}}{{{newDigestShort}}}{{else}}{{#if isMajor}}{{{prettyNewMajor}}}{{else}}{{{prettyNewVersion}}}{{/if}}{{/if}}',\n digest: {\n branchTopic: '{{{depNameSanitized}}}-{{{currentValue}}}',\n commitMessageExtra: 'to {{newDigestShort}}',\n commitMessageTopic:\n '{{{depName}}}{{#if currentValue}}:{{{currentValue}}}{{/if}} Docker digest',\n group: {\n commitMessageTopic: '{{{groupName}}}',\n commitMessageExtra: '',\n },\n },\n pin: {\n commitMessageExtra: '',\n groupName: 'Docker digests',\n group: {\n commitMessageTopic: '{{{groupName}}}',\n branchTopic: 'digests-pin',\n },\n },\n};\n\nexport class DockerDatasource extends Datasource {\n static readonly id = dockerDatasourceId;\n\n override readonly defaultVersioning = dockerVersioningId;\n\n override readonly defaultRegistryUrls = [DOCKER_HUB];\n\n override readonly defaultConfig = defaultConfig;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'Only supported on Docker Hub: The release timestamp is determined from the `tag_last_pushed` field in the results. **NOTE**: Currently, digests will receive the same release timestamp as the `tag_last_pushed`, which means that digests may appear newer than they are - see https://github.com/renovatebot/renovate/issues/38659';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `org.opencontainers.image.source` and `org.label-schema.vcs-url` labels present in the metadata of the **latest stable** image found on the Docker registry.';\n\n constructor() {\n super(DockerDatasource.id);\n }\n\n // TODO: debug why quay throws errors (#9612)\n private async getManifestResponse(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n mode: 'head' | 'getText' = 'getText',\n ): Promise<HttpResponse | null> {\n logger.debug(\n `getManifestResponse(${registryHost}, ${dockerRepository}, ${tag}, ${mode})`,\n );\n try {\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return null;\n }\n headers.accept = [\n 'application/vnd.docker.distribution.manifest.list.v2+json',\n 'application/vnd.docker.distribution.manifest.v2+json',\n 'application/vnd.oci.image.manifest.v1+json',\n 'application/vnd.oci.image.index.v1+json',\n ].join(', ');\n const url = `${registryHost}/v2/${dockerRepository}/manifests/${tag}`;\n const manifestResponse = await this.http[mode](url, {\n headers,\n noAuth: true,\n cacheProvider: memCacheProvider,\n });\n return manifestResponse;\n } catch (err) /* istanbul ignore next */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\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 if (err.statusCode === 404) {\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Docker Manifest is unknown',\n );\n return null;\n }\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n if (err.statusCode >= 500 && err.statusCode < 600) {\n throw new ExternalHostError(err);\n }\n if (err.code === 'ETIMEDOUT') {\n logger.debug(\n { registryHost },\n 'Timeout when attempting to connect to docker registry',\n );\n logger.debug({ err });\n return null;\n }\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Unknown Error looking up docker manifest',\n );\n return null;\n }\n }\n\n private async _getImageConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciImageConfig> | undefined> {\n logger.trace(\n `getImageConfig(${registryHost}, ${dockerRepository}, ${configDigest})`,\n );\n\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n /* v8 ignore next -- should never happen */\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return undefined;\n }\n const url = joinUrlParts(\n registryHost,\n 'v2',\n dockerRepository,\n 'blobs',\n configDigest,\n );\n return await this.http.getJson(\n url,\n {\n headers,\n noAuth: true,\n },\n OciImageConfig,\n );\n }\n\n getImageConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciImageConfig> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-imageconfig',\n key: `${registryHost}:${dockerRepository}@${configDigest}`,\n ttlMinutes: 1440 * 28,\n },\n () => this._getImageConfig(registryHost, dockerRepository, configDigest),\n );\n }\n\n private async _getHelmConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciHelmConfig> | undefined> {\n logger.trace(\n `getImageConfig(${registryHost}, ${dockerRepository}, ${configDigest})`,\n );\n\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n /* v8 ignore next -- should never happen */\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return undefined;\n }\n const url = joinUrlParts(\n registryHost,\n 'v2',\n dockerRepository,\n 'blobs',\n configDigest,\n );\n return await this.http.getJson(\n url,\n {\n headers,\n noAuth: true,\n },\n OciHelmConfig,\n );\n }\n\n getHelmConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciHelmConfig> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-imageconfig',\n key: `${registryHost}:${dockerRepository}@${configDigest}`,\n ttlMinutes: 1440 * 28,\n },\n () => this._getHelmConfig(registryHost, dockerRepository, configDigest),\n );\n }\n\n private async getConfigDigest(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<string | null> {\n return (\n (await this.getManifest(registry, dockerRepository, tag))?.config\n ?.digest ?? null\n );\n }\n\n private async getManifestDocument(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Manifest | null> {\n const manifestResponse = await this.getManifestResponse(\n registry,\n dockerRepository,\n tag,\n );\n\n // If getting the manifest fails here, then abort\n // This means that the latest tag doesn't have a manifest, which shouldn't\n // be possible\n /* v8 ignore next -- should never happen */\n if (!manifestResponse) {\n return null;\n }\n\n // Softfail on invalid manifests\n const parsed = ManifestJson.safeParse(manifestResponse.body);\n if (!parsed.success) {\n logger.debug(\n {\n registry,\n dockerRepository,\n tag,\n body: manifestResponse.body,\n headers: manifestResponse.headers,\n err: parsed.error,\n },\n 'Invalid manifest response',\n );\n return null;\n }\n\n return parsed.data;\n }\n\n private async resolveImageManifest(\n registry: string,\n dockerRepository: string,\n tag: string,\n manifest: Manifest,\n ): Promise<OciImageManifest | DistributionManifest | null> {\n switch (manifest.mediaType) {\n case 'application/vnd.docker.distribution.manifest.v2+json':\n case 'application/vnd.oci.image.manifest.v1+json':\n return manifest;\n case 'application/vnd.docker.distribution.manifest.list.v2+json':\n case 'application/vnd.oci.image.index.v1+json':\n if (!manifest.manifests.length) {\n logger.debug(\n { manifest },\n 'Invalid manifest list with no manifests - returning',\n );\n return null;\n }\n logger.trace(\n { registry, dockerRepository, tag },\n 'Found manifest list, using first image',\n );\n return this.getManifest(\n registry,\n dockerRepository,\n manifest.manifests[0].digest,\n );\n // istanbul ignore next: can't happen\n default:\n return null;\n }\n }\n\n private async getManifest(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<OciImageManifest | DistributionManifest | null> {\n const manifest = await this.getManifestDocument(\n registry,\n dockerRepository,\n tag,\n );\n if (!manifest) {\n return null;\n }\n return this.resolveImageManifest(registry, dockerRepository, tag, manifest);\n }\n\n private async _getImageArchitecture(\n registryHost: string,\n dockerRepository: string,\n currentDigest: string,\n ): Promise<string | null | undefined> {\n try {\n let manifestResponse: HttpResponse | null;\n\n try {\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n currentDigest,\n 'head',\n );\n } catch (_err) {\n const err =\n _err instanceof ExternalHostError\n ? _err.err\n : /* istanbul ignore next: can never happen */ _err;\n\n if (\n typeof err.statusCode === 'number' &&\n err.statusCode >= 500 &&\n err.statusCode < 600\n ) {\n // querying the digest manifest for a non existent image leads to a 500 statusCode\n return null;\n }\n\n /* istanbul ignore next */\n throw _err;\n }\n\n if (\n manifestResponse?.headers['content-type'] !==\n 'application/vnd.docker.distribution.manifest.v2+json' &&\n manifestResponse?.headers['content-type'] !==\n 'application/vnd.oci.image.manifest.v1+json'\n ) {\n return null;\n }\n\n const configDigest = await this.getConfigDigest(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n if (!configDigest) {\n return null;\n }\n\n const configResponse = await this.getImageConfig(\n registryHost,\n dockerRepository,\n configDigest,\n );\n\n // TODO: fix me, architecture is required in spec\n if (\n configResponse &&\n ('config' in configResponse.body ||\n 'architecture' in configResponse.body)\n ) {\n const architecture = configResponse.body.architecture ?? null;\n logger.debug(\n `Current digest ${currentDigest} relates to architecture ${\n architecture ?? 'null'\n }`,\n );\n\n return architecture;\n }\n } catch (err) /* istanbul ignore next */ {\n if (err.statusCode !== 404 || err.message === PAGE_NOT_FOUND_ERROR) {\n throw err;\n }\n logger.debug(\n { registryHost, dockerRepository, currentDigest, err },\n 'Unknown error getting image architecture',\n );\n }\n\n return undefined;\n }\n\n getImageArchitecture(\n registryHost: string,\n dockerRepository: string,\n currentDigest: string,\n ): Promise<string | null | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-architecture',\n key: `${registryHost}:${dockerRepository}@${currentDigest}`,\n ttlMinutes: 1440 * 28,\n shouldCacheResult: isNonEmptyString,\n },\n () =>\n this._getImageArchitecture(\n registryHost,\n dockerRepository,\n currentDigest,\n ),\n );\n }\n\n /*\n * docker.getLabels\n *\n * This function will:\n * - Return the labels for the requested image\n */\n private async _getLabels(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Record<string, string> | undefined> {\n logger.debug(`getLabels(${registryHost}, ${dockerRepository}, ${tag})`);\n // Skip Docker Hub image if RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP is set\n if (\n getEnv().RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP &&\n registryHost === DOCKER_HUB\n ) {\n logger.debug(\n 'Docker Hub image - skipping label lookup due to RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP',\n );\n return {};\n }\n try {\n let labels: Record<string, string> | undefined = {};\n const manifestDocument = await this.getManifestDocument(\n registryHost,\n dockerRepository,\n tag,\n );\n\n if (!manifestDocument) {\n logger.debug(\n { registryHost, dockerRepository, tag },\n 'No manifest found',\n );\n return undefined;\n }\n\n if ('annotations' in manifestDocument && manifestDocument.annotations) {\n labels = manifestDocument.annotations;\n }\n\n if ('manifests' in manifestDocument) {\n const descriptorAnnotations = manifestDocument.manifests\n .map((descriptor) => descriptor.annotations)\n .find(\n (annotations) =>\n isNonEmptyString(annotations?.[sourceLabel]) &&\n isNonEmptyString(annotations?.[gitRefLabel]),\n );\n if (descriptorAnnotations) {\n labels = { ...labels, ...descriptorAnnotations };\n }\n }\n\n if (\n 'manifests' in manifestDocument &&\n labels[sourceLabel] &&\n labels[gitRefLabel]\n ) {\n return labels;\n }\n\n const manifest = await this.resolveImageManifest(\n registryHost,\n dockerRepository,\n tag,\n manifestDocument,\n );\n if (!manifest) {\n return undefined;\n }\n\n if ('annotations' in manifest && manifest.annotations) {\n labels = { ...labels, ...manifest.annotations };\n }\n\n switch (manifest.config.mediaType) {\n case 'application/vnd.cncf.helm.config.v1+json': {\n if (labels[sourceLabel]) {\n // we already have the source url, so no need to pull the config\n return labels;\n }\n const configResponse = await this.getHelmConfig(\n registryHost,\n dockerRepository,\n manifest.config.digest,\n );\n\n if (configResponse) {\n // Helm chart\n const url = findHelmSourceUrl(configResponse.body);\n if (url) {\n labels[sourceLabel] = url;\n }\n }\n break;\n }\n case 'application/vnd.oci.image.config.v1+json':\n case 'application/vnd.docker.container.image.v1+json': {\n if (labels[sourceLabel] && labels[gitRefLabel]) {\n // we already have the source url, so no need to pull the config\n return labels;\n }\n const configResponse = await this.getImageConfig(\n registryHost,\n dockerRepository,\n manifest.config.digest,\n );\n\n /* v8 ignore next -- should never happen */\n if (!configResponse) {\n return labels;\n }\n\n const body = configResponse.body;\n if (body.config) {\n labels = { ...labels, ...body.config.Labels };\n } else {\n logger.debug(\n { headers: configResponse.headers, body },\n `manifest blob response body missing the \"config\" property`,\n );\n }\n break;\n }\n }\n\n if (labels) {\n logger.debug(\n {\n labels,\n },\n 'found labels in manifest',\n );\n }\n return labels;\n } catch (err) /* istanbul ignore next: should be tested in future */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (err.statusCode === 400 || err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository, err },\n 'Unauthorized docker lookup',\n );\n } else if (err.statusCode === 404) {\n logger.warn(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Config Manifest is unknown',\n );\n } else if (err.statusCode === 429 && isDockerHost(registryHost)) {\n logger.warn({ err }, 'docker registry failure: too many requests');\n } else if (err.statusCode >= 500 && err.statusCode < 600) {\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'docker registry failure: internal error',\n );\n } else if (\n err.code === 'ERR_TLS_CERT_ALTNAME_INVALID' ||\n err.code === 'ETIMEDOUT'\n ) {\n logger.debug(\n { registryHost, err },\n 'Error connecting to docker registry',\n );\n } else if (registryHost === 'https://quay.io') {\n // istanbul ignore next\n logger.debug(\n 'Ignoring quay.io errors until they fully support v2 schema',\n );\n } else {\n logger.info(\n { registryHost, dockerRepository, tag, err },\n 'Unknown error getting Docker labels',\n );\n }\n return {};\n }\n }\n\n getLabels(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Record<string, string> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-labels',\n key: `${registryHost}:${dockerRepository}:${tag}`,\n ttlMinutes: 24 * 60,\n },\n () => this._getLabels(registryHost, dockerRepository, tag),\n );\n }\n\n private async getTagsQuayRegistry(\n registry: string,\n repository: string,\n ): Promise<string[]> {\n let tags: string[] = [];\n const limit = 100;\n\n function pageUrl(page: number): string {\n return `${registry}/api/v1/repository/${repository}/tag/?limit=${limit}&page=${page}&onlyActiveTags=true`;\n }\n\n let page = 1;\n let url: string | null = pageUrl(page);\n while (url && page <= 20) {\n const res: HttpResponse<QuayTagsResponse> = await this.http.getJson(\n url,\n QuayTagsResponse,\n );\n const pageTags = res.body.tags.map((tag) => tag.name);\n tags = tags.concat(pageTags);\n page += 1;\n url = res.body.has_additional ? pageUrl(page) : null;\n }\n return tags;\n }\n\n private async getDockerApiTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | null> {\n let tags: string[] = [];\n // AWS ECR limits the maximum number of results to 1000\n // See https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeRepositories.html#ECR-DescribeRepositories-request-maxResults\n // See https://docs.aws.amazon.com/AmazonECRPublic/latest/APIReference/API_DescribeRepositories.html#ecrpublic-DescribeRepositories-request-maxResults\n const limit =\n ecrRegex.test(registryHost) || ecrPublicRegex.test(registryHost)\n ? 1000\n : 10000;\n let url: string | null =\n `${registryHost}/${dockerRepository}/tags/list?n=${limit}`;\n url = ensurePathPrefix(url, '/v2');\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n url,\n );\n if (!headers) {\n logger.debug('Failed to get authHeaders for getTags lookup');\n return null;\n }\n let page = 0;\n const hostsNeedingAllPages = [\n 'https://ghcr.io', // GHCR sorts from oldest to newest, so we need to get all pages\n 'https://quay.io', // Quay sorts from oldest to newest, so we need to get all pages\n 'https://cgr.dev', // Chainguard sorts lexically and publishes a tag per build, so current versions sort past the page limit\n ];\n const pages = hostsNeedingAllPages.includes(registryHost)\n ? 1000\n : GlobalConfig.get('dockerMaxPages');\n logger.trace({ registryHost, dockerRepository, pages }, 'docker.getTags');\n const allowCrossOrigin = isCrossOriginPaginationAllowed(dockerDatasourceId);\n let foundMaxResultsError = false;\n do {\n let res: HttpResponse<RegistryTagsList>;\n try {\n res = await this.http.getJson(\n url,\n { headers, noAuth: true },\n RegistryTagsList,\n );\n } catch (err) {\n if (\n !foundMaxResultsError &&\n err instanceof HttpError &&\n isECRMaxResultsError(err)\n ) {\n const maxResults = 1000;\n url = `${registryHost}/${dockerRepository}/tags/list?n=${maxResults}`;\n url = ensurePathPrefix(url, '/v2');\n foundMaxResultsError = true;\n continue;\n }\n throw err;\n }\n tags = tags.concat(res.body.tags);\n const linkHeader = parseLinkHeader(res.headers.link);\n if (isArtifactoryServer(res)) {\n // Artifactory bug: next link comes back without virtual-repo prefix (RTFACT-18971)\n if (linkHeader?.next?.last) {\n // parse the current URL, strip any old \"last\" param, then set the new one\n const parsed = parseUrl(url);\n // v8 ignore if: url is always a valid HTTP URL as `ensurePathPrefix`\n if (!parsed) {\n url = null;\n break;\n }\n parsed.searchParams.delete('last');\n parsed.searchParams.set('last', linkHeader.next.last);\n url = parsed.href;\n } else {\n url = null;\n }\n } else if (linkHeader?.next?.url) {\n // Resolve the relative-or-absolute next link, not following cross-origin requests unless explicitly opted in\n const nextUrl = resolvePaginationUrl(\n url,\n linkHeader.next.url,\n allowCrossOrigin,\n );\n if (!nextUrl) {\n // make sure that users are aware if there are any (potentially malicious, or misconfigured) pagination links being returned\n logger.once.warn(\n { registryHost, nextUrl: linkHeader.next.url },\n 'Ignoring cross-origin or invalid Docker registry tags pagination link',\n );\n }\n url = nextUrl;\n } else {\n url = null;\n }\n page += 1;\n } while (url && page < pages);\n return tags;\n }\n\n private async _getTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | null> {\n try {\n const isQuay = registryHost === 'https://quay.io';\n let tags: string[] | null;\n if (isQuay) {\n try {\n // Due to pagination and sorting limits on Quay Docker v2 API implementation we try the Quay v1 API first\n tags = await this.getTagsQuayRegistry(registryHost, dockerRepository);\n } catch (err) {\n // If we get a 401 Unauthorized error (v1 API requires separate auth for private images), fall back to Docker v2 API\n if (err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Quay v1 API unauthorized, falling back to Docker v2 API',\n );\n tags = await this.getDockerApiTags(registryHost, dockerRepository);\n } else {\n throw err;\n }\n }\n } else {\n tags = await this.getDockerApiTags(registryHost, dockerRepository);\n }\n return tags;\n } catch (_err) /* istanbul ignore next */ {\n const err = _err instanceof ExternalHostError ? _err.err : _err;\n\n if (\n (err.statusCode === 404 || err.message === PAGE_NOT_FOUND_ERROR) &&\n !dockerRepository.includes('/')\n ) {\n logger.debug(\n `Retrying Tags for ${registryHost}/${dockerRepository} using library/ prefix`,\n );\n return this.getTags(registryHost, `library/${dockerRepository}`);\n }\n // JFrog Artifactory - Retry handling when resolving Docker Official Images\n // These follow the format of {{registryHost}}{{jFrogRepository}}/library/{{dockerRepository}}\n if (\n (err.statusCode === 404 || err.message === PAGE_NOT_FOUND_ERROR) &&\n isArtifactoryServer(err.response) &&\n dockerRepository.split('/').length === 2\n ) {\n logger.debug(\n `JFrog Artifactory: Retrying Tags for ${registryHost}/${dockerRepository} using library/ path between JFrog virtual repository and image`,\n );\n\n const dockerRepositoryParts = dockerRepository.split('/');\n const jfrogRepository = dockerRepositoryParts[0];\n const dockerImage = dockerRepositoryParts[1];\n\n return this.getTags(\n registryHost,\n `${jfrogRepository}/library/${dockerImage}`,\n );\n }\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry failure: too many requests',\n );\n throw new ExternalHostError(err);\n }\n if (err.statusCode >= 500 && err.statusCode < 600) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry failure: internal error',\n );\n throw new ExternalHostError(err);\n }\n const errorCodes = ['ECONNRESET', 'ETIMEDOUT'];\n if (errorCodes.includes(err.code)) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry connection failure',\n );\n throw new ExternalHostError(err);\n }\n if (isDockerHost(registryHost)) {\n logger.info({ err }, 'Docker Hub lookup failure');\n }\n throw _err;\n }\n }\n\n getTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | null> {\n return withCache(\n {\n namespace: 'datasource-docker-tags',\n key: `${registryHost}:${dockerRepository}`,\n },\n () => this._getTags(registryHost, dockerRepository),\n );\n }\n\n /**\n * docker.getDigest\n *\n * The `newValue` supplied here should be a valid tag for the docker image.\n *\n * This function will:\n * - Look up a sha256 digest for a tag on its registry\n * - Return the digest as a string\n */\n private async _getDigest(\n { registryUrl, lookupName, packageName, currentDigest }: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n let registryHost: string;\n let dockerRepository: string;\n if (registryUrl && lookupName) {\n // Reuse the resolved values from getReleases()\n registryHost = registryUrl;\n dockerRepository = lookupName;\n } else {\n // Resolve values independently\n ({ registryHost, dockerRepository } = getRegistryRepository(\n packageName,\n registryUrl!,\n ));\n }\n logger.debug(\n // TODO: types (#22198)\n `getDigest(${registryHost}, ${dockerRepository}, ${newValue})`,\n );\n const newTag = isNonEmptyString(newValue) ? newValue : 'latest';\n let digest: string | null = null;\n try {\n let architecture: string | null | undefined = null;\n if (currentDigest && isDockerDigest(currentDigest)) {\n architecture = await this.getImageArchitecture(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n }\n\n let manifestResponse: HttpResponse | null = null;\n if (!architecture) {\n // Reuse the digest cached from the Docker Hub tag API\n if (registryHost === DOCKER_HUB) {\n const cache = await DockerHubCache.init(dockerRepository);\n const cachedDigest = cache.getDigestForTag(newTag);\n if (cachedDigest) {\n return cachedDigest;\n }\n }\n\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n newTag,\n 'head',\n );\n\n if (\n manifestResponse &&\n hasKey('docker-content-digest', manifestResponse.headers)\n ) {\n digest =\n (manifestResponse.headers['docker-content-digest'] as string) ||\n null;\n }\n }\n\n if (\n isNonEmptyString(architecture) ||\n (manifestResponse &&\n !hasKey('docker-content-digest', manifestResponse.headers))\n ) {\n // Reuse the per-arch digest cached from the Docker Hub tag API\n if (isNonEmptyString(architecture) && registryHost === DOCKER_HUB) {\n const cache = await DockerHubCache.init(dockerRepository);\n const cachedDigest = cache.getArchDigestForTag(newTag, architecture);\n if (cachedDigest) {\n return cachedDigest;\n }\n }\n\n logger.debug(\n { registryHost, dockerRepository },\n 'Architecture-specific digest or missing docker-content-digest header - pulling full manifest',\n );\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n newTag,\n );\n\n if (architecture && manifestResponse) {\n const parsed = ManifestJson.safeParse(manifestResponse.body);\n /* istanbul ignore else: hard to test */\n if (parsed.success) {\n const manifestList = parsed.data;\n if (\n manifestList.mediaType ===\n 'application/vnd.docker.distribution.manifest.list.v2+json' ||\n manifestList.mediaType ===\n 'application/vnd.oci.image.index.v1+json'\n ) {\n for (const manifest of manifestList.manifests) {\n if (manifest.platform?.architecture === architecture) {\n digest = manifest.digest;\n break;\n }\n }\n // TODO: return null if no matching architecture digest found\n // https://github.com/renovatebot/renovate/discussions/22639\n } else if (\n hasKey('docker-content-digest', manifestResponse.headers)\n ) {\n // TODO: return null if no matching architecture, requires to fetch the config manifest\n // https://github.com/renovatebot/renovate/discussions/22639\n digest = manifestResponse.headers[\n 'docker-content-digest'\n ] as string;\n }\n } else {\n logger.debug(\n {\n registryHost,\n dockerRepository,\n newTag,\n body: manifestResponse.body,\n headers: manifestResponse.headers,\n err: parsed.error,\n },\n 'Failed to parse manifest response',\n );\n }\n }\n\n if (!digest) {\n logger.debug(\n { registryHost, dockerRepository, newTag },\n 'Extraction digest from manifest response body is deprecated',\n );\n digest = extractDigestFromResponseBody(manifestResponse!);\n }\n }\n\n if (\n !manifestResponse &&\n !dockerRepository.includes('/') &&\n !packageName.includes('/')\n ) {\n logger.debug(\n `Retrying Digest for ${registryHost}/${dockerRepository} using library/ prefix`,\n );\n return this.getDigest(\n {\n registryUrl,\n packageName: `library/${packageName}`,\n currentDigest,\n },\n newValue,\n );\n }\n\n if (manifestResponse) {\n // TODO: fix types (#22198)\n logger.debug(`Got docker digest ${digest!}`);\n }\n } catch (err) /* istanbul ignore next */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n {\n err,\n packageName,\n newTag,\n },\n 'Unknown Error looking up docker image digest',\n );\n }\n return digest;\n }\n\n override getDigest(\n config: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n const newTag = newValue ?? 'latest';\n const { registryHost, dockerRepository } = getRegistryRepository(\n config.packageName,\n config.registryUrl!,\n );\n const digest = config.currentDigest ? `@${config.currentDigest}` : '';\n return withCache(\n {\n namespace: 'datasource-docker-digest',\n key: `${registryHost}:${dockerRepository}:${newTag}${digest}`,\n fallback: true,\n shouldCacheResult: isNonEmptyString,\n },\n () => this._getDigest(config, newValue),\n );\n }\n\n private async _getDockerHubTags(\n dockerRepository: string,\n ): Promise<Release[] | null> {\n let url = `https://hub.docker.com/v2/repositories/${dockerRepository}/tags?page_size=1000&ordering=last_updated`;\n\n const cache = await DockerHubCache.init(dockerRepository);\n const maxPages = GlobalConfig.get('dockerMaxPages');\n const allowCrossOrigin = isCrossOriginPaginationAllowed(dockerDatasourceId);\n let page = 0,\n needNextPage = true;\n while (needNextPage && page < maxPages) {\n const { val, err } = await this.http\n .getJsonSafe(url, DockerHubTagsPage)\n .unwrap();\n\n if (err) {\n logger.debug({ err }, `Docker: error fetching data from DockerHub`);\n return null;\n }\n page++;\n const { results, next, count } = val;\n\n needNextPage = cache.reconcile(results, count);\n\n if (!next) {\n break;\n }\n\n // Only follow the `next` link when it's on the same origin, unless explicitly opted in\n const nextUrl = resolvePaginationUrl(url, next, allowCrossOrigin);\n if (!nextUrl) {\n logger.once.warn(\n { dockerRepository, nextUrl: next },\n 'Ignoring cross-origin or invalid Docker Hub tags pagination link',\n );\n break;\n }\n\n url = nextUrl;\n }\n\n await cache.save();\n\n const items = cache.getItems();\n return items.map(({ name: version, tag_last_pushed }) => {\n const release: Release = { version };\n\n const releaseTimestamp = asTimestamp(tag_last_pushed);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n\n // Digest is intentionally not propagated — the Docker Hub tag API\n // returns the manifest-list digest, which would bypass arch-aware\n // resolution in `getDigest()`. `getDigest()` consults the same cache\n // as a shortcut when no arch resolution is needed.\n return release;\n });\n }\n\n getDockerHubTags(dockerRepository: string): Promise<Release[] | null> {\n return withCache(\n {\n namespace: 'datasource-docker-hub-tags',\n key: `${dockerRepository}`,\n },\n () => this._getDockerHubTags(dockerRepository),\n );\n }\n\n /**\n * docker.getReleases\n *\n * A docker image usually looks something like this: somehost.io/owner/repo:8.1.0-alpine\n * In the above:\n * - 'somehost.io' is the registry\n * - 'owner/repo' is the package name\n * - '8.1.0-alpine' is the tag\n *\n * This function will filter only tags that contain a semver version\n */\n private async _getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n const { registryHost, dockerRepository } = getRegistryRepository(\n packageName,\n registryUrl!,\n );\n\n type TagsResultType = AsyncResult<\n Release[],\n NonNullable<Error | 'tags-error' | 'dockerhub-error'>\n >;\n\n const getTags = (): TagsResultType =>\n Result.wrapNullable(\n this.getTags(registryHost, dockerRepository),\n 'tags-error' as const,\n ).transform((tags) => tags.map((version) => ({ version })));\n\n const getDockerHubTags = (): TagsResultType =>\n Result.wrapNullable(\n this.getDockerHubTags(dockerRepository),\n 'dockerhub-error' as const,\n ).catch(getTags);\n\n const tagsResult =\n registryHost === DOCKER_HUB &&\n !getEnv().RENOVATE_X_DOCKER_HUB_TAGS_DISABLE\n ? getDockerHubTags()\n : getTags();\n\n const { val: releases, err } = await tagsResult.unwrap();\n if (err instanceof Error) {\n throw err;\n } else if (err) {\n return null;\n }\n\n const ret: ReleaseResult = {\n registryUrl: registryHost,\n releases,\n };\n if (dockerRepository !== packageName) {\n // This will be reused later if a getDigest() call is made\n ret.lookupName = dockerRepository;\n }\n\n const tags = releases.map((release) => release.version);\n const latestTag = tags.includes('latest')\n ? 'latest'\n : (findLatestStable(tags) ?? tags.at(-1));\n\n /* v8 ignore next -- TODO: add test */\n if (!latestTag) {\n return ret;\n }\n const labels = await this.getLabels(\n registryHost,\n dockerRepository,\n latestTag,\n );\n if (labels) {\n if (isNonEmptyString(labels[gitRefLabel])) {\n ret.gitRef = labels[gitRefLabel];\n }\n for (const label of sourceLabels) {\n if (isNonEmptyString(labels[label])) {\n ret.sourceUrl = labels[label];\n break;\n }\n }\n if (isNonEmptyString(labels[imageUrlLabel])) {\n ret.homepage = labels[imageUrlLabel];\n }\n }\n return ret;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n const { registryHost, dockerRepository } = getRegistryRepository(\n config.packageName,\n config.registryUrl!,\n );\n return withCache(\n {\n namespace: 'datasource-docker-releases-v2',\n key: `${registryHost}:${dockerRepository}`,\n cacheable: registryHost === DOCKER_HUB,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["dockerVersioningId","HttpError"],"sources":["../../../../lib/modules/datasource/docker/index.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { PAGE_NOT_FOUND_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { hasKey } from '../../../util/object.ts';\nimport { type AsyncResult, Result } from '../../../util/result.ts';\nimport { isDockerDigest } from '../../../util/string-match.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport {\n ensurePathPrefix,\n joinUrlParts,\n parseLinkHeader,\n parseUrl,\n} from '../../../util/url.ts';\nimport { id as dockerVersioningId } from '../../versioning/docker/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type {\n DigestConfig,\n GetReleasesConfig,\n Release,\n ReleaseResult,\n} from '../types.ts';\nimport {\n isArtifactoryServer,\n isCrossOriginPaginationAllowed,\n resolvePaginationUrl,\n} from '../util.ts';\nimport {\n DOCKER_HUB,\n dockerDatasourceId,\n extractDigestFromResponseBody,\n findHelmSourceUrl,\n findLatestStable,\n getAuthHeaders,\n getRegistryRepository,\n gitRefLabel,\n imageUrlLabel,\n isDockerHost,\n sourceLabel,\n sourceLabels,\n} from './common.ts';\nimport { DockerHubCache } from './dockerhub-cache.ts';\nimport { ecrPublicRegex, ecrRegex, isECRMaxResultsError } from './ecr.ts';\nimport type {\n DistributionManifest,\n Manifest,\n OciImageManifest,\n} from './schema.ts';\nimport {\n DockerHubTagsPage,\n ManifestJson,\n OciHelmConfig,\n OciImageConfig,\n QuayTagsResponse,\n RegistryTagsList,\n} from './schema.ts';\n\nconst defaultConfig = {\n commitMessageTopic: '{{{depName}}} Docker tag',\n commitMessageExtra:\n 'to {{#if isPinDigest}}{{{newDigestShort}}}{{else}}{{#if isMajor}}{{{prettyNewMajor}}}{{else}}{{{prettyNewVersion}}}{{/if}}{{/if}}',\n digest: {\n branchTopic: '{{{depNameSanitized}}}-{{{currentValue}}}',\n commitMessageExtra: 'to {{newDigestShort}}',\n commitMessageTopic:\n '{{{depName}}}{{#if currentValue}}:{{{currentValue}}}{{/if}} Docker digest',\n group: {\n commitMessageTopic: '{{{groupName}}}',\n commitMessageExtra: '',\n },\n },\n pin: {\n commitMessageExtra: '',\n groupName: 'Docker digests',\n group: {\n commitMessageTopic: '{{{groupName}}}',\n branchTopic: 'digests-pin',\n },\n },\n};\n\nexport class DockerDatasource extends Datasource {\n static readonly id = dockerDatasourceId;\n\n override readonly defaultVersioning = dockerVersioningId;\n\n override readonly defaultRegistryUrls = [DOCKER_HUB];\n\n override readonly defaultConfig = defaultConfig;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'Only supported on Docker Hub: The release timestamp is determined from the `tag_last_pushed` field in the results. **NOTE**: Currently, digests will receive the same release timestamp as the `tag_last_pushed`, which means that digests may appear newer than they are - see https://github.com/renovatebot/renovate/issues/38659';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `org.opencontainers.image.source` and `org.label-schema.vcs-url` labels present in the metadata of the **latest stable** image found on the Docker registry.';\n\n constructor() {\n super(DockerDatasource.id);\n }\n\n // TODO: debug why quay throws errors (#9612)\n private async getManifestResponse(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n mode: 'head' | 'getText' = 'getText',\n ): Promise<HttpResponse | null> {\n logger.debug(\n `getManifestResponse(${registryHost}, ${dockerRepository}, ${tag}, ${mode})`,\n );\n try {\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return null;\n }\n headers.accept = [\n 'application/vnd.docker.distribution.manifest.list.v2+json',\n 'application/vnd.docker.distribution.manifest.v2+json',\n 'application/vnd.oci.image.manifest.v1+json',\n 'application/vnd.oci.image.index.v1+json',\n ].join(', ');\n const url = `${registryHost}/v2/${dockerRepository}/manifests/${tag}`;\n const manifestResponse = await this.http[mode](url, {\n headers,\n noAuth: true,\n cacheProvider: memCacheProvider,\n });\n return manifestResponse;\n } catch (err) /* istanbul ignore next */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\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 if (err.statusCode === 404) {\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Docker Manifest is unknown',\n );\n return null;\n }\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n if (err.statusCode >= 500 && err.statusCode < 600) {\n throw new ExternalHostError(err);\n }\n if (err.code === 'ETIMEDOUT') {\n logger.debug(\n { registryHost },\n 'Timeout when attempting to connect to docker registry',\n );\n logger.debug({ err });\n return null;\n }\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Unknown Error looking up docker manifest',\n );\n return null;\n }\n }\n\n private async _getImageConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciImageConfig> | undefined> {\n logger.trace(\n `getImageConfig(${registryHost}, ${dockerRepository}, ${configDigest})`,\n );\n\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n /* v8 ignore next -- should never happen */\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return undefined;\n }\n const url = joinUrlParts(\n registryHost,\n 'v2',\n dockerRepository,\n 'blobs',\n configDigest,\n );\n return await this.http.getJson(\n url,\n {\n headers,\n noAuth: true,\n },\n OciImageConfig,\n );\n }\n\n getImageConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciImageConfig> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-imageconfig',\n key: `${registryHost}:${dockerRepository}@${configDigest}`,\n ttlMinutes: 1440 * 28,\n },\n () => this._getImageConfig(registryHost, dockerRepository, configDigest),\n );\n }\n\n private async _getHelmConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciHelmConfig> | undefined> {\n logger.trace(\n `getImageConfig(${registryHost}, ${dockerRepository}, ${configDigest})`,\n );\n\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n /* v8 ignore next -- should never happen */\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return undefined;\n }\n const url = joinUrlParts(\n registryHost,\n 'v2',\n dockerRepository,\n 'blobs',\n configDigest,\n );\n return await this.http.getJson(\n url,\n {\n headers,\n noAuth: true,\n },\n OciHelmConfig,\n );\n }\n\n getHelmConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciHelmConfig> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-imageconfig',\n key: `${registryHost}:${dockerRepository}@${configDigest}`,\n ttlMinutes: 1440 * 28,\n },\n () => this._getHelmConfig(registryHost, dockerRepository, configDigest),\n );\n }\n\n private async getConfigDigest(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<string | null> {\n return (\n (await this.getManifest(registry, dockerRepository, tag))?.config\n ?.digest ?? null\n );\n }\n\n private async getManifestDocument(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Manifest | null> {\n const manifestResponse = await this.getManifestResponse(\n registry,\n dockerRepository,\n tag,\n );\n\n // If getting the manifest fails here, then abort\n // This means that the latest tag doesn't have a manifest, which shouldn't\n // be possible\n /* v8 ignore next -- should never happen */\n if (!manifestResponse) {\n return null;\n }\n\n // Softfail on invalid manifests\n const parsed = ManifestJson.safeParse(manifestResponse.body);\n if (!parsed.success) {\n logger.debug(\n {\n registry,\n dockerRepository,\n tag,\n body: manifestResponse.body,\n headers: manifestResponse.headers,\n err: parsed.error,\n },\n 'Invalid manifest response',\n );\n return null;\n }\n\n return parsed.data;\n }\n\n private async resolveImageManifest(\n registry: string,\n dockerRepository: string,\n tag: string,\n manifest: Manifest,\n ): Promise<OciImageManifest | DistributionManifest | null> {\n switch (manifest.mediaType) {\n case 'application/vnd.docker.distribution.manifest.v2+json':\n case 'application/vnd.oci.image.manifest.v1+json':\n return manifest;\n case 'application/vnd.docker.distribution.manifest.list.v2+json':\n case 'application/vnd.oci.image.index.v1+json':\n if (!manifest.manifests.length) {\n logger.debug(\n { manifest },\n 'Invalid manifest list with no manifests - returning',\n );\n return null;\n }\n logger.trace(\n { registry, dockerRepository, tag },\n 'Found manifest list, using first image',\n );\n return this.getManifest(\n registry,\n dockerRepository,\n manifest.manifests[0].digest,\n );\n // istanbul ignore next: can't happen\n default:\n return null;\n }\n }\n\n private async getManifest(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<OciImageManifest | DistributionManifest | null> {\n const manifest = await this.getManifestDocument(\n registry,\n dockerRepository,\n tag,\n );\n if (!manifest) {\n return null;\n }\n return this.resolveImageManifest(registry, dockerRepository, tag, manifest);\n }\n\n private async _getImageArchitecture(\n registryHost: string,\n dockerRepository: string,\n currentDigest: string,\n ): Promise<string | null | undefined> {\n try {\n let manifestResponse: HttpResponse | null;\n\n try {\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n currentDigest,\n 'head',\n );\n } catch (_err) {\n const err =\n _err instanceof ExternalHostError\n ? _err.err\n : /* istanbul ignore next: can never happen */ _err;\n\n if (\n typeof err.statusCode === 'number' &&\n err.statusCode >= 500 &&\n err.statusCode < 600\n ) {\n // querying the digest manifest for a non existent image leads to a 500 statusCode\n return null;\n }\n\n /* istanbul ignore next */\n throw _err;\n }\n\n if (\n manifestResponse?.headers['content-type'] !==\n 'application/vnd.docker.distribution.manifest.v2+json' &&\n manifestResponse?.headers['content-type'] !==\n 'application/vnd.oci.image.manifest.v1+json'\n ) {\n return null;\n }\n\n const configDigest = await this.getConfigDigest(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n if (!configDigest) {\n return null;\n }\n\n const configResponse = await this.getImageConfig(\n registryHost,\n dockerRepository,\n configDigest,\n );\n\n // TODO: fix me, architecture is required in spec\n if (\n configResponse &&\n ('config' in configResponse.body ||\n 'architecture' in configResponse.body)\n ) {\n const architecture = configResponse.body.architecture ?? null;\n logger.debug(\n `Current digest ${currentDigest} relates to architecture ${\n architecture ?? 'null'\n }`,\n );\n\n return architecture;\n }\n } catch (err) /* istanbul ignore next */ {\n if (err.statusCode !== 404 || err.message === PAGE_NOT_FOUND_ERROR) {\n throw err;\n }\n logger.debug(\n { registryHost, dockerRepository, currentDigest, err },\n 'Unknown error getting image architecture',\n );\n }\n\n return undefined;\n }\n\n getImageArchitecture(\n registryHost: string,\n dockerRepository: string,\n currentDigest: string,\n ): Promise<string | null | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-architecture',\n key: `${registryHost}:${dockerRepository}@${currentDigest}`,\n ttlMinutes: 1440 * 28,\n shouldCacheResult: isNonEmptyString,\n },\n () =>\n this._getImageArchitecture(\n registryHost,\n dockerRepository,\n currentDigest,\n ),\n );\n }\n\n /*\n * docker.getLabels\n *\n * This function will:\n * - Return the labels for the requested image\n */\n private async _getLabels(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Record<string, string> | undefined> {\n logger.debug(`getLabels(${registryHost}, ${dockerRepository}, ${tag})`);\n // Skip Docker Hub image if RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP is set\n if (\n getEnv().RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP &&\n registryHost === DOCKER_HUB\n ) {\n logger.debug(\n 'Docker Hub image - skipping label lookup due to RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP',\n );\n return {};\n }\n try {\n let labels: Record<string, string> | undefined = {};\n const manifestDocument = await this.getManifestDocument(\n registryHost,\n dockerRepository,\n tag,\n );\n\n if (!manifestDocument) {\n logger.debug(\n { registryHost, dockerRepository, tag },\n 'No manifest found',\n );\n return undefined;\n }\n\n if ('annotations' in manifestDocument && manifestDocument.annotations) {\n labels = manifestDocument.annotations;\n }\n\n if ('manifests' in manifestDocument) {\n const descriptorAnnotations = manifestDocument.manifests\n .map((descriptor) => descriptor.annotations)\n .find(\n (annotations) =>\n isNonEmptyString(annotations?.[sourceLabel]) &&\n isNonEmptyString(annotations?.[gitRefLabel]),\n );\n if (descriptorAnnotations) {\n labels = { ...labels, ...descriptorAnnotations };\n }\n }\n\n if (\n 'manifests' in manifestDocument &&\n labels[sourceLabel] &&\n labels[gitRefLabel]\n ) {\n return labels;\n }\n\n const manifest = await this.resolveImageManifest(\n registryHost,\n dockerRepository,\n tag,\n manifestDocument,\n );\n if (!manifest) {\n return undefined;\n }\n\n if ('annotations' in manifest && manifest.annotations) {\n labels = { ...labels, ...manifest.annotations };\n }\n\n switch (manifest.config.mediaType) {\n case 'application/vnd.cncf.helm.config.v1+json': {\n if (labels[sourceLabel]) {\n // we already have the source url, so no need to pull the config\n return labels;\n }\n const configResponse = await this.getHelmConfig(\n registryHost,\n dockerRepository,\n manifest.config.digest,\n );\n\n if (configResponse) {\n // Helm chart\n const url = findHelmSourceUrl(configResponse.body);\n if (url) {\n labels[sourceLabel] = url;\n }\n }\n break;\n }\n case 'application/vnd.oci.image.config.v1+json':\n case 'application/vnd.docker.container.image.v1+json': {\n if (labels[sourceLabel] && labels[gitRefLabel]) {\n // we already have the source url, so no need to pull the config\n return labels;\n }\n const configResponse = await this.getImageConfig(\n registryHost,\n dockerRepository,\n manifest.config.digest,\n );\n\n /* v8 ignore next -- should never happen */\n if (!configResponse) {\n return labels;\n }\n\n const body = configResponse.body;\n if (body.config) {\n labels = { ...labels, ...body.config.Labels };\n } else {\n logger.debug(\n { headers: configResponse.headers, body },\n `manifest blob response body missing the \"config\" property`,\n );\n }\n break;\n }\n }\n\n if (labels) {\n logger.debug(\n {\n labels,\n },\n 'found labels in manifest',\n );\n }\n return labels;\n } catch (err) /* istanbul ignore next: should be tested in future */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (err.statusCode === 400 || err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository, err },\n 'Unauthorized docker lookup',\n );\n } else if (err.statusCode === 404) {\n logger.warn(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Config Manifest is unknown',\n );\n } else if (err.statusCode === 429 && isDockerHost(registryHost)) {\n logger.warn({ err }, 'docker registry failure: too many requests');\n } else if (err.statusCode >= 500 && err.statusCode < 600) {\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'docker registry failure: internal error',\n );\n } else if (\n err.code === 'ERR_TLS_CERT_ALTNAME_INVALID' ||\n err.code === 'ETIMEDOUT'\n ) {\n logger.debug(\n { registryHost, err },\n 'Error connecting to docker registry',\n );\n } else if (registryHost === 'https://quay.io') {\n // istanbul ignore next\n logger.debug(\n 'Ignoring quay.io errors until they fully support v2 schema',\n );\n } else {\n logger.info(\n { registryHost, dockerRepository, tag, err },\n 'Unknown error getting Docker labels',\n );\n }\n return {};\n }\n }\n\n getLabels(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Record<string, string> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-labels',\n key: `${registryHost}:${dockerRepository}:${tag}`,\n ttlMinutes: 24 * 60,\n },\n () => this._getLabels(registryHost, dockerRepository, tag),\n );\n }\n\n private async getTagsQuayRegistry(\n registry: string,\n repository: string,\n ): Promise<string[]> {\n let tags: string[] = [];\n const limit = 100;\n\n function pageUrl(page: number): string {\n return `${registry}/api/v1/repository/${repository}/tag/?limit=${limit}&page=${page}&onlyActiveTags=true`;\n }\n\n let page = 1;\n let url: string | null = pageUrl(page);\n while (url && page <= 20) {\n const res: HttpResponse<QuayTagsResponse> = await this.http.getJson(\n url,\n QuayTagsResponse,\n );\n const pageTags = res.body.tags.map((tag) => tag.name);\n tags = tags.concat(pageTags);\n page += 1;\n url = res.body.has_additional ? pageUrl(page) : null;\n }\n return tags;\n }\n\n private async getDockerApiTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | undefined> {\n let tags: string[] = [];\n // AWS ECR limits the maximum number of results to 1000\n // See https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeRepositories.html#ECR-DescribeRepositories-request-maxResults\n // See https://docs.aws.amazon.com/AmazonECRPublic/latest/APIReference/API_DescribeRepositories.html#ecrpublic-DescribeRepositories-request-maxResults\n const limit =\n ecrRegex.test(registryHost) || ecrPublicRegex.test(registryHost)\n ? 1000\n : 10000;\n let url: string | null =\n `${registryHost}/${dockerRepository}/tags/list?n=${limit}`;\n url = ensurePathPrefix(url, '/v2');\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n url,\n );\n if (!headers) {\n logger.debug('Failed to get authHeaders for getTags lookup');\n return undefined;\n }\n let page = 0;\n const hostsNeedingAllPages = [\n 'https://ghcr.io', // GHCR sorts from oldest to newest, so we need to get all pages\n 'https://quay.io', // Quay sorts from oldest to newest, so we need to get all pages\n 'https://cgr.dev', // Chainguard sorts lexically and publishes a tag per build, so current versions sort past the page limit\n ];\n const pages = hostsNeedingAllPages.includes(registryHost)\n ? 1000\n : GlobalConfig.get('dockerMaxPages');\n logger.trace({ registryHost, dockerRepository, pages }, 'docker.getTags');\n const allowCrossOrigin = isCrossOriginPaginationAllowed(dockerDatasourceId);\n let foundMaxResultsError = false;\n do {\n let res: HttpResponse<RegistryTagsList>;\n try {\n res = await this.http.getJson(\n url,\n { headers, noAuth: true },\n RegistryTagsList,\n );\n } catch (err) {\n if (\n !foundMaxResultsError &&\n err instanceof HttpError &&\n isECRMaxResultsError(err)\n ) {\n const maxResults = 1000;\n url = `${registryHost}/${dockerRepository}/tags/list?n=${maxResults}`;\n url = ensurePathPrefix(url, '/v2');\n foundMaxResultsError = true;\n continue;\n }\n throw err;\n }\n tags = tags.concat(res.body.tags);\n const linkHeader = parseLinkHeader(res.headers.link);\n if (isArtifactoryServer(res)) {\n // Artifactory bug: next link comes back without virtual-repo prefix (RTFACT-18971)\n if (linkHeader?.next?.last) {\n // parse the current URL, strip any old \"last\" param, then set the new one\n const parsed = parseUrl(url);\n // v8 ignore if: url is always a valid HTTP URL as `ensurePathPrefix`\n if (!parsed) {\n url = null;\n break;\n }\n parsed.searchParams.delete('last');\n parsed.searchParams.set('last', linkHeader.next.last);\n url = parsed.href;\n } else {\n url = null;\n }\n } else if (linkHeader?.next?.url) {\n // Resolve the relative-or-absolute next link, not following cross-origin requests unless explicitly opted in\n const nextUrl = resolvePaginationUrl(\n url,\n linkHeader.next.url,\n allowCrossOrigin,\n );\n if (!nextUrl) {\n // make sure that users are aware if there are any (potentially malicious, or misconfigured) pagination links being returned\n logger.once.warn(\n { registryHost, nextUrl: linkHeader.next.url },\n 'Ignoring cross-origin or invalid Docker registry tags pagination link',\n );\n }\n url = nextUrl;\n } else {\n url = null;\n }\n page += 1;\n } while (url && page < pages);\n return tags;\n }\n\n private async _getTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | undefined> {\n try {\n const isQuay = registryHost === 'https://quay.io';\n let tags: string[] | undefined;\n if (isQuay) {\n try {\n // Due to pagination and sorting limits on Quay Docker v2 API implementation we try the Quay v1 API first\n tags = await this.getTagsQuayRegistry(registryHost, dockerRepository);\n } catch (err) {\n // If we get a 401 Unauthorized error (v1 API requires separate auth for private images), fall back to Docker v2 API\n if (err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Quay v1 API unauthorized, falling back to Docker v2 API',\n );\n tags = await this.getDockerApiTags(registryHost, dockerRepository);\n } else {\n throw err;\n }\n }\n } else {\n tags = await this.getDockerApiTags(registryHost, dockerRepository);\n }\n return tags;\n } catch (_err) /* istanbul ignore next */ {\n const err = _err instanceof ExternalHostError ? _err.err : _err;\n\n if (\n (err.statusCode === 404 || err.message === PAGE_NOT_FOUND_ERROR) &&\n !dockerRepository.includes('/')\n ) {\n logger.debug(\n `Retrying Tags for ${registryHost}/${dockerRepository} using library/ prefix`,\n );\n return this.getTags(registryHost, `library/${dockerRepository}`);\n }\n // JFrog Artifactory - Retry handling when resolving Docker Official Images\n // These follow the format of {{registryHost}}{{jFrogRepository}}/library/{{dockerRepository}}\n if (\n (err.statusCode === 404 || err.message === PAGE_NOT_FOUND_ERROR) &&\n isArtifactoryServer(err.response) &&\n dockerRepository.split('/').length === 2\n ) {\n logger.debug(\n `JFrog Artifactory: Retrying Tags for ${registryHost}/${dockerRepository} using library/ path between JFrog virtual repository and image`,\n );\n\n const dockerRepositoryParts = dockerRepository.split('/');\n const jfrogRepository = dockerRepositoryParts[0];\n const dockerImage = dockerRepositoryParts[1];\n\n return this.getTags(\n registryHost,\n `${jfrogRepository}/library/${dockerImage}`,\n );\n }\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry failure: too many requests',\n );\n throw new ExternalHostError(err);\n }\n if (err.statusCode >= 500 && err.statusCode < 600) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry failure: internal error',\n );\n throw new ExternalHostError(err);\n }\n const errorCodes = ['ECONNRESET', 'ETIMEDOUT'];\n if (errorCodes.includes(err.code)) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry connection failure',\n );\n throw new ExternalHostError(err);\n }\n if (isDockerHost(registryHost)) {\n logger.info({ err }, 'Docker Hub lookup failure');\n }\n throw _err;\n }\n }\n\n getTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-tags',\n key: `${registryHost}:${dockerRepository}`,\n cacheable: registryHost === DOCKER_HUB,\n },\n () => this._getTags(registryHost, dockerRepository),\n );\n }\n\n /**\n * docker.getDigest\n *\n * The `newValue` supplied here should be a valid tag for the docker image.\n *\n * This function will:\n * - Look up a sha256 digest for a tag on its registry\n * - Return the digest as a string\n */\n private async _getDigest(\n { registryUrl, lookupName, packageName, currentDigest }: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n let registryHost: string;\n let dockerRepository: string;\n if (registryUrl && lookupName) {\n // Reuse the resolved values from getReleases()\n registryHost = registryUrl;\n dockerRepository = lookupName;\n } else {\n // Resolve values independently\n ({ registryHost, dockerRepository } = getRegistryRepository(\n packageName,\n registryUrl!,\n ));\n }\n logger.debug(\n // TODO: types (#22198)\n `getDigest(${registryHost}, ${dockerRepository}, ${newValue})`,\n );\n const newTag = isNonEmptyString(newValue) ? newValue : 'latest';\n let digest: string | null = null;\n try {\n let architecture: string | null | undefined = null;\n if (currentDigest && isDockerDigest(currentDigest)) {\n architecture = await this.getImageArchitecture(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n }\n\n let manifestResponse: HttpResponse | null = null;\n if (!architecture) {\n // Reuse the digest cached from the Docker Hub tag API\n if (registryHost === DOCKER_HUB) {\n const cache = await DockerHubCache.init(dockerRepository);\n const cachedDigest = cache.getDigestForTag(newTag);\n if (cachedDigest) {\n return cachedDigest;\n }\n }\n\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n newTag,\n 'head',\n );\n\n if (\n manifestResponse &&\n hasKey('docker-content-digest', manifestResponse.headers)\n ) {\n digest =\n (manifestResponse.headers['docker-content-digest'] as string) ||\n null;\n }\n }\n\n if (\n isNonEmptyString(architecture) ||\n (manifestResponse &&\n !hasKey('docker-content-digest', manifestResponse.headers))\n ) {\n // Reuse the per-arch digest cached from the Docker Hub tag API\n if (isNonEmptyString(architecture) && registryHost === DOCKER_HUB) {\n const cache = await DockerHubCache.init(dockerRepository);\n const cachedDigest = cache.getArchDigestForTag(newTag, architecture);\n if (cachedDigest) {\n return cachedDigest;\n }\n }\n\n logger.debug(\n { registryHost, dockerRepository },\n 'Architecture-specific digest or missing docker-content-digest header - pulling full manifest',\n );\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n newTag,\n );\n\n if (architecture && manifestResponse) {\n const parsed = ManifestJson.safeParse(manifestResponse.body);\n /* istanbul ignore else: hard to test */\n if (parsed.success) {\n const manifestList = parsed.data;\n if (\n manifestList.mediaType ===\n 'application/vnd.docker.distribution.manifest.list.v2+json' ||\n manifestList.mediaType ===\n 'application/vnd.oci.image.index.v1+json'\n ) {\n for (const manifest of manifestList.manifests) {\n if (manifest.platform?.architecture === architecture) {\n digest = manifest.digest;\n break;\n }\n }\n // TODO: return null if no matching architecture digest found\n // https://github.com/renovatebot/renovate/discussions/22639\n } else if (\n hasKey('docker-content-digest', manifestResponse.headers)\n ) {\n // TODO: return null if no matching architecture, requires to fetch the config manifest\n // https://github.com/renovatebot/renovate/discussions/22639\n digest = manifestResponse.headers[\n 'docker-content-digest'\n ] as string;\n }\n } else {\n logger.debug(\n {\n registryHost,\n dockerRepository,\n newTag,\n body: manifestResponse.body,\n headers: manifestResponse.headers,\n err: parsed.error,\n },\n 'Failed to parse manifest response',\n );\n }\n }\n\n if (!digest) {\n logger.debug(\n { registryHost, dockerRepository, newTag },\n 'Extraction digest from manifest response body is deprecated',\n );\n digest = extractDigestFromResponseBody(manifestResponse!);\n }\n }\n\n if (\n !manifestResponse &&\n !dockerRepository.includes('/') &&\n !packageName.includes('/')\n ) {\n logger.debug(\n `Retrying Digest for ${registryHost}/${dockerRepository} using library/ prefix`,\n );\n return this.getDigest(\n {\n registryUrl,\n packageName: `library/${packageName}`,\n currentDigest,\n },\n newValue,\n );\n }\n\n if (manifestResponse) {\n // TODO: fix types (#22198)\n logger.debug(`Got docker digest ${digest!}`);\n }\n } catch (err) /* istanbul ignore next */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n {\n err,\n packageName,\n newTag,\n },\n 'Unknown Error looking up docker image digest',\n );\n }\n return digest;\n }\n\n override getDigest(\n config: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n const newTag = newValue ?? 'latest';\n const { registryHost, dockerRepository } = getRegistryRepository(\n config.packageName,\n config.registryUrl!,\n );\n const digest = config.currentDigest ? `@${config.currentDigest}` : '';\n return withCache(\n {\n namespace: 'datasource-docker-digest',\n key: `${registryHost}:${dockerRepository}:${newTag}${digest}`,\n fallback: true,\n shouldCacheResult: isNonEmptyString,\n },\n () => this._getDigest(config, newValue),\n );\n }\n\n private async _getDockerHubTags(\n dockerRepository: string,\n ): Promise<Release[] | null> {\n let url = `https://hub.docker.com/v2/repositories/${dockerRepository}/tags?page_size=1000&ordering=last_updated`;\n\n const cache = await DockerHubCache.init(dockerRepository);\n const maxPages = GlobalConfig.get('dockerMaxPages');\n const allowCrossOrigin = isCrossOriginPaginationAllowed(dockerDatasourceId);\n let page = 0,\n needNextPage = true;\n while (needNextPage && page < maxPages) {\n const { val, err } = await this.http\n .getJsonSafe(url, DockerHubTagsPage)\n .unwrap();\n\n if (err) {\n logger.debug({ err }, `Docker: error fetching data from DockerHub`);\n return null;\n }\n page++;\n const { results, next, count } = val;\n\n needNextPage = cache.reconcile(results, count);\n\n if (!next) {\n break;\n }\n\n // Only follow the `next` link when it's on the same origin, unless explicitly opted in\n const nextUrl = resolvePaginationUrl(url, next, allowCrossOrigin);\n if (!nextUrl) {\n logger.once.warn(\n { dockerRepository, nextUrl: next },\n 'Ignoring cross-origin or invalid Docker Hub tags pagination link',\n );\n break;\n }\n\n url = nextUrl;\n }\n\n await cache.save();\n\n const items = cache.getItems();\n return items.map(({ name: version, tag_last_pushed }) => {\n const release: Release = { version };\n\n const releaseTimestamp = asTimestamp(tag_last_pushed);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n\n // Digest is intentionally not propagated — the Docker Hub tag API\n // returns the manifest-list digest, which would bypass arch-aware\n // resolution in `getDigest()`. `getDigest()` consults the same cache\n // as a shortcut when no arch resolution is needed.\n return release;\n });\n }\n\n getDockerHubTags(dockerRepository: string): Promise<Release[] | null> {\n return withCache(\n {\n namespace: 'datasource-docker-hub-tags',\n key: `${dockerRepository}`,\n },\n () => this._getDockerHubTags(dockerRepository),\n );\n }\n\n /**\n * docker.getReleases\n *\n * A docker image usually looks something like this: somehost.io/owner/repo:8.1.0-alpine\n * In the above:\n * - 'somehost.io' is the registry\n * - 'owner/repo' is the package name\n * - '8.1.0-alpine' is the tag\n *\n * This function will filter only tags that contain a semver version\n */\n private async _getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n const { registryHost, dockerRepository } = getRegistryRepository(\n packageName,\n registryUrl!,\n );\n\n type TagsResultType = AsyncResult<\n Release[],\n NonNullable<Error | 'tags-error' | 'dockerhub-error'>\n >;\n\n const getTags = (): TagsResultType =>\n Result.wrapNullable(\n this.getTags(registryHost, dockerRepository),\n 'tags-error' as const,\n ).transform((tags) => tags.map((version) => ({ version })));\n\n const getDockerHubTags = (): TagsResultType =>\n Result.wrapNullable(\n this.getDockerHubTags(dockerRepository),\n 'dockerhub-error' as const,\n ).catch(getTags);\n\n const tagsResult =\n registryHost === DOCKER_HUB &&\n !getEnv().RENOVATE_X_DOCKER_HUB_TAGS_DISABLE\n ? getDockerHubTags()\n : getTags();\n\n const { val: releases, err } = await tagsResult.unwrap();\n if (err instanceof Error) {\n throw err;\n } else if (err) {\n return null;\n }\n\n const ret: ReleaseResult = {\n registryUrl: registryHost,\n releases,\n };\n if (dockerRepository !== packageName) {\n // This will be reused later if a getDigest() call is made\n ret.lookupName = dockerRepository;\n }\n\n const tags = releases.map((release) => release.version);\n const latestTag = tags.includes('latest')\n ? 'latest'\n : (findLatestStable(tags) ?? tags.at(-1));\n\n /* v8 ignore next -- TODO: add test */\n if (!latestTag) {\n return ret;\n }\n const labels = await this.getLabels(\n registryHost,\n dockerRepository,\n latestTag,\n );\n if (labels) {\n if (isNonEmptyString(labels[gitRefLabel])) {\n ret.gitRef = labels[gitRefLabel];\n }\n for (const label of sourceLabels) {\n if (isNonEmptyString(labels[label])) {\n ret.sourceUrl = labels[label];\n break;\n }\n }\n if (isNonEmptyString(labels[imageUrlLabel])) {\n ret.homepage = labels[imageUrlLabel];\n }\n }\n return ret;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n const { registryHost, dockerRepository } = getRegistryRepository(\n config.packageName,\n config.registryUrl!,\n );\n return withCache(\n {\n namespace: 'datasource-docker-releases-v2',\n key: `${registryHost}:${dockerRepository}`,\n cacheable: registryHost === DOCKER_HUB,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n}\n"],"mappings":"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"}
|
|
@@ -38,6 +38,7 @@ async function detectNodeCompatWorkspaces({ managerData, packageFile }) {
|
|
|
38
38
|
logger.debug(`Detecting deno's node compat Workspaces`);
|
|
39
39
|
let filters;
|
|
40
40
|
if (isNonEmptyArray(managerData?.workspaces)) filters = managerData?.workspaces;
|
|
41
|
+
if (!filters) return { packagePaths: [] };
|
|
41
42
|
const localDir = GlobalConfig.get("localDir");
|
|
42
43
|
const packagePaths = (await findPackages(upath.dirname(ensureLocalPath(packageFile)), {
|
|
43
44
|
patterns: filters,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compat.js","names":[],"sources":["../../../../lib/modules/manager/deno/compat.ts"],"sourcesContent":["import { isNonEmptyArray } from '@sindresorhus/is';\nimport { findPackages } from 'find-packages';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport { getSiblingFileName, readLocalFile } from '../../../util/fs/index.ts';\nimport { ensureLocalPath } from '../../../util/fs/util.ts';\nimport { extractPackageJson } from '../npm/extract/common/package-file.ts';\nimport type { NpmPackage } from '../npm/extract/types.ts';\nimport type { PackageFile } from '../types.ts';\nimport type { DenoManagerData } from './types.ts';\n\nexport async function extractDenoCompatiblePackageJson(\n packageFile: string,\n): Promise<PackageFile<DenoManagerData> | null> {\n const packageFileContent = await readLocalFile(packageFile, 'utf8');\n if (!packageFileContent) {\n logger.debug({ packageFile }, 'Deno: No package.json found');\n return null;\n }\n\n let packageJson: NpmPackage;\n try {\n packageJson = parseJson(packageFileContent, packageFile) as NpmPackage;\n } catch (err) {\n logger.error({ err, packageFile }, 'Error parsing package.json');\n return null;\n }\n\n const extracted = extractPackageJson(packageJson, packageFile);\n if (!extracted) {\n return null;\n }\n\n const result = extracted as PackageFile<DenoManagerData>;\n result.managerData = {\n packageName: extracted.managerData?.packageJsonName,\n workspaces: extracted.managerData?.workspaces,\n };\n result.packageFile = packageFile;\n return result;\n}\n\n// referring to lib/modules/manager/npm/extract/pnpm.ts detectPnpmWorkspaces()\nexport async function detectNodeCompatWorkspaces({\n managerData,\n packageFile,\n}: Pick<PackageFile<DenoManagerData>, 'managerData' | 'packageFile'>): Promise<{\n workspaces?: string[];\n packagePaths: string[];\n}> {\n logger.debug(`Detecting deno's node compat Workspaces`);\n\n let filters: string[] | undefined;\n\n // npm workspace\n if (isNonEmptyArray(managerData?.workspaces)) {\n filters = managerData?.workspaces;\n }\n\n const localDir = GlobalConfig.get('localDir');\n const packages = await findPackages(\n upath.dirname(ensureLocalPath(packageFile)),\n {\n patterns: filters,\n // Match the ignores used in @pnpm/find-workspace-packages\n ignore: ['**/node_modules/**', '**/bower_components/**'],\n },\n );\n const packagePaths = packages.map((pkg) => {\n const pkgPath = upath.join(pkg.dir, 'package.json');\n return upath.relative(localDir, pkgPath);\n });\n\n return {\n workspaces: filters,\n packagePaths,\n };\n}\n\nexport async function collectPackageJson(\n lockFile: string,\n): Promise<PackageFile<DenoManagerData>[] | null> {\n const lockFiles = [lockFile];\n const packageFiles: PackageFile<DenoManagerData>[] = [];\n const rootPackageJson = getSiblingFileName(lockFile, 'package.json');\n const rootPackageFile =\n await extractDenoCompatiblePackageJson(rootPackageJson);\n if (rootPackageFile) {\n rootPackageFile.lockFiles = lockFiles;\n\n // detect node compat workspaces\n const result = await detectNodeCompatWorkspaces(rootPackageFile);\n const { workspaces, packagePaths } = result;\n rootPackageFile.managerData = {\n packageName: rootPackageFile.managerData?.packageName,\n // override workspace\n workspaces,\n };\n packageFiles.push(rootPackageFile);\n\n for (const packagePath of packagePaths) {\n const packageFile = await extractDenoCompatiblePackageJson(packagePath);\n if (packageFile) {\n packageFile.lockFiles = lockFiles;\n packageFiles.push(packageFile);\n }\n }\n }\n\n return packageFiles;\n}\n"],"mappings":";;;;;;;;;;AAaA,eAAsB,iCACpB,aAC8C;CAC9C,MAAM,qBAAqB,MAAM,cAAc,aAAa,MAAM;CAClE,IAAI,CAAC,oBAAoB;EACvB,OAAO,MAAM,EAAE,YAAY,GAAG,6BAA6B;EAC3D,OAAO;CACT;CAEA,IAAI;CACJ,IAAI;EACF,cAAc,UAAU,oBAAoB,WAAW;CACzD,SAAS,KAAK;EACZ,OAAO,MAAM;GAAE;GAAK;EAAY,GAAG,4BAA4B;EAC/D,OAAO;CACT;CAEA,MAAM,YAAY,mBAAmB,aAAa,WAAW;CAC7D,IAAI,CAAC,WACH,OAAO;CAGT,MAAM,SAAS;CACf,OAAO,cAAc;EACnB,aAAa,UAAU,aAAa;EACpC,YAAY,UAAU,aAAa;CACrC;CACA,OAAO,cAAc;CACrB,OAAO;AACT;AAGA,eAAsB,2BAA2B,EAC/C,aACA,eAIC;CACD,OAAO,MAAM,yCAAyC;CAEtD,IAAI;CAGJ,IAAI,gBAAgB,aAAa,UAAU,GACzC,UAAU,aAAa;
|
|
1
|
+
{"version":3,"file":"compat.js","names":[],"sources":["../../../../lib/modules/manager/deno/compat.ts"],"sourcesContent":["import { isNonEmptyArray } from '@sindresorhus/is';\nimport { findPackages } from 'find-packages';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport { getSiblingFileName, readLocalFile } from '../../../util/fs/index.ts';\nimport { ensureLocalPath } from '../../../util/fs/util.ts';\nimport { extractPackageJson } from '../npm/extract/common/package-file.ts';\nimport type { NpmPackage } from '../npm/extract/types.ts';\nimport type { PackageFile } from '../types.ts';\nimport type { DenoManagerData } from './types.ts';\n\nexport async function extractDenoCompatiblePackageJson(\n packageFile: string,\n): Promise<PackageFile<DenoManagerData> | null> {\n const packageFileContent = await readLocalFile(packageFile, 'utf8');\n if (!packageFileContent) {\n logger.debug({ packageFile }, 'Deno: No package.json found');\n return null;\n }\n\n let packageJson: NpmPackage;\n try {\n packageJson = parseJson(packageFileContent, packageFile) as NpmPackage;\n } catch (err) {\n logger.error({ err, packageFile }, 'Error parsing package.json');\n return null;\n }\n\n const extracted = extractPackageJson(packageJson, packageFile);\n if (!extracted) {\n return null;\n }\n\n const result = extracted as PackageFile<DenoManagerData>;\n result.managerData = {\n packageName: extracted.managerData?.packageJsonName,\n workspaces: extracted.managerData?.workspaces,\n };\n result.packageFile = packageFile;\n return result;\n}\n\n// referring to lib/modules/manager/npm/extract/pnpm.ts detectPnpmWorkspaces()\nexport async function detectNodeCompatWorkspaces({\n managerData,\n packageFile,\n}: Pick<PackageFile<DenoManagerData>, 'managerData' | 'packageFile'>): Promise<{\n workspaces?: string[];\n packagePaths: string[];\n}> {\n logger.debug(`Detecting deno's node compat Workspaces`);\n\n let filters: string[] | undefined;\n\n // npm workspace\n if (isNonEmptyArray(managerData?.workspaces)) {\n filters = managerData?.workspaces;\n }\n\n // findPackages() matches every package.json below the directory when it is given no patterns\n if (!filters) {\n return { packagePaths: [] };\n }\n\n const localDir = GlobalConfig.get('localDir');\n const packages = await findPackages(\n upath.dirname(ensureLocalPath(packageFile)),\n {\n patterns: filters,\n // Match the ignores used in @pnpm/find-workspace-packages\n ignore: ['**/node_modules/**', '**/bower_components/**'],\n },\n );\n const packagePaths = packages.map((pkg) => {\n const pkgPath = upath.join(pkg.dir, 'package.json');\n return upath.relative(localDir, pkgPath);\n });\n\n return {\n workspaces: filters,\n packagePaths,\n };\n}\n\nexport async function collectPackageJson(\n lockFile: string,\n): Promise<PackageFile<DenoManagerData>[] | null> {\n const lockFiles = [lockFile];\n const packageFiles: PackageFile<DenoManagerData>[] = [];\n const rootPackageJson = getSiblingFileName(lockFile, 'package.json');\n const rootPackageFile =\n await extractDenoCompatiblePackageJson(rootPackageJson);\n if (rootPackageFile) {\n rootPackageFile.lockFiles = lockFiles;\n\n // detect node compat workspaces\n const result = await detectNodeCompatWorkspaces(rootPackageFile);\n const { workspaces, packagePaths } = result;\n rootPackageFile.managerData = {\n packageName: rootPackageFile.managerData?.packageName,\n // override workspace\n workspaces,\n };\n packageFiles.push(rootPackageFile);\n\n for (const packagePath of packagePaths) {\n const packageFile = await extractDenoCompatiblePackageJson(packagePath);\n if (packageFile) {\n packageFile.lockFiles = lockFiles;\n packageFiles.push(packageFile);\n }\n }\n }\n\n return packageFiles;\n}\n"],"mappings":";;;;;;;;;;AAaA,eAAsB,iCACpB,aAC8C;CAC9C,MAAM,qBAAqB,MAAM,cAAc,aAAa,MAAM;CAClE,IAAI,CAAC,oBAAoB;EACvB,OAAO,MAAM,EAAE,YAAY,GAAG,6BAA6B;EAC3D,OAAO;CACT;CAEA,IAAI;CACJ,IAAI;EACF,cAAc,UAAU,oBAAoB,WAAW;CACzD,SAAS,KAAK;EACZ,OAAO,MAAM;GAAE;GAAK;EAAY,GAAG,4BAA4B;EAC/D,OAAO;CACT;CAEA,MAAM,YAAY,mBAAmB,aAAa,WAAW;CAC7D,IAAI,CAAC,WACH,OAAO;CAGT,MAAM,SAAS;CACf,OAAO,cAAc;EACnB,aAAa,UAAU,aAAa;EACpC,YAAY,UAAU,aAAa;CACrC;CACA,OAAO,cAAc;CACrB,OAAO;AACT;AAGA,eAAsB,2BAA2B,EAC/C,aACA,eAIC;CACD,OAAO,MAAM,yCAAyC;CAEtD,IAAI;CAGJ,IAAI,gBAAgB,aAAa,UAAU,GACzC,UAAU,aAAa;CAIzB,IAAI,CAAC,SACH,OAAO,EAAE,cAAc,CAAC,EAAE;CAG5B,MAAM,WAAW,aAAa,IAAI,UAAU;CAS5C,MAAM,gBAAe,MARE,aACrB,MAAM,QAAQ,gBAAgB,WAAW,CAAC,GAC1C;EACE,UAAU;EAEV,QAAQ,CAAC,sBAAsB,wBAAwB;CACzD,CACF,EAAA,CAC8B,KAAK,QAAQ;EACzC,MAAM,UAAU,MAAM,KAAK,IAAI,KAAK,cAAc;EAClD,OAAO,MAAM,SAAS,UAAU,OAAO;CACzC,CAAC;CAED,OAAO;EACL,YAAY;EACZ;CACF;AACF;AAEA,eAAsB,mBACpB,UACgD;CAChD,MAAM,YAAY,CAAC,QAAQ;CAC3B,MAAM,eAA+C,CAAC;CAEtD,MAAM,kBACJ,MAAM,iCAFgB,mBAAmB,UAAU,cAEE,CAAC;CACxD,IAAI,iBAAiB;EACnB,gBAAgB,YAAY;EAI5B,MAAM,EAAE,YAAY,iBAAiB,MADhB,2BAA2B,eAAe;EAE/D,gBAAgB,cAAc;GAC5B,aAAa,gBAAgB,aAAa;GAE1C;EACF;EACA,aAAa,KAAK,eAAe;EAEjC,KAAK,MAAM,eAAe,cAAc;GACtC,MAAM,cAAc,MAAM,iCAAiC,WAAW;GACtE,IAAI,aAAa;IACf,YAAY,YAAY;IACxB,aAAa,KAAK,WAAW;GAC/B;EACF;CACF;CAEA,OAAO;AACT"}
|
|
@@ -242,7 +242,8 @@ function extractPackageFile(content, _packageFile, config) {
|
|
|
242
242
|
}
|
|
243
243
|
if (!deps.length) return null;
|
|
244
244
|
for (const d of deps) d.depType ??= "stage";
|
|
245
|
-
deps.
|
|
245
|
+
const lastStage = deps.filter((d) => d.depType === "stage").at(-1);
|
|
246
|
+
if (lastStage) lastStage.depType = "final";
|
|
246
247
|
return { deps };
|
|
247
248
|
}
|
|
248
249
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.js","names":["ubuntuVersioning.id","debianVersioning.id"],"sources":["../../../../lib/modules/manager/dockerfile/extract.ts"],"sourcesContent":["import {\n isNonEmptyStringAndNotWhitespace,\n isNumericString,\n isString,\n} from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { DockerDatasource } from '../../datasource/docker/index.ts';\nimport * as debianVersioning from '../../versioning/debian/index.ts';\nimport * as ubuntuVersioning from '../../versioning/ubuntu/index.ts';\nimport type {\n ExtractConfig,\n PackageDependency,\n PackageFileContent,\n} from '../types.ts';\n\nconst variableMarker = '$';\n\nexport function extractVariables(image: string): Record<string, string> {\n const variables: Record<string, string> = {};\n const variableRegex = regEx(\n /(?<fullvariable>\\\\?\\$(?<simplearg>\\w+)|\\\\?\\${(?<complexarg>\\w+)(?::.+?)?}+)/gi,\n );\n\n let match: RegExpExecArray | null;\n do {\n match = variableRegex.exec(image);\n if (match?.groups?.fullvariable) {\n variables[match.groups.fullvariable] =\n match.groups?.simplearg || match.groups?.complexarg;\n }\n } while (match);\n\n return variables;\n}\n\nfunction getAutoReplaceTemplate(dep: PackageDependency): string | undefined {\n let template = dep.replaceString;\n\n if (dep.currentValue) {\n let placeholder = '{{#if newValue}}{{newValue}}{{/if}}';\n if (!dep.currentDigest) {\n placeholder += '{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n template = template?.replace(dep.currentValue, placeholder);\n }\n\n if (dep.currentDigest) {\n template = template?.replace(\n dep.currentDigest,\n '{{#if newDigest}}{{newDigest}}{{/if}}',\n );\n }\n\n return template;\n}\n\nfunction processDepForAutoReplace(\n dep: PackageDependency,\n lineNumberRanges: number[][],\n lines: string[],\n linefeed: string,\n): void {\n const lineNumberRangesToReplace: number[][] = [];\n for (const lineNumberRange of lineNumberRanges) {\n for (const lineNumber of lineNumberRange) {\n if (\n (isString(dep.currentValue) &&\n lines[lineNumber].includes(dep.currentValue)) ||\n (isString(dep.currentDigest) &&\n lines[lineNumber].includes(dep.currentDigest))\n ) {\n lineNumberRangesToReplace.push(lineNumberRange);\n }\n }\n }\n\n lineNumberRangesToReplace.sort((a, b) => {\n return a[0] - b[0];\n });\n\n const minLine = lineNumberRangesToReplace[0]?.[0];\n const maxLine = lineNumberRangesToReplace.at(-1)?.[1];\n if (\n lineNumberRanges.length === 1 ||\n minLine === undefined ||\n maxLine === undefined\n ) {\n return;\n }\n\n const unfoldedLineNumbers = Array.from(\n { length: maxLine - minLine + 1 },\n (_v, k) => k + minLine,\n );\n\n dep.replaceString = unfoldedLineNumbers\n .map((lineNumber) => lines[lineNumber])\n .join(linefeed);\n\n if (!dep.currentDigest) {\n dep.replaceString += linefeed;\n }\n\n dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep);\n}\n\nexport function splitImageParts(currentFrom: string): PackageDependency {\n let isVariable = false;\n let cleanedCurrentFrom = currentFrom;\n\n // Check if we have a variable in format of \"${VARIABLE:-<image>:<defaultVal>@<digest>}\"\n // If so, remove everything except the image, defaultVal and digest.\n if (cleanedCurrentFrom?.includes(variableMarker)) {\n const defaultValueRegex = regEx(/^\\${.+?:-\"?(?<value>.*?)\"?}$/);\n const defaultValueMatch =\n defaultValueRegex.exec(cleanedCurrentFrom)?.groups;\n if (defaultValueMatch?.value) {\n isVariable = true;\n cleanedCurrentFrom = defaultValueMatch.value;\n }\n\n if (cleanedCurrentFrom?.includes(variableMarker)) {\n // If cleanedCurrentFrom contains a variable, after cleaning, e.g. \"$REGISTRY/alpine\", we do not support this.\n return {\n skipReason: 'contains-variable',\n };\n }\n }\n\n const [currentDepTag, currentDigest] = cleanedCurrentFrom.split('@');\n const depTagSplit = currentDepTag.split(':');\n let depName: string;\n let currentValue: string | undefined;\n if (depTagSplit.length === 1 || depTagSplit.at(-1)!.includes('/')) {\n depName = currentDepTag;\n } else {\n currentValue = depTagSplit.pop();\n depName = depTagSplit.join(':');\n }\n\n const dep: PackageDependency = {\n depName,\n packageName: depName,\n currentValue,\n currentDigest,\n };\n\n if (isVariable) {\n dep.replaceString = cleanedCurrentFrom;\n\n if (!dep.currentValue) {\n delete dep.currentValue;\n }\n\n if (!dep.currentDigest) {\n delete dep.currentDigest;\n }\n }\n\n return dep;\n}\n\nconst quayRegex = regEx(/^quay\\.io(?::[1-9][0-9]{0,4})?/i);\n\nexport function getDep(\n currentFrom: string | null | undefined,\n specifyReplaceString = true,\n registryAliases?: Record<string, string>,\n): PackageDependency {\n if (\n !isString(currentFrom) ||\n !isNonEmptyStringAndNotWhitespace(currentFrom)\n ) {\n return {\n skipReason: 'invalid-value',\n };\n }\n\n // Resolve registry aliases first so that we don't need special casing later on:\n for (const [name, value] of Object.entries(coerceObject(registryAliases))) {\n // Allow `${VAR}`/`${VAR:-...}` keys to match without a trailing slash\n // (`}` is an unambiguous boundary). Bare identifier keys like\n // `$CI_REGISTRY` still require `/` so they can't eat `$CI_REGISTRY_IMAGE/`.\n const matchedWithSlash = currentFrom.startsWith(`${name}/`);\n const matchedAtBoundary =\n name.endsWith('}') && currentFrom.startsWith(name);\n if (!matchedWithSlash && !matchedAtBoundary) {\n continue;\n }\n const depName = currentFrom.slice(\n matchedWithSlash ? name.length + 1 : name.length,\n );\n // An empty alias value means \"no registry prefix\", i.e. Docker Hub.\n const valueWithSlash = value ? ensureTrailingSlash(value) : '';\n const dep = getDep(`${valueWithSlash}${depName}`, false);\n // TODO: when the inner getDep strips a `library/` prefix (or similar)\n // the depName no longer starts with `valueWithSlash` and the alias-rooted\n // depName is not restored.\n if (dep.depName?.startsWith(valueWithSlash)) {\n dep.packageName = dep.depName;\n const [imageAndTag] = currentFrom.split('@');\n dep.depName = dep.currentValue\n ? imageAndTag.substring(0, imageAndTag.lastIndexOf(':'))\n : imageAndTag;\n }\n if (specifyReplaceString) {\n dep.replaceString = currentFrom;\n dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep);\n }\n return dep;\n }\n\n const dep = splitImageParts(currentFrom);\n if (specifyReplaceString) {\n dep.replaceString ??= currentFrom;\n dep.autoReplaceStringTemplate =\n '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n dep.datasource = DockerDatasource.id;\n\n // Pretty up special prefixes\n if (dep.depName) {\n const specialPrefixes = ['amd64', 'arm64', 'library'];\n for (const prefix of specialPrefixes) {\n if (dep.depName.startsWith(`${prefix}/`)) {\n dep.depName = dep.depName.replace(`${prefix}/`, '');\n if (specifyReplaceString) {\n dep.autoReplaceStringTemplate =\n '{{packageName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n }\n }\n }\n\n if (dep.depName === 'ubuntu' || dep.depName?.endsWith('/ubuntu')) {\n dep.versioning = ubuntuVersioning.id;\n }\n\n if (\n (dep.depName === 'debian' || dep.depName?.endsWith('/debian')) &&\n debianVersioning.api.isVersion(dep.currentValue)\n ) {\n dep.versioning = debianVersioning.id;\n }\n\n // Don't display quay.io ports\n if (dep.depName && quayRegex.test(dep.depName)) {\n const depName = dep.depName.replace(quayRegex, 'quay.io');\n if (depName !== dep.depName) {\n dep.depName = depName;\n dep.autoReplaceStringTemplate =\n '{{packageName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n }\n\n return dep;\n}\n\nexport function extractPackageFile(\n content: string,\n _packageFile: string,\n config: ExtractConfig,\n): PackageFileContent | null {\n const sanitizedContent = content.replace(regEx(/^\\uFEFF/), ''); // remove bom marker\n const deps: PackageDependency[] = [];\n const stageNames: string[] = [];\n const args: Record<string, string> = {};\n const argsLines: Record<string, number[]> = {};\n\n let escapeChar = '\\\\\\\\';\n let lookForEscapeChar = true;\n let lookForSyntaxDirective = true;\n\n const lineFeed = sanitizedContent.includes('\\r\\n') ? '\\r\\n' : '\\n';\n const lines = sanitizedContent.split(newlineRegex);\n for (let lineNumber = 0; lineNumber < lines.length; ) {\n const lineNumberInstrStart = lineNumber;\n let instruction = lines[lineNumber];\n\n if (lookForEscapeChar) {\n const directivesMatch = regEx(\n /^[ \\t]*#[ \\t]*(?<directive>syntax|escape)[ \\t]*=[ \\t]*(?<escapeChar>\\S)/i,\n ).exec(instruction);\n if (!directivesMatch) {\n lookForEscapeChar = false;\n } else if (directivesMatch.groups?.directive.toLowerCase() === 'escape') {\n if (directivesMatch.groups?.escapeChar === '`') {\n escapeChar = '`';\n }\n lookForEscapeChar = false;\n }\n }\n\n if (lookForSyntaxDirective) {\n const syntaxRegex = regEx(\n '^#[ \\\\t]*syntax[ \\\\t]*=[ \\\\t]*(?<image>\\\\S+)',\n 'im',\n );\n const syntaxMatch = instruction.match(syntaxRegex);\n if (syntaxMatch?.groups?.image) {\n const syntaxImage = syntaxMatch.groups.image;\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n const dep = getDep(syntaxImage, true, config.registryAliases);\n dep.depType = 'syntax';\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.trace(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile # syntax',\n );\n deps.push(dep);\n }\n lookForSyntaxDirective = false;\n }\n\n const lineContinuationRegex = regEx(`${escapeChar}[ \\\\t]*$|^[ \\\\t]*#`, 'm');\n let lineLookahead = instruction;\n while (\n !lookForEscapeChar &&\n !instruction.trimStart().startsWith('#') &&\n lineContinuationRegex.test(lineLookahead)\n ) {\n lineLookahead = lines[++lineNumber] || '';\n instruction += `\\n${lineLookahead}`;\n }\n\n const argRegex = regEx(\n `^[ \\\\t]*ARG(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n)+(?<name>\\\\w+)[ =](?<value>\\\\S*)`,\n 'im',\n );\n const argMatch = argRegex.exec(instruction);\n if (argMatch?.groups?.name) {\n argsLines[argMatch.groups.name] = [lineNumberInstrStart, lineNumber];\n let argMatchValue = argMatch.groups?.value;\n\n if (\n (argMatchValue.startsWith('\"') && argMatchValue.endsWith('\"')) ||\n (argMatchValue.startsWith(\"'\") && argMatchValue.endsWith(\"'\"))\n ) {\n argMatchValue = argMatchValue.slice(1, -1);\n }\n\n args[argMatch.groups.name] = argMatchValue || '';\n }\n\n const fromRegex = regEx(\n `^[ \\\\t]*FROM(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--platform=\\\\S+)+(?<image>\\\\S+)(?:(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n)+as[ \\\\t]+(?<name>\\\\S+))?`,\n 'im',\n );\n const fromMatch = instruction.match(fromRegex);\n if (fromMatch?.groups?.image) {\n let fromImage = fromMatch.groups.image;\n const lineNumberRanges: number[][] = [[lineNumberInstrStart, lineNumber]];\n\n if (fromImage.includes(variableMarker)) {\n const variables = extractVariables(fromImage);\n for (const [fullVariable, argName] of Object.entries(variables)) {\n const resolvedArgValue = args[argName];\n if (resolvedArgValue || resolvedArgValue === '') {\n fromImage = fromImage.replaceAll(fullVariable, resolvedArgValue);\n lineNumberRanges.push(argsLines[argName]);\n }\n }\n }\n\n if (fromMatch.groups?.name) {\n logger.debug(\n `Found a multistage build stage name: ${fromMatch.groups.name}`,\n );\n stageNames.push(fromMatch.groups.name);\n }\n if (fromImage === 'scratch') {\n logger.debug('Skipping scratch');\n } else if (fromImage && stageNames.includes(fromImage)) {\n logger.debug(`Skipping alias FROM image:${fromImage}`);\n } else {\n const dep = getDep(fromImage, true, config.registryAliases);\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.trace(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile FROM',\n );\n deps.push(dep);\n }\n }\n\n const copyFromRegex = regEx(\n `^[ \\\\t]*COPY(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--[a-z]+(?:=[a-zA-Z0-9_.:-]+?)?)+--from=(?<image>\\\\S+)`,\n 'im',\n );\n const copyFromMatch = instruction.match(copyFromRegex);\n if (copyFromMatch?.groups?.image) {\n if (stageNames.includes(copyFromMatch.groups.image)) {\n logger.debug(\n { image: copyFromMatch.groups.image },\n 'Skipping alias COPY --from',\n );\n } else if (isNumericString(copyFromMatch.groups.image)) {\n logger.debug(\n { image: copyFromMatch.groups.image },\n 'Skipping index reference COPY --from',\n );\n } else {\n const dep = getDep(\n copyFromMatch.groups.image,\n true,\n config.registryAliases,\n );\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.debug(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile COPY --from',\n );\n deps.push(dep);\n }\n }\n\n const runMountFromRegex = regEx(\n `^[ \\\\t]*RUN(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--[a-z]+(?:=[a-zA-Z0-9_.:-]+?)?)+--mount=(?:\\\\S*=\\\\S*,)*from=(?<image>[^, ]+)`,\n 'im',\n );\n const runMountFromMatch = instruction.match(runMountFromRegex);\n if (runMountFromMatch?.groups?.image) {\n if (stageNames.includes(runMountFromMatch.groups.image)) {\n logger.debug(\n { image: runMountFromMatch.groups.image },\n 'Skipping alias RUN --mount=from',\n );\n } else {\n const dep = getDep(\n runMountFromMatch.groups.image,\n true,\n config.registryAliases,\n );\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.debug(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile RUN --mount=from',\n );\n deps.push(dep);\n }\n }\n\n lineNumber += 1;\n }\n\n if (!deps.length) {\n return null;\n }\n for (const d of deps) {\n d.depType ??= 'stage';\n }\n deps.at(-1)!.depType = 'final';\n return { deps };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extract.js","names":["ubuntuVersioning.id","debianVersioning.id"],"sources":["../../../../lib/modules/manager/dockerfile/extract.ts"],"sourcesContent":["import {\n isNonEmptyStringAndNotWhitespace,\n isNumericString,\n isString,\n} from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { DockerDatasource } from '../../datasource/docker/index.ts';\nimport * as debianVersioning from '../../versioning/debian/index.ts';\nimport * as ubuntuVersioning from '../../versioning/ubuntu/index.ts';\nimport type {\n ExtractConfig,\n PackageDependency,\n PackageFileContent,\n} from '../types.ts';\n\nconst variableMarker = '$';\n\nexport function extractVariables(image: string): Record<string, string> {\n const variables: Record<string, string> = {};\n const variableRegex = regEx(\n /(?<fullvariable>\\\\?\\$(?<simplearg>\\w+)|\\\\?\\${(?<complexarg>\\w+)(?::.+?)?}+)/gi,\n );\n\n let match: RegExpExecArray | null;\n do {\n match = variableRegex.exec(image);\n if (match?.groups?.fullvariable) {\n variables[match.groups.fullvariable] =\n match.groups?.simplearg || match.groups?.complexarg;\n }\n } while (match);\n\n return variables;\n}\n\nfunction getAutoReplaceTemplate(dep: PackageDependency): string | undefined {\n let template = dep.replaceString;\n\n if (dep.currentValue) {\n let placeholder = '{{#if newValue}}{{newValue}}{{/if}}';\n if (!dep.currentDigest) {\n placeholder += '{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n template = template?.replace(dep.currentValue, placeholder);\n }\n\n if (dep.currentDigest) {\n template = template?.replace(\n dep.currentDigest,\n '{{#if newDigest}}{{newDigest}}{{/if}}',\n );\n }\n\n return template;\n}\n\nfunction processDepForAutoReplace(\n dep: PackageDependency,\n lineNumberRanges: number[][],\n lines: string[],\n linefeed: string,\n): void {\n const lineNumberRangesToReplace: number[][] = [];\n for (const lineNumberRange of lineNumberRanges) {\n for (const lineNumber of lineNumberRange) {\n if (\n (isString(dep.currentValue) &&\n lines[lineNumber].includes(dep.currentValue)) ||\n (isString(dep.currentDigest) &&\n lines[lineNumber].includes(dep.currentDigest))\n ) {\n lineNumberRangesToReplace.push(lineNumberRange);\n }\n }\n }\n\n lineNumberRangesToReplace.sort((a, b) => {\n return a[0] - b[0];\n });\n\n const minLine = lineNumberRangesToReplace[0]?.[0];\n const maxLine = lineNumberRangesToReplace.at(-1)?.[1];\n if (\n lineNumberRanges.length === 1 ||\n minLine === undefined ||\n maxLine === undefined\n ) {\n return;\n }\n\n const unfoldedLineNumbers = Array.from(\n { length: maxLine - minLine + 1 },\n (_v, k) => k + minLine,\n );\n\n dep.replaceString = unfoldedLineNumbers\n .map((lineNumber) => lines[lineNumber])\n .join(linefeed);\n\n if (!dep.currentDigest) {\n dep.replaceString += linefeed;\n }\n\n dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep);\n}\n\nexport function splitImageParts(currentFrom: string): PackageDependency {\n let isVariable = false;\n let cleanedCurrentFrom = currentFrom;\n\n // Check if we have a variable in format of \"${VARIABLE:-<image>:<defaultVal>@<digest>}\"\n // If so, remove everything except the image, defaultVal and digest.\n if (cleanedCurrentFrom?.includes(variableMarker)) {\n const defaultValueRegex = regEx(/^\\${.+?:-\"?(?<value>.*?)\"?}$/);\n const defaultValueMatch =\n defaultValueRegex.exec(cleanedCurrentFrom)?.groups;\n if (defaultValueMatch?.value) {\n isVariable = true;\n cleanedCurrentFrom = defaultValueMatch.value;\n }\n\n if (cleanedCurrentFrom?.includes(variableMarker)) {\n // If cleanedCurrentFrom contains a variable, after cleaning, e.g. \"$REGISTRY/alpine\", we do not support this.\n return {\n skipReason: 'contains-variable',\n };\n }\n }\n\n const [currentDepTag, currentDigest] = cleanedCurrentFrom.split('@');\n const depTagSplit = currentDepTag.split(':');\n let depName: string;\n let currentValue: string | undefined;\n if (depTagSplit.length === 1 || depTagSplit.at(-1)!.includes('/')) {\n depName = currentDepTag;\n } else {\n currentValue = depTagSplit.pop();\n depName = depTagSplit.join(':');\n }\n\n const dep: PackageDependency = {\n depName,\n packageName: depName,\n currentValue,\n currentDigest,\n };\n\n if (isVariable) {\n dep.replaceString = cleanedCurrentFrom;\n\n if (!dep.currentValue) {\n delete dep.currentValue;\n }\n\n if (!dep.currentDigest) {\n delete dep.currentDigest;\n }\n }\n\n return dep;\n}\n\nconst quayRegex = regEx(/^quay\\.io(?::[1-9][0-9]{0,4})?/i);\n\nexport function getDep(\n currentFrom: string | null | undefined,\n specifyReplaceString = true,\n registryAliases?: Record<string, string>,\n): PackageDependency {\n if (\n !isString(currentFrom) ||\n !isNonEmptyStringAndNotWhitespace(currentFrom)\n ) {\n return {\n skipReason: 'invalid-value',\n };\n }\n\n // Resolve registry aliases first so that we don't need special casing later on:\n for (const [name, value] of Object.entries(coerceObject(registryAliases))) {\n // Allow `${VAR}`/`${VAR:-...}` keys to match without a trailing slash\n // (`}` is an unambiguous boundary). Bare identifier keys like\n // `$CI_REGISTRY` still require `/` so they can't eat `$CI_REGISTRY_IMAGE/`.\n const matchedWithSlash = currentFrom.startsWith(`${name}/`);\n const matchedAtBoundary =\n name.endsWith('}') && currentFrom.startsWith(name);\n if (!matchedWithSlash && !matchedAtBoundary) {\n continue;\n }\n const depName = currentFrom.slice(\n matchedWithSlash ? name.length + 1 : name.length,\n );\n // An empty alias value means \"no registry prefix\", i.e. Docker Hub.\n const valueWithSlash = value ? ensureTrailingSlash(value) : '';\n const dep = getDep(`${valueWithSlash}${depName}`, false);\n // TODO: when the inner getDep strips a `library/` prefix (or similar)\n // the depName no longer starts with `valueWithSlash` and the alias-rooted\n // depName is not restored.\n if (dep.depName?.startsWith(valueWithSlash)) {\n dep.packageName = dep.depName;\n const [imageAndTag] = currentFrom.split('@');\n dep.depName = dep.currentValue\n ? imageAndTag.substring(0, imageAndTag.lastIndexOf(':'))\n : imageAndTag;\n }\n if (specifyReplaceString) {\n dep.replaceString = currentFrom;\n dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep);\n }\n return dep;\n }\n\n const dep = splitImageParts(currentFrom);\n if (specifyReplaceString) {\n dep.replaceString ??= currentFrom;\n dep.autoReplaceStringTemplate =\n '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n dep.datasource = DockerDatasource.id;\n\n // Pretty up special prefixes\n if (dep.depName) {\n const specialPrefixes = ['amd64', 'arm64', 'library'];\n for (const prefix of specialPrefixes) {\n if (dep.depName.startsWith(`${prefix}/`)) {\n dep.depName = dep.depName.replace(`${prefix}/`, '');\n if (specifyReplaceString) {\n dep.autoReplaceStringTemplate =\n '{{packageName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n }\n }\n }\n\n if (dep.depName === 'ubuntu' || dep.depName?.endsWith('/ubuntu')) {\n dep.versioning = ubuntuVersioning.id;\n }\n\n if (\n (dep.depName === 'debian' || dep.depName?.endsWith('/debian')) &&\n debianVersioning.api.isVersion(dep.currentValue)\n ) {\n dep.versioning = debianVersioning.id;\n }\n\n // Don't display quay.io ports\n if (dep.depName && quayRegex.test(dep.depName)) {\n const depName = dep.depName.replace(quayRegex, 'quay.io');\n if (depName !== dep.depName) {\n dep.depName = depName;\n dep.autoReplaceStringTemplate =\n '{{packageName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';\n }\n }\n\n return dep;\n}\n\nexport function extractPackageFile(\n content: string,\n _packageFile: string,\n config: ExtractConfig,\n): PackageFileContent | null {\n const sanitizedContent = content.replace(regEx(/^\\uFEFF/), ''); // remove bom marker\n const deps: PackageDependency[] = [];\n const stageNames: string[] = [];\n const args: Record<string, string> = {};\n const argsLines: Record<string, number[]> = {};\n\n let escapeChar = '\\\\\\\\';\n let lookForEscapeChar = true;\n let lookForSyntaxDirective = true;\n\n const lineFeed = sanitizedContent.includes('\\r\\n') ? '\\r\\n' : '\\n';\n const lines = sanitizedContent.split(newlineRegex);\n for (let lineNumber = 0; lineNumber < lines.length; ) {\n const lineNumberInstrStart = lineNumber;\n let instruction = lines[lineNumber];\n\n if (lookForEscapeChar) {\n const directivesMatch = regEx(\n /^[ \\t]*#[ \\t]*(?<directive>syntax|escape)[ \\t]*=[ \\t]*(?<escapeChar>\\S)/i,\n ).exec(instruction);\n if (!directivesMatch) {\n lookForEscapeChar = false;\n } else if (directivesMatch.groups?.directive.toLowerCase() === 'escape') {\n if (directivesMatch.groups?.escapeChar === '`') {\n escapeChar = '`';\n }\n lookForEscapeChar = false;\n }\n }\n\n if (lookForSyntaxDirective) {\n const syntaxRegex = regEx(\n '^#[ \\\\t]*syntax[ \\\\t]*=[ \\\\t]*(?<image>\\\\S+)',\n 'im',\n );\n const syntaxMatch = instruction.match(syntaxRegex);\n if (syntaxMatch?.groups?.image) {\n const syntaxImage = syntaxMatch.groups.image;\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n const dep = getDep(syntaxImage, true, config.registryAliases);\n dep.depType = 'syntax';\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.trace(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile # syntax',\n );\n deps.push(dep);\n }\n lookForSyntaxDirective = false;\n }\n\n const lineContinuationRegex = regEx(`${escapeChar}[ \\\\t]*$|^[ \\\\t]*#`, 'm');\n let lineLookahead = instruction;\n while (\n !lookForEscapeChar &&\n !instruction.trimStart().startsWith('#') &&\n lineContinuationRegex.test(lineLookahead)\n ) {\n lineLookahead = lines[++lineNumber] || '';\n instruction += `\\n${lineLookahead}`;\n }\n\n const argRegex = regEx(\n `^[ \\\\t]*ARG(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n)+(?<name>\\\\w+)[ =](?<value>\\\\S*)`,\n 'im',\n );\n const argMatch = argRegex.exec(instruction);\n if (argMatch?.groups?.name) {\n argsLines[argMatch.groups.name] = [lineNumberInstrStart, lineNumber];\n let argMatchValue = argMatch.groups?.value;\n\n if (\n (argMatchValue.startsWith('\"') && argMatchValue.endsWith('\"')) ||\n (argMatchValue.startsWith(\"'\") && argMatchValue.endsWith(\"'\"))\n ) {\n argMatchValue = argMatchValue.slice(1, -1);\n }\n\n args[argMatch.groups.name] = argMatchValue || '';\n }\n\n const fromRegex = regEx(\n `^[ \\\\t]*FROM(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--platform=\\\\S+)+(?<image>\\\\S+)(?:(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n)+as[ \\\\t]+(?<name>\\\\S+))?`,\n 'im',\n );\n const fromMatch = instruction.match(fromRegex);\n if (fromMatch?.groups?.image) {\n let fromImage = fromMatch.groups.image;\n const lineNumberRanges: number[][] = [[lineNumberInstrStart, lineNumber]];\n\n if (fromImage.includes(variableMarker)) {\n const variables = extractVariables(fromImage);\n for (const [fullVariable, argName] of Object.entries(variables)) {\n const resolvedArgValue = args[argName];\n if (resolvedArgValue || resolvedArgValue === '') {\n fromImage = fromImage.replaceAll(fullVariable, resolvedArgValue);\n lineNumberRanges.push(argsLines[argName]);\n }\n }\n }\n\n if (fromMatch.groups?.name) {\n logger.debug(\n `Found a multistage build stage name: ${fromMatch.groups.name}`,\n );\n stageNames.push(fromMatch.groups.name);\n }\n if (fromImage === 'scratch') {\n logger.debug('Skipping scratch');\n } else if (fromImage && stageNames.includes(fromImage)) {\n logger.debug(`Skipping alias FROM image:${fromImage}`);\n } else {\n const dep = getDep(fromImage, true, config.registryAliases);\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.trace(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile FROM',\n );\n deps.push(dep);\n }\n }\n\n const copyFromRegex = regEx(\n `^[ \\\\t]*COPY(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--[a-z]+(?:=[a-zA-Z0-9_.:-]+?)?)+--from=(?<image>\\\\S+)`,\n 'im',\n );\n const copyFromMatch = instruction.match(copyFromRegex);\n if (copyFromMatch?.groups?.image) {\n if (stageNames.includes(copyFromMatch.groups.image)) {\n logger.debug(\n { image: copyFromMatch.groups.image },\n 'Skipping alias COPY --from',\n );\n } else if (isNumericString(copyFromMatch.groups.image)) {\n logger.debug(\n { image: copyFromMatch.groups.image },\n 'Skipping index reference COPY --from',\n );\n } else {\n const dep = getDep(\n copyFromMatch.groups.image,\n true,\n config.registryAliases,\n );\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.debug(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile COPY --from',\n );\n deps.push(dep);\n }\n }\n\n const runMountFromRegex = regEx(\n `^[ \\\\t]*RUN(?:${escapeChar}[ \\\\t]*\\\\r?\\\\n| |\\\\t|#.*?\\\\r?\\\\n|--[a-z]+(?:=[a-zA-Z0-9_.:-]+?)?)+--mount=(?:\\\\S*=\\\\S*,)*from=(?<image>[^, ]+)`,\n 'im',\n );\n const runMountFromMatch = instruction.match(runMountFromRegex);\n if (runMountFromMatch?.groups?.image) {\n if (stageNames.includes(runMountFromMatch.groups.image)) {\n logger.debug(\n { image: runMountFromMatch.groups.image },\n 'Skipping alias RUN --mount=from',\n );\n } else {\n const dep = getDep(\n runMountFromMatch.groups.image,\n true,\n config.registryAliases,\n );\n const lineNumberRanges: number[][] = [\n [lineNumberInstrStart, lineNumber],\n ];\n processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed);\n logger.debug(\n {\n depName: dep.depName,\n currentValue: dep.currentValue,\n currentDigest: dep.currentDigest,\n },\n 'Dockerfile RUN --mount=from',\n );\n deps.push(dep);\n }\n }\n\n lineNumber += 1;\n }\n\n if (!deps.length) {\n return null;\n }\n for (const d of deps) {\n d.depType ??= 'stage';\n }\n // find the last `stage`, and treat it as the `final` stage\n const lastStage = deps.filter((d) => d.depType === 'stage').at(-1);\n if (lastStage) {\n lastStage.depType = 'final';\n }\n return { deps };\n}\n"],"mappings":"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"}
|
|
@@ -32,12 +32,12 @@ hashMap.set("copier", "d70688a4a74d7239229a69eb1e3c5af19da0a38d12b9324c92ff86776
|
|
|
32
32
|
hashMap.set("cpanfile", "07813fec3f3c2197056500e9266a0553b9774c02f2c74d5ca2e213188c7c12d3");
|
|
33
33
|
hashMap.set("crossplane", "5c26b1201a1a51454ffb94d829e223a76a781569bf79cdb1e47087c30233ec40");
|
|
34
34
|
hashMap.set("crow", "eb9a5f9f95041855dded67bcce3dd54724f690995ed6268d272e8a666ff28fd0");
|
|
35
|
-
hashMap.set("deno", "
|
|
35
|
+
hashMap.set("deno", "bdb28fcfdc032e3ea75d2569213fef207fd18bcaa46a6e4ea933150e49df24bf");
|
|
36
36
|
hashMap.set("deps-edn", "7b6ac92be04b44fdf1da8755550a6417bb294908158119c8fff10adeb05048d2");
|
|
37
37
|
hashMap.set("devbox", "abca7468e2363c04b7e4b85bfdbc75e11ed38e9d3b84b9ccc6d1a4c34a8fc1fb");
|
|
38
38
|
hashMap.set("devcontainer", "24320ed1cb6191d04cb8b2707214d82c08c682597aed1d84f250aa00ad1632ec");
|
|
39
39
|
hashMap.set("docker-compose", "a9c27711356fbda8dd14f21e046936e1e43f18c5528325b468d89937f76fe1e7");
|
|
40
|
-
hashMap.set("dockerfile", "
|
|
40
|
+
hashMap.set("dockerfile", "a83e9e93f31576697d45fd60a0b44f7d14a610752e695a62507624ab2dbb2162");
|
|
41
41
|
hashMap.set("droneci", "e2039bb37c2d63c53027b188d1f0faa7c8923dcbfe6cf3851fba8d4e9f43a358");
|
|
42
42
|
hashMap.set("fleet", "6b091fd5b8c2e9fc5d5b81ba34befec915d585d45cbc175c851ccc1555372925");
|
|
43
43
|
hashMap.set("flux", "70833dd068ea0a746a9392469e7904021562c7629428d0cd554603bad4eb6ce5");
|
|
@@ -75,7 +75,7 @@ hashMap.set("mise", "bc13ff3b8b16a2e79f450017920e87da37fbfbf61fc8c95ddeaa7cfd451
|
|
|
75
75
|
hashMap.set("mix", "473bb870c00b270faae93c4614873f644ad516f762acf07f773b12a7b8e01d19");
|
|
76
76
|
hashMap.set("nix", "a9d4ae3f9f01abb71dc9ebc12a9cd8bec237ad9d2dabfbf4f5ffd59e56c9a612");
|
|
77
77
|
hashMap.set("nodenv", "ac652c28481b001f7471f4183eac07b45d98ecbe83efc275830b0a1b2e0459b8");
|
|
78
|
-
hashMap.set("npm", "
|
|
78
|
+
hashMap.set("npm", "e563e8a7ad94b90ca5a777e1a88af9638f2f8a9e2a142ed317c8ae5758d72cbd");
|
|
79
79
|
hashMap.set("nuget", "136bc3226e77b8fe65940454dc2c858fde86c2e0da6dbbdf71a5269ab137caee");
|
|
80
80
|
hashMap.set("nvm", "3eb77c7b0acf6d64753de78fad2499b352719853aa6872878c40675d14152322");
|
|
81
81
|
hashMap.set("ocb", "032b216684c14b0954e0bb019513a2aca3faaee5748587acb668d377d7c891ca");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.generated.js","names":[],"sources":["../../../lib/modules/manager/fingerprint.generated.ts"],"sourcesContent":["export const hashMap = new Map<string, string>();\n\nhashMap.set('ansible','a52394a36ac5517f7330473c31d93aa05b2ce607c5e951b48f25a4693cd20a81');\nhashMap.set('ansible-galaxy','0a264d6be73953d801510fdeff271e4071c274339569c6dab4e2a128eaf4869f');\nhashMap.set('ant','2df5943cf0ed19a21b94df13729dbb925655548130caf37e3e22bebaed518e17');\nhashMap.set('apm','146e023bced69a0625adfac29148a5254d9457ad5a48931c7047299f6452cb43');\nhashMap.set('argocd','5d35b1992e53130bf83b0e59a0f90ccd3a78919974c69044f306dc5d162f48ce');\nhashMap.set('asdf','430eb99b58171700c8a59c78b9e648575e9b176b781d90dd10a710f7b69015bb');\nhashMap.set('azure-pipelines','6bf7782e8a02fc87dc5d84aab59e517c09df51fd23cf57805e62207dbd5efdb5');\nhashMap.set('batect','375d39b432013bedb1330cf40a2199dd822751b28578214f219e7bab98594b8d');\nhashMap.set('batect-wrapper','d999355511ea7f4053325a18b8cfc8d2b586c61e6760c35e557d383a673e3939');\nhashMap.set('bazel','ef00591c6f09069550ef97ff7ff5e387b9dd3df51cdecc9ef941169b19315396');\nhashMap.set('bazel-module','65e6cb3d6c0d9b3b1fda22388b6c72148c518cd06e8c434b46e4645384381bad');\nhashMap.set('bazelisk','a83328e3c5b4c3f5af2e425f680b4852c08ef5c6d035a248e09577136cf3b14d');\nhashMap.set('bicep','7246e0bfc06e0e28cbb03ac088c5591f648956b086e106aeb251fe5d628329db');\nhashMap.set('bitbucket-pipelines','59c0503494ab1442b127914503c01b97ac17b6742b19c632292d5aa24de115cd');\nhashMap.set('bitrise','478dfd316221fad7c29e177c70d1018d832fb2626b53308a5d0f1f0380e69f42');\nhashMap.set('buildkite','b8b404f53cd5d61c39153fddf93945e621471c4ac6aa9960c881cd868922bb4c');\nhashMap.set('buildpacks','6bef3cb04d66b5cfbb195adb4829bcbccae6408518706744d291bacf0610421f');\nhashMap.set('bun','3d40239b69d462ab843562ff8ee5bfacbc46d4976d38d0af17d037973f174e3e');\nhashMap.set('bun-version','df3ae8e4a5de1fa1b4544f3d7fc8117e80adb1e151c46d1ede54a4dbea6521e4');\nhashMap.set('bundler','9c5b8a2e7b84a545bbd6cc74c1fd9422f167da67c41bcc9bfb4cc2098b41de0c');\nhashMap.set('cake','9ebd8b481220b30a8860121d26184540a1a2fcc05ef780df9295dea39b386fad');\nhashMap.set('cargo','e8f43c68e874a9f3e684c2f3323b77a2799c49a1a538495ae75fb3a3bdd1f786');\nhashMap.set('cdnurl','9a81c8e3c6ad6c788498c99fc1067ffdfcd92a427c3afaf8c0130975d83131f2');\nhashMap.set('circleci','91cbeb33ea20f9838e2c81a1195eb806f0b38fa282bc3679f62552f20575ca85');\nhashMap.set('cloudbuild','f4e40388944652c8a19f8518771ac8d3f3c4ccf81ddef0e68b463aca833cb73c');\nhashMap.set('cocoapods','f832e2beef885bb3fd697ed9bb3e8cd742926bfec37ff41212edd2dbb4edb3ba');\nhashMap.set('composer','3906e56e8decf5d5e51cccdb46d2ce4eb4ff8efc8b0596b859f0f7210e13ed45');\nhashMap.set('conan','1cfe3887dba15d974fbbad3c0f49b7b745a6bad194ff95f067976ce3ae47d2bf');\nhashMap.set('copier','d70688a4a74d7239229a69eb1e3c5af19da0a38d12b9324c92ff86776fa0dec7');\nhashMap.set('cpanfile','07813fec3f3c2197056500e9266a0553b9774c02f2c74d5ca2e213188c7c12d3');\nhashMap.set('crossplane','5c26b1201a1a51454ffb94d829e223a76a781569bf79cdb1e47087c30233ec40');\nhashMap.set('crow','eb9a5f9f95041855dded67bcce3dd54724f690995ed6268d272e8a666ff28fd0');\nhashMap.set('deno','8f7d06d6e9de36f92d6939097d2c04c1cd87d6901f3ed36ea355bdb0da8a9734');\nhashMap.set('deps-edn','7b6ac92be04b44fdf1da8755550a6417bb294908158119c8fff10adeb05048d2');\nhashMap.set('devbox','abca7468e2363c04b7e4b85bfdbc75e11ed38e9d3b84b9ccc6d1a4c34a8fc1fb');\nhashMap.set('devcontainer','24320ed1cb6191d04cb8b2707214d82c08c682597aed1d84f250aa00ad1632ec');\nhashMap.set('docker-compose','a9c27711356fbda8dd14f21e046936e1e43f18c5528325b468d89937f76fe1e7');\nhashMap.set('dockerfile','84e3949ac7e9ac94451a103545dc1e8f1a99147283e56d816430efed4bec6cc8');\nhashMap.set('droneci','e2039bb37c2d63c53027b188d1f0faa7c8923dcbfe6cf3851fba8d4e9f43a358');\nhashMap.set('fleet','6b091fd5b8c2e9fc5d5b81ba34befec915d585d45cbc175c851ccc1555372925');\nhashMap.set('flux','70833dd068ea0a746a9392469e7904021562c7629428d0cd554603bad4eb6ce5');\nhashMap.set('fvm','9b161df0f14bc6e536368952adf373e343630097121a913cea60ee284027fb90');\nhashMap.set('git-submodules','df8bb92b2906d8cddda2d4b302ee503f8002e3554d32d74cef2f584fe891f38f');\nhashMap.set('github-actions','28532556bb676239d3af375c21af30cfe392ff029f8a695391e0fc1203fc0cab');\nhashMap.set('gitlabci','a5e1e66ef461e1c1e71062f85f35a212417e23627f4b002810f9a98295d6e672');\nhashMap.set('gitlabci-include','8860a15ab516fde00694f9bd9bf56fce4addafe5a55b5ddb9a4ec477d301d351');\nhashMap.set('glasskube','93e7b9000a17efa15a1abaaf320b5af9169b1ecd828fc0c881d98570ef9d9e30');\nhashMap.set('gleam','a3bd05c4814eb57872d39979a40342a8ee23e61a85e2ab25e84346e8215dadc1');\nhashMap.set('gomod','1ed58f0af452a6776ae1899466851bab659f8287c90cff96619068d8184048d5');\nhashMap.set('gradle','ef9db616bf60e9a3623fff0e41df274a457333a37f37c24f3841a3ca3a531449');\nhashMap.set('gradle-wrapper','77f7e75be2597b847fc821ff8ff5bb4b3e37ab3cc4e780e22ce75e0342becac8');\nhashMap.set('haskell-cabal','f158b7725e3143dfd2950e3de0bbccc2a61cd7eba87f7a54c5057e01252348e2');\nhashMap.set('helm-requirements','7ee9dace4c036dfe113c0c0e46369d8b83a739caa831660142ca98d3236a180a');\nhashMap.set('helm-values','01069e887d4f3b55ca62a3c0dc66d8620264e1426207be9eb240a10c1ad5e412');\nhashMap.set('helmfile','433d1d0fd4a81f191a0b553ab52419627b1d7aa0eb3099d53f7ae4a1d076c221');\nhashMap.set('helmsman','c4af380756eae8dc988d24c91e9749ce0a97b201daa55f59d2394c1c90d73779');\nhashMap.set('helmv3','cc9396b650a7226eeae1bed6b620cfb6d12e6a8ad52faf80b527ffaeb2b68066');\nhashMap.set('hermit','0fb25b7766c3a264fbb765ff75b1542b24136c4c9f933696d4a5aecfed637071');\nhashMap.set('homeassistant-manifest','05043c6db870cffbb6f8f3e351c025e3de227eaae0b24134b796aec46f84b65f');\nhashMap.set('homebrew','9c64a4f1475b1c2052372e566c9190f32ae8acd1c54313031d55ae8772388367');\nhashMap.set('html','81fa6c2bf2b868596584a48b949645207a2aa3081951ed99183ee50b70b77d5f');\nhashMap.set('jenkins','7bfb09418a132e052579196633bac78ac947cf93f1e70748ea1b3da929874b87');\nhashMap.set('jsonnet-bundler','06d163b939b258e1e2847a12a1249cb7d68d77c7bcf13c6d1a0a916744eba5cc');\nhashMap.set('kotlin-script','95ebc844c040ca047321b207d525220e29774a2a1fe06f9639e8353c66908564');\nhashMap.set('kubernetes','321e7d77fb3600dd4c00a86eaa1294927e7f92300b74fa2977d813dcaa3bb4de');\nhashMap.set('kustomize','558fcfe5b20f1eb4aba0d3c755a060bb4561611e99db7000786ce4edcd3f7894');\nhashMap.set('leiningen','a7295160ce901e08e12be75cb3aaf6b9a199de811eb60b618feb773f7c552bba');\nhashMap.set('maven','c110b99291c2a5bc82cf7a69330275e9bbd7dc8ba3e9e987611dfcffbe002d8d');\nhashMap.set('maven-wrapper','db967206d960b12d7c58d78132808d3c412087ababf5c59444262782e4434c6a');\nhashMap.set('meteor','4636a47ba4dcfff19fe662572ef7a40d17146be3c966e00ef437e1fc8de92776');\nhashMap.set('mint','248fe4f1ea5c985921c286785792c97e06fc41f402b2d45df82f6aecd17f710e');\nhashMap.set('mise','bc13ff3b8b16a2e79f450017920e87da37fbfbf61fc8c95ddeaa7cfd4517b5b6');\nhashMap.set('mix','473bb870c00b270faae93c4614873f644ad516f762acf07f773b12a7b8e01d19');\nhashMap.set('nix','a9d4ae3f9f01abb71dc9ebc12a9cd8bec237ad9d2dabfbf4f5ffd59e56c9a612');\nhashMap.set('nodenv','ac652c28481b001f7471f4183eac07b45d98ecbe83efc275830b0a1b2e0459b8');\nhashMap.set('npm','e60c7151bffb3c34c2400389558d36575875d66bd9bc5802c89e58989e2dda79');\nhashMap.set('nuget','136bc3226e77b8fe65940454dc2c858fde86c2e0da6dbbdf71a5269ab137caee');\nhashMap.set('nvm','3eb77c7b0acf6d64753de78fad2499b352719853aa6872878c40675d14152322');\nhashMap.set('ocb','032b216684c14b0954e0bb019513a2aca3faaee5748587acb668d377d7c891ca');\nhashMap.set('osgi','d6567a733ef3983112b46fdccd7ceebfcd48411104e0c6b6e714d4310db48024');\nhashMap.set('pep621','2908e3287941e0d111b492140b56863915f8ed8601a7728de39ff9f878400210');\nhashMap.set('pep723','b96683163de63ed93207ec0538066705b1e58a1cd5b8bd11c63fc28b26bddba1');\nhashMap.set('pip-compile','ad43905a365c677315d2dcba725aef9b82c677d6ff30ee358f890f10faeb035f');\nhashMap.set('pip_requirements','953af0f3b41c2c1027327a8b1f37675c72892a8b03fdfbc3862ab63a1c3c72bf');\nhashMap.set('pip_setup','df18fba2bdcf48f3ca12a8f7e5cd28df31e2368d5528127277038ef4206eca79');\nhashMap.set('pipenv','fc2fd2e06753fada34958eb190c6d9236271b81a8a4cf1a354937a209cef06a9');\nhashMap.set('pixi','35630a711b242af39f01911835efc8fd19605e564e0e4ede5a18dab7e38fec3e');\nhashMap.set('poetry','33dfbd8bddcf2aca101be8c869cca7ba8d33a7224c7b86296718814fde8241cb');\nhashMap.set('pre-commit','a8fa968d6308947c8a6eedd799ea449e548e918971acdc250b627e86a446dc23');\nhashMap.set('proto','412053d4550026b4ace490b46e970915b87ec1abf0b0a0c6c8c58ccf1fc16843');\nhashMap.set('pub','d0c11bb1076c7b84a3f30458d8747d5cdfd0126cc52a8d8218ab77c46287219b');\nhashMap.set('puppet','ba58ab689e44acc8f61c3569ab8b40fde01b8a9d3aad712708e2a419e57d8b45');\nhashMap.set('pyenv','9ede8becc97774f9040b40f4472d3e933534b596e04c360bfe0f3c6f95f25182');\nhashMap.set('quadlet','e1fc88a4e14cd595e89bb3d79b4adf2add3ce5eb80f75276e712c32598cca53d');\nhashMap.set('renovate-config','ca60beee2e3b871ea1216fa9df9a501f7ed355fe7da29e12509e56a124a78e69');\nhashMap.set('ruby-version','2db2140d9eee8c555e729a4de0396fa2d78846d3149890ee12fa515bd654be97');\nhashMap.set('runtime-version','b582b168c0cc595e39010feb10f4b97a82683eb269e9598216fbb11cc186e160');\nhashMap.set('rust-toolchain','6ace53db02874d73620d2d872291839820a512a9529c42d174358c692e5db720');\nhashMap.set('sbt','2bb0c98d231bbd6c9043127bfc566a954e7e04fc8654b119c14438a63371e4a7');\nhashMap.set('scalafmt','9d36159b56835e96498af026a1fb0543200db0581681ef95ec54988f411e180f');\nhashMap.set('setup-cfg','4a3a7c812d34739c07685691e7e64c7d3127f9d7d4aff99dc45a25df97ed9745');\nhashMap.set('smithy','9641b91d065ffb63be0dd888139a0402dba41e550f8b44c592db9daf52109100');\nhashMap.set('sveltos','e0b799487e3331b91de1fec7dfb975378340b883dc0aeb95b950d289eb4737c5');\nhashMap.set('swift','5ebd875ee7a541b4725f6263789ea9a7c77a4b7c40b2119f894e67b588cfa672');\nhashMap.set('tekton','33948f5bdf7553909fa63744adb26da97ddf366e9499bccab1250879570267c9');\nhashMap.set('terraform','369872bc79b8c0424d68345b2cec69d71534c0a4a42113af8ee7f04c32ad95a2');\nhashMap.set('terraform-version','ec8f786b9731d47f2c2fe0307caf64d7ddd83046fe7ff1f7d8423239f8b0f2aa');\nhashMap.set('terragrunt','ffcbaa67dd65f064d43f8c121c1006115eab1879c4bd38de263b9b90a009c118');\nhashMap.set('terragrunt-version','eea6087b33717d22ede2fc68c2f64df8390b75abe82110ed831a180648feb51d');\nhashMap.set('tflint-plugin','31247d37bc80aae17039bfa21bd989c5717730c5ef10cf2a6f09841576d012ec');\nhashMap.set('travis','04c94f72622003195c8ea8147c8fbd93003f444ec807ce33f2ada2384282db83');\nhashMap.set('typst','d080a79fbd961c6e21fcc505d544b7e0ff2126142acb1dcabdf6abbcd9339248');\nhashMap.set('unity3d','f13e25e115e3443f4e16cf31578acffa78fb1a5e23339680a92d8d6de6052920');\nhashMap.set('velaci','fda00ddb7cc23e9a37e0a8a253151df0a6930b4276d3e4f78cc54b9ac09af7de');\nhashMap.set('vendir','f07c508ef8bf0c6d74b4e3ebdc7573ab606ab7f0671f4d1e5f6002adaed84c9c');\nhashMap.set('woodpecker','6110d3bec33aaeb3511d4bbfa896cec3c8e02fb04a6cff50c9ba81061c851045');\nhashMap.set('xcodegen','dad511d88a9ce1dbdde8b9731f3da7f2bdaa4ca8a083294ee58d56da62ab1683');\nhashMap.set('jsonata','416bcf61144b276b3112814c6e6d261aa29608f46fbb0516c471d35c16f8f0d7');\nhashMap.set('regex','20be5247fdc164173871a051acb0527da017d0c155c653d7563601f55e7b3ff5');"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fingerprint.generated.js","names":[],"sources":["../../../lib/modules/manager/fingerprint.generated.ts"],"sourcesContent":["export const hashMap = new Map<string, string>();\n\nhashMap.set('ansible','a52394a36ac5517f7330473c31d93aa05b2ce607c5e951b48f25a4693cd20a81');\nhashMap.set('ansible-galaxy','0a264d6be73953d801510fdeff271e4071c274339569c6dab4e2a128eaf4869f');\nhashMap.set('ant','2df5943cf0ed19a21b94df13729dbb925655548130caf37e3e22bebaed518e17');\nhashMap.set('apm','146e023bced69a0625adfac29148a5254d9457ad5a48931c7047299f6452cb43');\nhashMap.set('argocd','5d35b1992e53130bf83b0e59a0f90ccd3a78919974c69044f306dc5d162f48ce');\nhashMap.set('asdf','430eb99b58171700c8a59c78b9e648575e9b176b781d90dd10a710f7b69015bb');\nhashMap.set('azure-pipelines','6bf7782e8a02fc87dc5d84aab59e517c09df51fd23cf57805e62207dbd5efdb5');\nhashMap.set('batect','375d39b432013bedb1330cf40a2199dd822751b28578214f219e7bab98594b8d');\nhashMap.set('batect-wrapper','d999355511ea7f4053325a18b8cfc8d2b586c61e6760c35e557d383a673e3939');\nhashMap.set('bazel','ef00591c6f09069550ef97ff7ff5e387b9dd3df51cdecc9ef941169b19315396');\nhashMap.set('bazel-module','65e6cb3d6c0d9b3b1fda22388b6c72148c518cd06e8c434b46e4645384381bad');\nhashMap.set('bazelisk','a83328e3c5b4c3f5af2e425f680b4852c08ef5c6d035a248e09577136cf3b14d');\nhashMap.set('bicep','7246e0bfc06e0e28cbb03ac088c5591f648956b086e106aeb251fe5d628329db');\nhashMap.set('bitbucket-pipelines','59c0503494ab1442b127914503c01b97ac17b6742b19c632292d5aa24de115cd');\nhashMap.set('bitrise','478dfd316221fad7c29e177c70d1018d832fb2626b53308a5d0f1f0380e69f42');\nhashMap.set('buildkite','b8b404f53cd5d61c39153fddf93945e621471c4ac6aa9960c881cd868922bb4c');\nhashMap.set('buildpacks','6bef3cb04d66b5cfbb195adb4829bcbccae6408518706744d291bacf0610421f');\nhashMap.set('bun','3d40239b69d462ab843562ff8ee5bfacbc46d4976d38d0af17d037973f174e3e');\nhashMap.set('bun-version','df3ae8e4a5de1fa1b4544f3d7fc8117e80adb1e151c46d1ede54a4dbea6521e4');\nhashMap.set('bundler','9c5b8a2e7b84a545bbd6cc74c1fd9422f167da67c41bcc9bfb4cc2098b41de0c');\nhashMap.set('cake','9ebd8b481220b30a8860121d26184540a1a2fcc05ef780df9295dea39b386fad');\nhashMap.set('cargo','e8f43c68e874a9f3e684c2f3323b77a2799c49a1a538495ae75fb3a3bdd1f786');\nhashMap.set('cdnurl','9a81c8e3c6ad6c788498c99fc1067ffdfcd92a427c3afaf8c0130975d83131f2');\nhashMap.set('circleci','91cbeb33ea20f9838e2c81a1195eb806f0b38fa282bc3679f62552f20575ca85');\nhashMap.set('cloudbuild','f4e40388944652c8a19f8518771ac8d3f3c4ccf81ddef0e68b463aca833cb73c');\nhashMap.set('cocoapods','f832e2beef885bb3fd697ed9bb3e8cd742926bfec37ff41212edd2dbb4edb3ba');\nhashMap.set('composer','3906e56e8decf5d5e51cccdb46d2ce4eb4ff8efc8b0596b859f0f7210e13ed45');\nhashMap.set('conan','1cfe3887dba15d974fbbad3c0f49b7b745a6bad194ff95f067976ce3ae47d2bf');\nhashMap.set('copier','d70688a4a74d7239229a69eb1e3c5af19da0a38d12b9324c92ff86776fa0dec7');\nhashMap.set('cpanfile','07813fec3f3c2197056500e9266a0553b9774c02f2c74d5ca2e213188c7c12d3');\nhashMap.set('crossplane','5c26b1201a1a51454ffb94d829e223a76a781569bf79cdb1e47087c30233ec40');\nhashMap.set('crow','eb9a5f9f95041855dded67bcce3dd54724f690995ed6268d272e8a666ff28fd0');\nhashMap.set('deno','bdb28fcfdc032e3ea75d2569213fef207fd18bcaa46a6e4ea933150e49df24bf');\nhashMap.set('deps-edn','7b6ac92be04b44fdf1da8755550a6417bb294908158119c8fff10adeb05048d2');\nhashMap.set('devbox','abca7468e2363c04b7e4b85bfdbc75e11ed38e9d3b84b9ccc6d1a4c34a8fc1fb');\nhashMap.set('devcontainer','24320ed1cb6191d04cb8b2707214d82c08c682597aed1d84f250aa00ad1632ec');\nhashMap.set('docker-compose','a9c27711356fbda8dd14f21e046936e1e43f18c5528325b468d89937f76fe1e7');\nhashMap.set('dockerfile','a83e9e93f31576697d45fd60a0b44f7d14a610752e695a62507624ab2dbb2162');\nhashMap.set('droneci','e2039bb37c2d63c53027b188d1f0faa7c8923dcbfe6cf3851fba8d4e9f43a358');\nhashMap.set('fleet','6b091fd5b8c2e9fc5d5b81ba34befec915d585d45cbc175c851ccc1555372925');\nhashMap.set('flux','70833dd068ea0a746a9392469e7904021562c7629428d0cd554603bad4eb6ce5');\nhashMap.set('fvm','9b161df0f14bc6e536368952adf373e343630097121a913cea60ee284027fb90');\nhashMap.set('git-submodules','df8bb92b2906d8cddda2d4b302ee503f8002e3554d32d74cef2f584fe891f38f');\nhashMap.set('github-actions','28532556bb676239d3af375c21af30cfe392ff029f8a695391e0fc1203fc0cab');\nhashMap.set('gitlabci','a5e1e66ef461e1c1e71062f85f35a212417e23627f4b002810f9a98295d6e672');\nhashMap.set('gitlabci-include','8860a15ab516fde00694f9bd9bf56fce4addafe5a55b5ddb9a4ec477d301d351');\nhashMap.set('glasskube','93e7b9000a17efa15a1abaaf320b5af9169b1ecd828fc0c881d98570ef9d9e30');\nhashMap.set('gleam','a3bd05c4814eb57872d39979a40342a8ee23e61a85e2ab25e84346e8215dadc1');\nhashMap.set('gomod','1ed58f0af452a6776ae1899466851bab659f8287c90cff96619068d8184048d5');\nhashMap.set('gradle','ef9db616bf60e9a3623fff0e41df274a457333a37f37c24f3841a3ca3a531449');\nhashMap.set('gradle-wrapper','77f7e75be2597b847fc821ff8ff5bb4b3e37ab3cc4e780e22ce75e0342becac8');\nhashMap.set('haskell-cabal','f158b7725e3143dfd2950e3de0bbccc2a61cd7eba87f7a54c5057e01252348e2');\nhashMap.set('helm-requirements','7ee9dace4c036dfe113c0c0e46369d8b83a739caa831660142ca98d3236a180a');\nhashMap.set('helm-values','01069e887d4f3b55ca62a3c0dc66d8620264e1426207be9eb240a10c1ad5e412');\nhashMap.set('helmfile','433d1d0fd4a81f191a0b553ab52419627b1d7aa0eb3099d53f7ae4a1d076c221');\nhashMap.set('helmsman','c4af380756eae8dc988d24c91e9749ce0a97b201daa55f59d2394c1c90d73779');\nhashMap.set('helmv3','cc9396b650a7226eeae1bed6b620cfb6d12e6a8ad52faf80b527ffaeb2b68066');\nhashMap.set('hermit','0fb25b7766c3a264fbb765ff75b1542b24136c4c9f933696d4a5aecfed637071');\nhashMap.set('homeassistant-manifest','05043c6db870cffbb6f8f3e351c025e3de227eaae0b24134b796aec46f84b65f');\nhashMap.set('homebrew','9c64a4f1475b1c2052372e566c9190f32ae8acd1c54313031d55ae8772388367');\nhashMap.set('html','81fa6c2bf2b868596584a48b949645207a2aa3081951ed99183ee50b70b77d5f');\nhashMap.set('jenkins','7bfb09418a132e052579196633bac78ac947cf93f1e70748ea1b3da929874b87');\nhashMap.set('jsonnet-bundler','06d163b939b258e1e2847a12a1249cb7d68d77c7bcf13c6d1a0a916744eba5cc');\nhashMap.set('kotlin-script','95ebc844c040ca047321b207d525220e29774a2a1fe06f9639e8353c66908564');\nhashMap.set('kubernetes','321e7d77fb3600dd4c00a86eaa1294927e7f92300b74fa2977d813dcaa3bb4de');\nhashMap.set('kustomize','558fcfe5b20f1eb4aba0d3c755a060bb4561611e99db7000786ce4edcd3f7894');\nhashMap.set('leiningen','a7295160ce901e08e12be75cb3aaf6b9a199de811eb60b618feb773f7c552bba');\nhashMap.set('maven','c110b99291c2a5bc82cf7a69330275e9bbd7dc8ba3e9e987611dfcffbe002d8d');\nhashMap.set('maven-wrapper','db967206d960b12d7c58d78132808d3c412087ababf5c59444262782e4434c6a');\nhashMap.set('meteor','4636a47ba4dcfff19fe662572ef7a40d17146be3c966e00ef437e1fc8de92776');\nhashMap.set('mint','248fe4f1ea5c985921c286785792c97e06fc41f402b2d45df82f6aecd17f710e');\nhashMap.set('mise','bc13ff3b8b16a2e79f450017920e87da37fbfbf61fc8c95ddeaa7cfd4517b5b6');\nhashMap.set('mix','473bb870c00b270faae93c4614873f644ad516f762acf07f773b12a7b8e01d19');\nhashMap.set('nix','a9d4ae3f9f01abb71dc9ebc12a9cd8bec237ad9d2dabfbf4f5ffd59e56c9a612');\nhashMap.set('nodenv','ac652c28481b001f7471f4183eac07b45d98ecbe83efc275830b0a1b2e0459b8');\nhashMap.set('npm','e563e8a7ad94b90ca5a777e1a88af9638f2f8a9e2a142ed317c8ae5758d72cbd');\nhashMap.set('nuget','136bc3226e77b8fe65940454dc2c858fde86c2e0da6dbbdf71a5269ab137caee');\nhashMap.set('nvm','3eb77c7b0acf6d64753de78fad2499b352719853aa6872878c40675d14152322');\nhashMap.set('ocb','032b216684c14b0954e0bb019513a2aca3faaee5748587acb668d377d7c891ca');\nhashMap.set('osgi','d6567a733ef3983112b46fdccd7ceebfcd48411104e0c6b6e714d4310db48024');\nhashMap.set('pep621','2908e3287941e0d111b492140b56863915f8ed8601a7728de39ff9f878400210');\nhashMap.set('pep723','b96683163de63ed93207ec0538066705b1e58a1cd5b8bd11c63fc28b26bddba1');\nhashMap.set('pip-compile','ad43905a365c677315d2dcba725aef9b82c677d6ff30ee358f890f10faeb035f');\nhashMap.set('pip_requirements','953af0f3b41c2c1027327a8b1f37675c72892a8b03fdfbc3862ab63a1c3c72bf');\nhashMap.set('pip_setup','df18fba2bdcf48f3ca12a8f7e5cd28df31e2368d5528127277038ef4206eca79');\nhashMap.set('pipenv','fc2fd2e06753fada34958eb190c6d9236271b81a8a4cf1a354937a209cef06a9');\nhashMap.set('pixi','35630a711b242af39f01911835efc8fd19605e564e0e4ede5a18dab7e38fec3e');\nhashMap.set('poetry','33dfbd8bddcf2aca101be8c869cca7ba8d33a7224c7b86296718814fde8241cb');\nhashMap.set('pre-commit','a8fa968d6308947c8a6eedd799ea449e548e918971acdc250b627e86a446dc23');\nhashMap.set('proto','412053d4550026b4ace490b46e970915b87ec1abf0b0a0c6c8c58ccf1fc16843');\nhashMap.set('pub','d0c11bb1076c7b84a3f30458d8747d5cdfd0126cc52a8d8218ab77c46287219b');\nhashMap.set('puppet','ba58ab689e44acc8f61c3569ab8b40fde01b8a9d3aad712708e2a419e57d8b45');\nhashMap.set('pyenv','9ede8becc97774f9040b40f4472d3e933534b596e04c360bfe0f3c6f95f25182');\nhashMap.set('quadlet','e1fc88a4e14cd595e89bb3d79b4adf2add3ce5eb80f75276e712c32598cca53d');\nhashMap.set('renovate-config','ca60beee2e3b871ea1216fa9df9a501f7ed355fe7da29e12509e56a124a78e69');\nhashMap.set('ruby-version','2db2140d9eee8c555e729a4de0396fa2d78846d3149890ee12fa515bd654be97');\nhashMap.set('runtime-version','b582b168c0cc595e39010feb10f4b97a82683eb269e9598216fbb11cc186e160');\nhashMap.set('rust-toolchain','6ace53db02874d73620d2d872291839820a512a9529c42d174358c692e5db720');\nhashMap.set('sbt','2bb0c98d231bbd6c9043127bfc566a954e7e04fc8654b119c14438a63371e4a7');\nhashMap.set('scalafmt','9d36159b56835e96498af026a1fb0543200db0581681ef95ec54988f411e180f');\nhashMap.set('setup-cfg','4a3a7c812d34739c07685691e7e64c7d3127f9d7d4aff99dc45a25df97ed9745');\nhashMap.set('smithy','9641b91d065ffb63be0dd888139a0402dba41e550f8b44c592db9daf52109100');\nhashMap.set('sveltos','e0b799487e3331b91de1fec7dfb975378340b883dc0aeb95b950d289eb4737c5');\nhashMap.set('swift','5ebd875ee7a541b4725f6263789ea9a7c77a4b7c40b2119f894e67b588cfa672');\nhashMap.set('tekton','33948f5bdf7553909fa63744adb26da97ddf366e9499bccab1250879570267c9');\nhashMap.set('terraform','369872bc79b8c0424d68345b2cec69d71534c0a4a42113af8ee7f04c32ad95a2');\nhashMap.set('terraform-version','ec8f786b9731d47f2c2fe0307caf64d7ddd83046fe7ff1f7d8423239f8b0f2aa');\nhashMap.set('terragrunt','ffcbaa67dd65f064d43f8c121c1006115eab1879c4bd38de263b9b90a009c118');\nhashMap.set('terragrunt-version','eea6087b33717d22ede2fc68c2f64df8390b75abe82110ed831a180648feb51d');\nhashMap.set('tflint-plugin','31247d37bc80aae17039bfa21bd989c5717730c5ef10cf2a6f09841576d012ec');\nhashMap.set('travis','04c94f72622003195c8ea8147c8fbd93003f444ec807ce33f2ada2384282db83');\nhashMap.set('typst','d080a79fbd961c6e21fcc505d544b7e0ff2126142acb1dcabdf6abbcd9339248');\nhashMap.set('unity3d','f13e25e115e3443f4e16cf31578acffa78fb1a5e23339680a92d8d6de6052920');\nhashMap.set('velaci','fda00ddb7cc23e9a37e0a8a253151df0a6930b4276d3e4f78cc54b9ac09af7de');\nhashMap.set('vendir','f07c508ef8bf0c6d74b4e3ebdc7573ab606ab7f0671f4d1e5f6002adaed84c9c');\nhashMap.set('woodpecker','6110d3bec33aaeb3511d4bbfa896cec3c8e02fb04a6cff50c9ba81061c851045');\nhashMap.set('xcodegen','dad511d88a9ce1dbdde8b9731f3da7f2bdaa4ca8a083294ee58d56da62ab1683');\nhashMap.set('jsonata','416bcf61144b276b3112814c6e6d261aa29608f46fbb0516c471d35c16f8f0d7');\nhashMap.set('regex','20be5247fdc164173871a051acb0527da017d0c155c653d7563601f55e7b3ff5');"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { logger } from "../../../../../../logger/index.js";
|
|
|
4
4
|
function replaceConstraintVersion(lockFileContent, depName, constraint, newVersion, newConstraint) {
|
|
5
5
|
if (lockFileContent.startsWith("__metadata:")) return lockFileContent;
|
|
6
6
|
const depNameConstraint = `${depName}@${constraint}`;
|
|
7
|
-
const matchString = `(
|
|
7
|
+
const matchString = `((?:^|\n|, )"?${depNameConstraint.replace(regEx(/(?<special>@|\^|\.|\\|\|)/g), "\\$<special>")}(("|",|,)[^\n:]*)?:\n)(.*\n)*?(\\s+dependencies|\n[@a-z])`;
|
|
8
8
|
const matchResult = regEx(matchString).exec(lockFileContent);
|
|
9
9
|
/* v8 ignore next -- needs test */
|
|
10
10
|
if (!matchResult) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace.js","names":[],"sources":["../../../../../../../lib/modules/manager/npm/update/locked-dependency/yarn-lock/replace.ts"],"sourcesContent":["import { logger } from '../../../../../../logger/index.ts';\nimport { regEx } from '../../../../../../util/regex.ts';\n\nexport function replaceConstraintVersion(\n lockFileContent: string,\n depName: string,\n constraint: string,\n newVersion: string,\n newConstraint?: string,\n): string {\n if (lockFileContent.startsWith('__metadata:')) {\n // Yarn 2+\n return lockFileContent;\n }\n const depNameConstraint = `${depName}@${constraint}`;\n const escaped = depNameConstraint.replace(\n regEx(/(?<special>@|\\^|\\.|\\\\|\\|)/g),\n '\\\\$<special>',\n );\n const matchString = `(
|
|
1
|
+
{"version":3,"file":"replace.js","names":[],"sources":["../../../../../../../lib/modules/manager/npm/update/locked-dependency/yarn-lock/replace.ts"],"sourcesContent":["import { logger } from '../../../../../../logger/index.ts';\nimport { regEx } from '../../../../../../util/regex.ts';\n\nexport function replaceConstraintVersion(\n lockFileContent: string,\n depName: string,\n constraint: string,\n newVersion: string,\n newConstraint?: string,\n): string {\n if (lockFileContent.startsWith('__metadata:')) {\n // Yarn 2+\n return lockFileContent;\n }\n const depNameConstraint = `${depName}@${constraint}`;\n const escaped = depNameConstraint.replace(\n regEx(/(?<special>@|\\^|\\.|\\\\|\\|)/g),\n '\\\\$<special>',\n );\n const matchString = `((?:^|\\n|, )\"?${escaped}((\"|\",|,)[^\\n:]*)?:\\n)(.*\\n)*?(\\\\s+dependencies|\\n[@a-z])`;\n // yarn will fill in the details later\n const matchResult = regEx(matchString).exec(lockFileContent);\n /* v8 ignore next -- needs test */\n if (!matchResult) {\n logger.debug(\n { depName, constraint, newVersion },\n 'Could not find constraint in lock file',\n );\n return lockFileContent;\n }\n let constraintLine = matchResult[1];\n if (newConstraint) {\n const newDepNameConstraint = `${depName}@${newConstraint}`;\n constraintLine = constraintLine.replace(\n depNameConstraint,\n newDepNameConstraint,\n );\n }\n return lockFileContent.replace(\n regEx(matchString),\n `${constraintLine} version \"${newVersion}\"\\n$5`,\n );\n}\n"],"mappings":";;;AAGA,SAAgB,yBACd,iBACA,SACA,YACA,YACA,eACQ;CACR,IAAI,gBAAgB,WAAW,aAAa,GAE1C,OAAO;CAET,MAAM,oBAAoB,GAAG,QAAQ,GAAG;CAKxC,MAAM,cAAc,iBAJJ,kBAAkB,QAChC,MAAM,4BAA4B,GAClC,cAEyC,EAAE;CAE7C,MAAM,cAAc,MAAM,WAAW,CAAC,CAAC,KAAK,eAAe;;CAE3D,IAAI,CAAC,aAAa;EAChB,OAAO,MACL;GAAE;GAAS;GAAY;EAAW,GAClC,wCACF;EACA,OAAO;CACT;CACA,IAAI,iBAAiB,YAAY;CACjC,IAAI,eAAe;EACjB,MAAM,uBAAuB,GAAG,QAAQ,GAAG;EAC3C,iBAAiB,eAAe,QAC9B,mBACA,oBACF;CACF;CACA,OAAO,gBAAgB,QACrB,MAAM,WAAW,GACjB,GAAG,eAAe,aAAa,WAAW,MAC5C;AACF"}
|
package/package.json
CHANGED
package/renovate-schema.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$id": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
-
"title": "JSON schema for Renovate 44.
|
|
3
|
+
"title": "JSON schema for Renovate 44.68.0 config files (https://renovatebot.com/)",
|
|
4
4
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
5
|
-
"x-renovate-version": "44.
|
|
5
|
+
"x-renovate-version": "44.68.0",
|
|
6
6
|
"allowComments": true,
|
|
7
7
|
"type": "object",
|
|
8
8
|
"definitions": {
|