renovate 43.24.0 → 43.24.1
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/crate/index.js +3 -1
- package/dist/modules/datasource/crate/index.js.map +1 -1
- package/dist/util/http/http.js +3 -2
- package/dist/util/http/http.js.map +1 -1
- package/dist/util/http/types.d.ts +1 -0
- package/dist/util/mutex.js +4 -3
- package/dist/util/mutex.js.map +1 -1
- package/package.json +5 -5
- package/renovate-schema.json +2 -2
|
@@ -173,7 +173,9 @@ var CrateDatasource = class CrateDatasource extends Datasource {
|
|
|
173
173
|
}
|
|
174
174
|
if (registry.flavor !== "crates.io" && !registry.isSparse) {
|
|
175
175
|
const cacheKey = `crate-datasource/registry-clone-path/${registryFetchUrl}`;
|
|
176
|
-
const
|
|
176
|
+
const lockKey = registryFetchUrl;
|
|
177
|
+
const executionTimeout = GlobalConfig.get("executionTimeout", 15) * 60 * 1e3;
|
|
178
|
+
const releaseLock = await acquireLock(lockKey, "crate-registry", GlobalConfig.get("gitTimeout", executionTimeout));
|
|
177
179
|
try {
|
|
178
180
|
const cached = get(cacheKey);
|
|
179
181
|
if (cached?.err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["cargoVersioning.id","memCache.get"],"sources":["../../../../lib/modules/datasource/crate/index.ts"],"sourcesContent":["import { simpleGit } from 'simple-git';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport * as memCache from '../../../util/cache/memory/index.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getChildEnv } from '../../../util/exec/utils.ts';\nimport { privateCacheDir, readCacheFile } from '../../../util/fs/index.ts';\nimport { simpleGitConfig } from '../../../util/git/config.ts';\nimport { toSha256 } from '../../../util/hash.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { acquireLock } from '../../../util/mutex.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { joinUrlParts, parseUrl } from '../../../util/url.ts';\nimport * as cargoVersioning from '../../versioning/cargo/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type {\n GetReleasesConfig,\n PostprocessReleaseConfig,\n PostprocessReleaseResult,\n Release,\n ReleaseResult,\n} from '../types.ts';\nimport { ReleaseTimestamp } from './schema.ts';\nimport type {\n CrateMetadata,\n CrateRecord,\n RegistryFlavor,\n RegistryInfo,\n} from './types.ts';\n\ntype CloneResult =\n | {\n err: Error;\n clonePath?: undefined;\n }\n | {\n clonePath: string;\n err?: undefined;\n };\n\nexport class CrateDatasource extends Datasource {\n static readonly id = 'crate';\n\n constructor() {\n super(CrateDatasource.id);\n }\n\n override defaultRegistryUrls = ['https://crates.io'];\n\n override defaultVersioning = cargoVersioning.id;\n\n static readonly CRATES_IO_BASE_URL =\n 'https://raw.githubusercontent.com/rust-lang/crates.io-index/master/';\n\n static readonly CRATES_IO_API_BASE_URL = 'https://crates.io/api/v1/';\n\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `repository` field in the results.';\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from `pubtime` field from crates.io index if available, or `version.created_at` field from crates.io API otherwise.';\n\n private async _getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore if -- should never happen */\n if (!registryUrl) {\n logger.warn(\n 'crate datasource: No registryUrl specified, cannot perform getReleases',\n );\n return null;\n }\n\n const registryInfo = await CrateDatasource.fetchRegistryInfo({\n packageName,\n registryUrl,\n });\n if (!registryInfo) {\n logger.debug(`Could not fetch registry info from ${registryUrl}`);\n return null;\n }\n\n const dependencyUrl = CrateDatasource.getDependencyUrl(\n registryInfo,\n packageName,\n );\n\n const payload = await this.fetchCrateRecordsPayload(\n registryInfo,\n packageName,\n );\n const lines = payload\n .split(newlineRegex) // break into lines\n .map((line) => line.trim()) // remove whitespace\n .filter((line) => line.length !== 0) // remove empty lines\n .map((line) => JSON.parse(line) as CrateRecord); // parse\n\n const metadata = await this.getCrateMetadata(registryInfo, packageName);\n\n const result: ReleaseResult = {\n dependencyUrl,\n releases: [],\n };\n\n if (metadata?.homepage) {\n result.homepage = metadata.homepage;\n }\n\n if (metadata?.repository) {\n result.sourceUrl = metadata.repository;\n }\n\n result.releases = lines\n .map((line) => {\n const versionOrig = line.vers;\n const version = versionOrig.replace(/\\+.*$/, '');\n const release: Release = { version };\n\n if (versionOrig !== version) {\n release.versionOrig = versionOrig;\n }\n\n if (line.yanked) {\n release.isDeprecated = true;\n }\n\n if (line.rust_version) {\n release.constraints = { rust: [line.rust_version] };\n }\n\n if (line.pubtime) {\n release.releaseTimestamp = asTimestamp(line.pubtime);\n }\n\n return release;\n })\n .filter((release) => release.version);\n if (!result.releases.length) {\n return null;\n }\n\n return result;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${CrateDatasource.id}`,\n // TODO: types (#22198)\n key: `${config.registryUrl}/${config.packageName}`,\n cacheable: CrateDatasource.areReleasesCacheable(config.registryUrl),\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n private async _getCrateMetadata(\n info: RegistryInfo,\n packageName: string,\n ): Promise<CrateMetadata | null> {\n if (info.flavor !== 'crates.io') {\n return null;\n }\n\n // The `?include=` suffix is required to avoid unnecessary database queries\n // on the crates.io server. This lets us work around the regular request\n // throttling of one request per second.\n const crateUrl = `${CrateDatasource.CRATES_IO_API_BASE_URL}crates/${packageName}?include=`;\n\n logger.debug(\n { crateUrl, packageName, registryUrl: info.rawUrl },\n 'downloading crate metadata',\n );\n\n try {\n interface Response {\n crate: CrateMetadata;\n }\n const response = await this.http.getJsonUnchecked<Response>(crateUrl);\n return response.body.crate;\n } catch (err) {\n logger.warn(\n { err, packageName, registryUrl: info.rawUrl },\n 'failed to download crate metadata',\n );\n }\n\n return null;\n }\n\n public getCrateMetadata(\n info: RegistryInfo,\n packageName: string,\n ): Promise<CrateMetadata | null> {\n return withCache(\n {\n namespace: `datasource-${CrateDatasource.id}-metadata`,\n key: `${info.rawUrl}/${packageName}`,\n cacheable: CrateDatasource.areReleasesCacheable(info.rawUrl),\n ttlMinutes: 24 * 60, // 24 hours\n },\n () => this._getCrateMetadata(info, packageName),\n );\n }\n\n public async fetchCrateRecordsPayload(\n info: RegistryInfo,\n packageName: string,\n ): Promise<string> {\n if (info.clonePath) {\n const path = upath.join(\n info.clonePath,\n ...CrateDatasource.getIndexSuffix(packageName),\n );\n return readCacheFile(path, 'utf8');\n }\n\n const baseUrl =\n info.flavor === 'crates.io'\n ? CrateDatasource.CRATES_IO_BASE_URL\n : info.rawUrl;\n\n if (info.flavor === 'crates.io' || info.isSparse) {\n const packageSuffix = CrateDatasource.getIndexSuffix(\n packageName.toLowerCase(),\n );\n const crateUrl = joinUrlParts(baseUrl, ...packageSuffix);\n try {\n return (await this.http.getText(crateUrl)).body;\n } catch (err) {\n this.handleGenericErrors(err);\n }\n }\n throw new Error(`unsupported crate registry flavor: ${info.flavor}`);\n }\n\n /**\n * Computes the dependency URL for a crate, given\n * registry information\n */\n private static getDependencyUrl(\n info: RegistryInfo,\n packageName: string,\n ): string {\n switch (info.flavor) {\n case 'crates.io':\n return `https://crates.io/crates/${packageName}`;\n case 'cloudsmith': {\n // input: https://dl.cloudsmith.io/basic/$org/$repo/cargo/index.git\n const tokens = info.url.pathname.split('/');\n const org = tokens[2];\n const repo = tokens[3];\n return `https://cloudsmith.io/~${org}/repos/${repo}/packages/detail/cargo/${packageName}`;\n }\n default:\n return `${info.rawUrl}/${packageName}`;\n }\n }\n\n /**\n * Given a Git URL, computes a semi-human-readable name for a folder in which to\n * clone the repository.\n */\n private static cacheDirFromUrl(url: URL): string {\n const proto = url.protocol.replace(regEx(/:$/), '');\n const host = url.hostname;\n const hash = toSha256(url.pathname).substring(0, 7);\n\n return `crate-registry-${proto}-${host}-${hash}`;\n }\n\n private static isSparseRegistry(url: string): boolean {\n const parsed = parseUrl(url);\n if (!parsed) {\n return false;\n }\n return parsed.protocol.startsWith('sparse+');\n }\n\n /**\n * Fetches information about a registry, by url.\n * If no url is given, assumes crates.io.\n * If an url is given, assumes it's a valid Git repository\n * url and clones it to cache.\n */\n private static async fetchRegistryInfo({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<RegistryInfo | null> {\n /* v8 ignore next 3 -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const isSparseRegistry = CrateDatasource.isSparseRegistry(registryUrl);\n const registryFetchUrl = isSparseRegistry\n ? registryUrl.replace(/^sparse\\+/, '')\n : registryUrl;\n\n const url = parseUrl(registryFetchUrl);\n if (!url) {\n logger.debug(`Could not parse registry URL ${registryFetchUrl}`);\n return null;\n }\n\n let flavor: RegistryFlavor;\n if (url.hostname === 'crates.io') {\n flavor = 'crates.io';\n } else if (url.hostname === 'dl.cloudsmith.io') {\n flavor = 'cloudsmith';\n } else {\n flavor = 'other';\n }\n\n const registry: RegistryInfo = {\n flavor,\n rawUrl: registryFetchUrl,\n url,\n isSparse: isSparseRegistry,\n };\n\n if (\n registry.flavor !== 'crates.io' &&\n !GlobalConfig.get('allowCustomCrateRegistries')\n ) {\n logger.warn(\n 'crate datasource: allowCustomCrateRegistries=true is required for registries other than crates.io, bailing out',\n );\n return null;\n }\n if (registry.flavor !== 'crates.io' && !registry.isSparse) {\n const cacheKey = `crate-datasource/registry-clone-path/${registryFetchUrl}`;\n const lockKey = registryFetchUrl;\n\n const releaseLock = await acquireLock(lockKey, 'crate-registry');\n try {\n const cached = memCache.get<CloneResult>(cacheKey);\n\n if (cached?.err) {\n logger.warn(\n { err: cached.err, packageName, registryFetchUrl },\n 'Previous git clone failed, bailing out.',\n );\n return null;\n }\n\n if (cached?.clonePath) {\n registry.clonePath = cached.clonePath;\n return registry;\n }\n\n const clonePath = upath.join(\n privateCacheDir(),\n CrateDatasource.cacheDirFromUrl(url),\n );\n\n const result = await CrateDatasource.clone(\n registryFetchUrl,\n clonePath,\n packageName,\n );\n\n memCache.set(cacheKey, result);\n\n if (result.err) {\n logger.warn(\n { err: result.err, packageName, registryFetchUrl },\n 'Git clone failed, bailing out.',\n );\n return null;\n }\n\n registry.clonePath = result.clonePath;\n } finally {\n releaseLock();\n }\n }\n\n return registry;\n }\n\n private static async clone(\n registryFetchUrl: string,\n clonePath: string,\n packageName: string,\n ): Promise<CloneResult> {\n logger.info(\n { clonePath, registryFetchUrl },\n `Cloning private cargo registry`,\n );\n\n const git = simpleGit({\n ...simpleGitConfig(),\n maxConcurrentProcesses: 1,\n }).env(getChildEnv());\n\n try {\n await git.clone(registryFetchUrl, clonePath, {\n '--depth': 1,\n });\n return { clonePath };\n } catch (err) {\n if (\n err.message.includes(\n 'fatal: dumb http transport does not support shallow capabilities',\n )\n ) {\n logger.info(\n { packageName, registryFetchUrl },\n 'failed to shallow clone git registry, doing full clone',\n );\n try {\n await git.clone(registryFetchUrl, clonePath);\n return { clonePath };\n } catch (err) {\n logger.warn(\n { err, packageName, registryFetchUrl },\n 'failed cloning git registry',\n );\n return { err };\n }\n } else {\n logger.warn(\n { err, packageName, registryFetchUrl },\n 'failed cloning git registry',\n );\n return { err };\n }\n }\n }\n\n private static areReleasesCacheable(\n registryUrl: string | undefined,\n ): boolean {\n // We only cache public releases, we don't want to cache private\n // cloned data between runs.\n return registryUrl === 'https://crates.io';\n }\n\n public static getIndexSuffix(packageName: string): string[] {\n const len = packageName.length;\n\n if (len === 1) {\n return ['1', packageName];\n }\n if (len === 2) {\n return ['2', packageName];\n }\n if (len === 3) {\n return ['3', packageName[0], packageName];\n }\n\n return [packageName.slice(0, 2), packageName.slice(2, 4), packageName];\n }\n\n private async _postprocessRelease(\n { packageName, registryUrl }: PostprocessReleaseConfig,\n release: Release,\n ): Promise<PostprocessReleaseResult> {\n if (release.releaseTimestamp || registryUrl !== 'https://crates.io') {\n return release;\n }\n\n const url = `https://crates.io/api/v1/crates/${packageName}/${release.versionOrig ?? release.version}`;\n // Getting release timestamp could become unnecessary if the manual backfill of `pubtime` mentioned in\n // https://github.com/rust-lang/cargo/issues/15491 is done for all packages.\n const { body: releaseTimestamp } = await this.http.getJson(\n url,\n { cacheProvider: memCacheProvider },\n ReleaseTimestamp,\n );\n release.releaseTimestamp = releaseTimestamp;\n return release;\n }\n\n override postprocessRelease(\n config: PostprocessReleaseConfig,\n release: Release,\n ): Promise<PostprocessReleaseResult> {\n return withCache(\n {\n namespace: `datasource-crate`,\n key: `postprocessRelease:${config.registryUrl}:${config.packageName}:${release.version}`,\n ttlMinutes: 7 * 24 * 60,\n cacheable: config.registryUrl === 'https://crates.io',\n },\n () => this._postprocessRelease(config, release),\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["cargoVersioning.id","memCache.get"],"sources":["../../../../lib/modules/datasource/crate/index.ts"],"sourcesContent":["import { simpleGit } from 'simple-git';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport * as memCache from '../../../util/cache/memory/index.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getChildEnv } from '../../../util/exec/utils.ts';\nimport { privateCacheDir, readCacheFile } from '../../../util/fs/index.ts';\nimport { simpleGitConfig } from '../../../util/git/config.ts';\nimport { toSha256 } from '../../../util/hash.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { acquireLock } from '../../../util/mutex.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { joinUrlParts, parseUrl } from '../../../util/url.ts';\nimport * as cargoVersioning from '../../versioning/cargo/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type {\n GetReleasesConfig,\n PostprocessReleaseConfig,\n PostprocessReleaseResult,\n Release,\n ReleaseResult,\n} from '../types.ts';\nimport { ReleaseTimestamp } from './schema.ts';\nimport type {\n CrateMetadata,\n CrateRecord,\n RegistryFlavor,\n RegistryInfo,\n} from './types.ts';\n\ntype CloneResult =\n | {\n err: Error;\n clonePath?: undefined;\n }\n | {\n clonePath: string;\n err?: undefined;\n };\n\nexport class CrateDatasource extends Datasource {\n static readonly id = 'crate';\n\n constructor() {\n super(CrateDatasource.id);\n }\n\n override defaultRegistryUrls = ['https://crates.io'];\n\n override defaultVersioning = cargoVersioning.id;\n\n static readonly CRATES_IO_BASE_URL =\n 'https://raw.githubusercontent.com/rust-lang/crates.io-index/master/';\n\n static readonly CRATES_IO_API_BASE_URL = 'https://crates.io/api/v1/';\n\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `repository` field in the results.';\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from `pubtime` field from crates.io index if available, or `version.created_at` field from crates.io API otherwise.';\n\n private async _getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore if -- should never happen */\n if (!registryUrl) {\n logger.warn(\n 'crate datasource: No registryUrl specified, cannot perform getReleases',\n );\n return null;\n }\n\n const registryInfo = await CrateDatasource.fetchRegistryInfo({\n packageName,\n registryUrl,\n });\n if (!registryInfo) {\n logger.debug(`Could not fetch registry info from ${registryUrl}`);\n return null;\n }\n\n const dependencyUrl = CrateDatasource.getDependencyUrl(\n registryInfo,\n packageName,\n );\n\n const payload = await this.fetchCrateRecordsPayload(\n registryInfo,\n packageName,\n );\n const lines = payload\n .split(newlineRegex) // break into lines\n .map((line) => line.trim()) // remove whitespace\n .filter((line) => line.length !== 0) // remove empty lines\n .map((line) => JSON.parse(line) as CrateRecord); // parse\n\n const metadata = await this.getCrateMetadata(registryInfo, packageName);\n\n const result: ReleaseResult = {\n dependencyUrl,\n releases: [],\n };\n\n if (metadata?.homepage) {\n result.homepage = metadata.homepage;\n }\n\n if (metadata?.repository) {\n result.sourceUrl = metadata.repository;\n }\n\n result.releases = lines\n .map((line) => {\n const versionOrig = line.vers;\n const version = versionOrig.replace(/\\+.*$/, '');\n const release: Release = { version };\n\n if (versionOrig !== version) {\n release.versionOrig = versionOrig;\n }\n\n if (line.yanked) {\n release.isDeprecated = true;\n }\n\n if (line.rust_version) {\n release.constraints = { rust: [line.rust_version] };\n }\n\n if (line.pubtime) {\n release.releaseTimestamp = asTimestamp(line.pubtime);\n }\n\n return release;\n })\n .filter((release) => release.version);\n if (!result.releases.length) {\n return null;\n }\n\n return result;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${CrateDatasource.id}`,\n // TODO: types (#22198)\n key: `${config.registryUrl}/${config.packageName}`,\n cacheable: CrateDatasource.areReleasesCacheable(config.registryUrl),\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n private async _getCrateMetadata(\n info: RegistryInfo,\n packageName: string,\n ): Promise<CrateMetadata | null> {\n if (info.flavor !== 'crates.io') {\n return null;\n }\n\n // The `?include=` suffix is required to avoid unnecessary database queries\n // on the crates.io server. This lets us work around the regular request\n // throttling of one request per second.\n const crateUrl = `${CrateDatasource.CRATES_IO_API_BASE_URL}crates/${packageName}?include=`;\n\n logger.debug(\n { crateUrl, packageName, registryUrl: info.rawUrl },\n 'downloading crate metadata',\n );\n\n try {\n interface Response {\n crate: CrateMetadata;\n }\n const response = await this.http.getJsonUnchecked<Response>(crateUrl);\n return response.body.crate;\n } catch (err) {\n logger.warn(\n { err, packageName, registryUrl: info.rawUrl },\n 'failed to download crate metadata',\n );\n }\n\n return null;\n }\n\n public getCrateMetadata(\n info: RegistryInfo,\n packageName: string,\n ): Promise<CrateMetadata | null> {\n return withCache(\n {\n namespace: `datasource-${CrateDatasource.id}-metadata`,\n key: `${info.rawUrl}/${packageName}`,\n cacheable: CrateDatasource.areReleasesCacheable(info.rawUrl),\n ttlMinutes: 24 * 60, // 24 hours\n },\n () => this._getCrateMetadata(info, packageName),\n );\n }\n\n public async fetchCrateRecordsPayload(\n info: RegistryInfo,\n packageName: string,\n ): Promise<string> {\n if (info.clonePath) {\n const path = upath.join(\n info.clonePath,\n ...CrateDatasource.getIndexSuffix(packageName),\n );\n return readCacheFile(path, 'utf8');\n }\n\n const baseUrl =\n info.flavor === 'crates.io'\n ? CrateDatasource.CRATES_IO_BASE_URL\n : info.rawUrl;\n\n if (info.flavor === 'crates.io' || info.isSparse) {\n const packageSuffix = CrateDatasource.getIndexSuffix(\n packageName.toLowerCase(),\n );\n const crateUrl = joinUrlParts(baseUrl, ...packageSuffix);\n try {\n return (await this.http.getText(crateUrl)).body;\n } catch (err) {\n this.handleGenericErrors(err);\n }\n }\n throw new Error(`unsupported crate registry flavor: ${info.flavor}`);\n }\n\n /**\n * Computes the dependency URL for a crate, given\n * registry information\n */\n private static getDependencyUrl(\n info: RegistryInfo,\n packageName: string,\n ): string {\n switch (info.flavor) {\n case 'crates.io':\n return `https://crates.io/crates/${packageName}`;\n case 'cloudsmith': {\n // input: https://dl.cloudsmith.io/basic/$org/$repo/cargo/index.git\n const tokens = info.url.pathname.split('/');\n const org = tokens[2];\n const repo = tokens[3];\n return `https://cloudsmith.io/~${org}/repos/${repo}/packages/detail/cargo/${packageName}`;\n }\n default:\n return `${info.rawUrl}/${packageName}`;\n }\n }\n\n /**\n * Given a Git URL, computes a semi-human-readable name for a folder in which to\n * clone the repository.\n */\n private static cacheDirFromUrl(url: URL): string {\n const proto = url.protocol.replace(regEx(/:$/), '');\n const host = url.hostname;\n const hash = toSha256(url.pathname).substring(0, 7);\n\n return `crate-registry-${proto}-${host}-${hash}`;\n }\n\n private static isSparseRegistry(url: string): boolean {\n const parsed = parseUrl(url);\n if (!parsed) {\n return false;\n }\n return parsed.protocol.startsWith('sparse+');\n }\n\n /**\n * Fetches information about a registry, by url.\n * If no url is given, assumes crates.io.\n * If an url is given, assumes it's a valid Git repository\n * url and clones it to cache.\n */\n private static async fetchRegistryInfo({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<RegistryInfo | null> {\n /* v8 ignore next 3 -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const isSparseRegistry = CrateDatasource.isSparseRegistry(registryUrl);\n const registryFetchUrl = isSparseRegistry\n ? registryUrl.replace(/^sparse\\+/, '')\n : registryUrl;\n\n const url = parseUrl(registryFetchUrl);\n if (!url) {\n logger.debug(`Could not parse registry URL ${registryFetchUrl}`);\n return null;\n }\n\n let flavor: RegistryFlavor;\n if (url.hostname === 'crates.io') {\n flavor = 'crates.io';\n } else if (url.hostname === 'dl.cloudsmith.io') {\n flavor = 'cloudsmith';\n } else {\n flavor = 'other';\n }\n\n const registry: RegistryInfo = {\n flavor,\n rawUrl: registryFetchUrl,\n url,\n isSparse: isSparseRegistry,\n };\n\n if (\n registry.flavor !== 'crates.io' &&\n !GlobalConfig.get('allowCustomCrateRegistries')\n ) {\n logger.warn(\n 'crate datasource: allowCustomCrateRegistries=true is required for registries other than crates.io, bailing out',\n );\n return null;\n }\n if (registry.flavor !== 'crates.io' && !registry.isSparse) {\n const cacheKey = `crate-datasource/registry-clone-path/${registryFetchUrl}`;\n const lockKey = registryFetchUrl;\n\n const executionTimeout =\n GlobalConfig.get('executionTimeout', 15) * 60 * 1000;\n const gitTimeout = GlobalConfig.get('gitTimeout', executionTimeout);\n const releaseLock = await acquireLock(\n lockKey,\n 'crate-registry',\n gitTimeout,\n );\n try {\n const cached = memCache.get<CloneResult>(cacheKey);\n\n if (cached?.err) {\n logger.warn(\n { err: cached.err, packageName, registryFetchUrl },\n 'Previous git clone failed, bailing out.',\n );\n return null;\n }\n\n if (cached?.clonePath) {\n registry.clonePath = cached.clonePath;\n return registry;\n }\n\n const clonePath = upath.join(\n privateCacheDir(),\n CrateDatasource.cacheDirFromUrl(url),\n );\n\n const result = await CrateDatasource.clone(\n registryFetchUrl,\n clonePath,\n packageName,\n );\n\n memCache.set(cacheKey, result);\n\n if (result.err) {\n logger.warn(\n { err: result.err, packageName, registryFetchUrl },\n 'Git clone failed, bailing out.',\n );\n return null;\n }\n\n registry.clonePath = result.clonePath;\n } finally {\n releaseLock();\n }\n }\n\n return registry;\n }\n\n private static async clone(\n registryFetchUrl: string,\n clonePath: string,\n packageName: string,\n ): Promise<CloneResult> {\n logger.info(\n { clonePath, registryFetchUrl },\n `Cloning private cargo registry`,\n );\n\n const git = simpleGit({\n ...simpleGitConfig(),\n maxConcurrentProcesses: 1,\n }).env(getChildEnv());\n\n try {\n await git.clone(registryFetchUrl, clonePath, {\n '--depth': 1,\n });\n return { clonePath };\n } catch (err) {\n if (\n err.message.includes(\n 'fatal: dumb http transport does not support shallow capabilities',\n )\n ) {\n logger.info(\n { packageName, registryFetchUrl },\n 'failed to shallow clone git registry, doing full clone',\n );\n try {\n await git.clone(registryFetchUrl, clonePath);\n return { clonePath };\n } catch (err) {\n logger.warn(\n { err, packageName, registryFetchUrl },\n 'failed cloning git registry',\n );\n return { err };\n }\n } else {\n logger.warn(\n { err, packageName, registryFetchUrl },\n 'failed cloning git registry',\n );\n return { err };\n }\n }\n }\n\n private static areReleasesCacheable(\n registryUrl: string | undefined,\n ): boolean {\n // We only cache public releases, we don't want to cache private\n // cloned data between runs.\n return registryUrl === 'https://crates.io';\n }\n\n public static getIndexSuffix(packageName: string): string[] {\n const len = packageName.length;\n\n if (len === 1) {\n return ['1', packageName];\n }\n if (len === 2) {\n return ['2', packageName];\n }\n if (len === 3) {\n return ['3', packageName[0], packageName];\n }\n\n return [packageName.slice(0, 2), packageName.slice(2, 4), packageName];\n }\n\n private async _postprocessRelease(\n { packageName, registryUrl }: PostprocessReleaseConfig,\n release: Release,\n ): Promise<PostprocessReleaseResult> {\n if (release.releaseTimestamp || registryUrl !== 'https://crates.io') {\n return release;\n }\n\n const url = `https://crates.io/api/v1/crates/${packageName}/${release.versionOrig ?? release.version}`;\n // Getting release timestamp could become unnecessary if the manual backfill of `pubtime` mentioned in\n // https://github.com/rust-lang/cargo/issues/15491 is done for all packages.\n const { body: releaseTimestamp } = await this.http.getJson(\n url,\n { cacheProvider: memCacheProvider },\n ReleaseTimestamp,\n );\n release.releaseTimestamp = releaseTimestamp;\n return release;\n }\n\n override postprocessRelease(\n config: PostprocessReleaseConfig,\n release: Release,\n ): Promise<PostprocessReleaseResult> {\n return withCache(\n {\n namespace: `datasource-crate`,\n key: `postprocessRelease:${config.registryUrl}:${config.packageName}:${release.version}`,\n ttlMinutes: 7 * 24 * 60,\n cacheable: config.registryUrl === 'https://crates.io',\n },\n () => this._postprocessRelease(config, release),\n );\n }\n}\n"],"mappings":"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"}
|
package/dist/util/http/http.js
CHANGED
|
@@ -69,7 +69,8 @@ var HttpBase = class {
|
|
|
69
69
|
throw new Error(HOST_DISABLED);
|
|
70
70
|
}
|
|
71
71
|
options = applyAuthorization(options);
|
|
72
|
-
options.timeout
|
|
72
|
+
const timeout = options.timeout ?? 6e4;
|
|
73
|
+
options.timeout = timeout;
|
|
73
74
|
let cacheProvider;
|
|
74
75
|
if (isReadMethod && options.cacheProvider) cacheProvider = options.cacheProvider;
|
|
75
76
|
const memCacheKey = !process.env.RENOVATE_X_DISABLE_HTTP_MEMCACHE && !cacheProvider && options.memCache !== false && isReadMethod ? hash(`got-${JSON.stringify({
|
|
@@ -89,7 +90,7 @@ var HttpBase = class {
|
|
|
89
90
|
const startTime = Date.now();
|
|
90
91
|
const httpTask = async () => {
|
|
91
92
|
let releaseLock;
|
|
92
|
-
if (isReadMethod) releaseLock = await acquireLock(`${options.method} ${url}`, "http-mutex");
|
|
93
|
+
if (isReadMethod) releaseLock = await acquireLock(`${options.method} ${url}`, "http-mutex", timeout * 2);
|
|
93
94
|
try {
|
|
94
95
|
const cachedResponse = await cacheProvider?.bypassServer(options.method, url);
|
|
95
96
|
if (cachedResponse) return cachedResponse;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","names":["memCache.get"],"sources":["../../../lib/util/http/http.ts"],"sourcesContent":["import { isPlainObject, isUndefined } from '@sindresorhus/is';\nimport merge from 'deepmerge';\nimport type { Options, RetryObject } from 'got';\nimport type { Merge, SetRequired } from 'type-fest';\nimport type { z } from 'zod';\nimport { ZodType } from 'zod';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { HOST_DISABLED } from '../../constants/error-messages.ts';\nimport { pkg } from '../../expose.ts';\nimport { logger } from '../../logger/index.ts';\nimport { ExternalHostError } from '../../types/errors/external-host-error.ts';\nimport * as memCache from '../cache/memory/index.ts';\nimport { getEnv } from '../env.ts';\nimport { hash } from '../hash.ts';\nimport { acquireLock } from '../mutex.ts';\nimport { type AsyncResult, Result } from '../result.ts';\nimport { Toml } from '../schema-utils/index.ts';\nimport { ObsoleteCacheHitLogger } from '../stats.ts';\nimport { isHttpUrl, parseUrl, resolveBaseUrl } from '../url.ts';\nimport { parseSingleYaml } from '../yaml.ts';\nimport { applyAuthorization, removeAuthorization } from './auth.ts';\nimport type { HttpCacheProvider } from './cache/types.ts';\nimport { fetch, stream } from './got.ts';\nimport { applyHostRule, findMatchingRule } from './host-rules.ts';\n\nimport { getQueue } from './queue.ts';\nimport { getRetryAfter, wrapWithRetry } from './retry-after.ts';\nimport { getThrottle } from './throttle.ts';\nimport type {\n GotOptions,\n GotStreamOptions,\n GotTask,\n HttpMethod,\n HttpOptions,\n HttpResponse,\n SafeJsonError,\n} from './types.ts';\nimport { copyResponse } from './util.ts';\n\nexport interface InternalJsonUnsafeOptions<\n Opts extends HttpOptions = HttpOptions,\n> {\n url: string | URL;\n httpOptions?: Opts;\n}\n\nexport interface InternalJsonOptions<\n Opts extends HttpOptions,\n ResT = unknown,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n> extends InternalJsonUnsafeOptions<Opts> {\n schema?: Schema;\n}\n\nexport type InternalGotOptions = SetRequired<GotOptions, 'method' | 'context'>;\n\nexport interface InternalHttpOptions extends HttpOptions {\n json?: HttpOptions['body'];\n\n method?: HttpMethod;\n\n parseJson?: Options['parseJson'];\n}\n\nexport function applyDefaultHeaders(options: Options): void {\n const renovateVersion = pkg.version;\n options.headers = {\n ...options.headers,\n 'user-agent':\n GlobalConfig.get('userAgent') ??\n `Renovate/${renovateVersion} (https://github.com/renovatebot/renovate)`,\n };\n}\n\nexport abstract class HttpBase<\n JSONOpts extends HttpOptions = HttpOptions,\n Opts extends HttpOptions = HttpOptions,\n> {\n private readonly options: InternalGotOptions;\n\n protected get baseUrl(): string | undefined {\n return undefined;\n }\n\n protected hostType: string;\n\n constructor(hostType: string, options: HttpOptions = {}) {\n this.hostType = hostType;\n const retryLimit = getEnv().NODE_ENV === 'test' ? 0 : 2;\n this.options = merge<InternalGotOptions>(\n options,\n {\n method: 'get',\n context: { hostType },\n retry: {\n calculateDelay: (retryObject) =>\n this.calculateRetryDelay(retryObject),\n limit: retryLimit,\n maxRetryAfter: 0, // Don't rely on `got` retry-after handling, just let it fail and then we'll handle it\n },\n },\n { isMergeableObject: isPlainObject },\n );\n }\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions,\n ): Promise<HttpResponse<string>>;\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'text' },\n ): Promise<HttpResponse<string>>;\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'buffer' },\n ): Promise<HttpResponse<Buffer>>;\n private async request<T = unknown>(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'json' },\n ): Promise<HttpResponse<T>>;\n\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions,\n ): Promise<HttpResponse<unknown>> {\n const resolvedUrl = this.resolveUrl(requestUrl, httpOptions);\n const url = resolvedUrl.toString();\n\n this.processOptions(resolvedUrl, httpOptions);\n\n let options = merge<InternalGotOptions, InternalHttpOptions>(\n {\n ...this.options,\n hostType: this.hostType,\n },\n httpOptions,\n { isMergeableObject: isPlainObject },\n );\n\n const method = options.method.toLowerCase();\n const isReadMethod = ['head', 'get'].includes(method);\n\n logger.trace(`HTTP request: ${method.toUpperCase()} ${url}`);\n\n options.hooks = {\n beforeRedirect: [removeAuthorization],\n };\n\n applyDefaultHeaders(options);\n\n if (isUndefined(options.readOnly) && isReadMethod) {\n options.readOnly = true;\n }\n\n const hostRule = findMatchingRule(url, options);\n options = applyHostRule(url, options, hostRule);\n if (options.enabled === false) {\n logger.debug(`Host is disabled - rejecting request. HostUrl: ${url}`);\n throw new Error(HOST_DISABLED);\n }\n options = applyAuthorization(options);\n options.timeout ??= 60000;\n\n let cacheProvider: HttpCacheProvider | undefined;\n if (isReadMethod && options.cacheProvider) {\n cacheProvider = options.cacheProvider;\n }\n\n const memCacheKey =\n !process.env.RENOVATE_X_DISABLE_HTTP_MEMCACHE &&\n !cacheProvider &&\n options.memCache !== false &&\n isReadMethod\n ? hash(\n `got-${JSON.stringify({\n url,\n headers: options.headers,\n method,\n })}`,\n )\n : null;\n\n let resPromise: Promise<HttpResponse<unknown>> | null = null;\n\n // Cache GET requests unless memCache=false\n if (memCacheKey) {\n resPromise = memCache.get(memCacheKey);\n\n /* v8 ignore next: temporary code */\n if (resPromise && !cacheProvider) {\n ObsoleteCacheHitLogger.write(url);\n }\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (!resPromise) {\n if (cacheProvider) {\n await cacheProvider.setCacheHeaders(method, url, options);\n }\n\n const startTime = Date.now();\n const httpTask: GotTask = async () => {\n let releaseLock: undefined | (() => void);\n if (isReadMethod) {\n releaseLock = await acquireLock(\n `${options.method} ${url}`,\n 'http-mutex',\n );\n }\n try {\n const cachedResponse = await cacheProvider?.bypassServer<unknown>(\n options.method,\n url,\n );\n if (cachedResponse) {\n return cachedResponse;\n }\n\n const queueMs = Date.now() - startTime;\n return fetch(url, options, { queueMs });\n } finally {\n releaseLock?.();\n }\n };\n\n const throttle = getThrottle(url);\n const throttledTask = throttle ? () => throttle.add(httpTask) : httpTask;\n\n const queue = getQueue(url);\n const queuedTask = queue ? () => queue.add(throttledTask) : throttledTask;\n\n const { maxRetryAfter = 60 } = hostRule;\n resPromise = wrapWithRetry(queuedTask, url, getRetryAfter, maxRetryAfter);\n\n if (memCacheKey) {\n memCache.set(memCacheKey, resPromise);\n }\n }\n\n try {\n const res = await resPromise;\n const deepCopyNeeded = !!memCacheKey && res.statusCode !== 304;\n const resCopy = copyResponse(res, deepCopyNeeded);\n resCopy.authorization = !!options?.headers?.authorization;\n\n if (cacheProvider) {\n return await cacheProvider.wrapServerResponse(method, url, resCopy);\n }\n\n return resCopy;\n } catch (err) {\n const { abortOnError, abortIgnoreStatusCodes } = options;\n if (abortOnError && !abortIgnoreStatusCodes?.includes(err.statusCode)) {\n throw new ExternalHostError(err);\n }\n\n const staleResponse = await cacheProvider?.bypassServer<string | Buffer>(\n method,\n url,\n true,\n );\n if (staleResponse) {\n logger.debug(\n { err },\n `Request error: returning stale cache instead for ${url}`,\n );\n return staleResponse;\n }\n\n this.handleError(requestUrl, httpOptions, err);\n }\n }\n\n protected processOptions(_url: URL, _options: InternalHttpOptions): void {\n // noop\n }\n\n protected handleError(\n _url: string | URL,\n _httpOptions: HttpOptions,\n err: Error,\n ): never {\n throw err;\n }\n\n resolveUrl(\n requestUrl: string | URL,\n options: HttpOptions | undefined = undefined,\n ): URL {\n let url = requestUrl;\n\n if (url instanceof URL) {\n // already a aboslute URL\n return url;\n }\n\n const baseUrl = options?.baseUrl ?? this.baseUrl;\n if (baseUrl) {\n url = resolveBaseUrl(baseUrl, url);\n }\n\n const parsedUrl = parseUrl(url);\n if (!parsedUrl || !isHttpUrl(parsedUrl)) {\n logger.error(\n { url: requestUrl, baseUrl, resolvedUrl: url },\n 'Request Error: cannot parse url',\n );\n throw new Error('Invalid URL');\n }\n return parsedUrl;\n }\n\n protected calculateRetryDelay({ computedValue }: RetryObject): number {\n return computedValue;\n }\n\n get(\n url: string,\n options: HttpOptions = {},\n ): Promise<HttpResponse<string | Buffer>> {\n return this.request(url, options);\n }\n\n head(url: string, options: HttpOptions = {}): Promise<HttpResponse<never>> {\n // to complex to validate\n return this.request(url, {\n ...options,\n responseType: 'text',\n method: 'head',\n }) as Promise<HttpResponse<never>>;\n }\n\n getText(\n url: string | URL,\n options: HttpOptions = {},\n ): Promise<HttpResponse<string>> {\n return this.request(url, { ...options, responseType: 'text' });\n }\n\n getBuffer(\n url: string | URL,\n options: HttpOptions = {},\n ): Promise<HttpResponse<Buffer>> {\n return this.request(url, { ...options, responseType: 'buffer' });\n }\n\n protected requestJsonUnsafe<ResT>(\n method: HttpMethod,\n { url, httpOptions: requestOptions }: InternalJsonUnsafeOptions<JSONOpts>,\n ): Promise<HttpResponse<ResT>> {\n const { body: json, ...httpOptions } = { ...requestOptions };\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method,\n };\n // signal that we expect a json response\n opts.headers = {\n accept: 'application/json',\n ...opts.headers,\n };\n if (json) {\n opts.json = json;\n }\n return this.request<ResT>(url, { ...opts, responseType: 'json' });\n }\n\n private async requestJson<ResT, Schema extends ZodType<ResT> = ZodType<ResT>>(\n method: HttpMethod,\n options: InternalJsonOptions<JSONOpts, ResT, Schema>,\n ): Promise<HttpResponse<ResT>> {\n const res = await this.requestJsonUnsafe<ResT>(method, options);\n\n if (options.schema) {\n res.body = await options.schema.parseAsync(res.body);\n }\n\n return res;\n }\n\n private resolveArgs<ResT = unknown>(\n arg1: string,\n arg2: JSONOpts | ZodType<ResT> | undefined,\n arg3: ZodType<ResT> | undefined,\n ): InternalJsonOptions<JSONOpts, ResT> {\n const res: InternalJsonOptions<JSONOpts, ResT> = { url: arg1 };\n\n if (arg2 instanceof ZodType) {\n res.schema = arg2;\n } else if (arg2) {\n res.httpOptions = arg2;\n }\n\n if (arg3) {\n res.schema = arg3;\n }\n\n return res;\n }\n\n async getPlain(url: string, options?: Opts): Promise<HttpResponse> {\n const opt = options ?? {};\n return await this.getText(url, {\n headers: {\n Accept: 'text/plain',\n },\n ...opt,\n });\n }\n\n /**\n * @deprecated use `getYaml` instead\n */\n async getYamlUnchecked<ResT>(\n url: string,\n options?: Opts,\n ): Promise<HttpResponse<ResT>> {\n const res = await this.getText(url, options);\n const body = parseSingleYaml<ResT>(res.body);\n return { ...res, body };\n }\n\n async getYaml<Schema extends ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getYaml<Schema extends ZodType<any, any, any>>(\n url: string,\n options: Opts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getYaml<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: Opts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const url = arg1;\n let schema: Schema;\n let httpOptions: Opts | undefined;\n if (arg3) {\n schema = arg3;\n httpOptions = arg2 as Opts;\n } else {\n schema = arg2 as Schema;\n }\n\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method: 'get',\n };\n\n const res = await this.getText(url, opts);\n const body = await schema.parseAsync(parseSingleYaml(res.body));\n return { ...res, body };\n }\n\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(url: string, schema: Schema): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(\n url: string,\n options: Opts,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(\n arg1: string,\n arg2: Opts | Schema,\n arg3?: Schema,\n ): AsyncResult<ResT, SafeJsonError> {\n const url = arg1;\n let schema: Schema;\n let httpOptions: Opts | undefined;\n if (arg3) {\n schema = arg3;\n httpOptions = arg2 as Opts;\n } else {\n schema = arg2 as Schema;\n }\n\n let res: AsyncResult<HttpResponse<ResT>, SafeJsonError>;\n if (httpOptions) {\n res = Result.wrap(this.getYaml(url, httpOptions, schema));\n } else {\n res = Result.wrap(this.getYaml(url, schema));\n }\n\n return res.transform((response) => Result.ok(response.body));\n }\n\n /**\n * Request JSON and return the response without any validation.\n *\n * The usage of this method is discouraged, please use `getJson` instead.\n *\n * If you're new to Zod schema validation library:\n * - consult the [documentation of Zod library](https://github.com/colinhacks/zod?tab=readme-ov-file#basic-usage)\n * - search the Renovate codebase for 'zod' module usage\n * - take a look at the `schema-utils.ts` file for Renovate-specific schemas and utilities\n */\n getJsonUnchecked<ResT = unknown>(\n url: string,\n options?: JSONOpts,\n ): Promise<HttpResponse<ResT>> {\n return this.requestJson<ResT>('get', { url, httpOptions: options });\n }\n\n /**\n * Request JSON with a Zod schema for the response,\n * throwing an error if the response is not valid.\n *\n * @param url\n * @param schema Zod schema for the response\n */\n getJson<Schema extends ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n getJson<Schema extends ZodType<any, any, any>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n getJson<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const args = this.resolveArgs<z.infer<Schema>>(arg1, arg2, arg3);\n return this.requestJson<z.infer<Schema>>('get', args);\n }\n\n /**\n * Request JSON with a Zod schema for the response,\n * wrapping response data in a `Result` class.\n *\n * @param url\n * @param schema Zod schema for the response\n */\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n url: string,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): AsyncResult<ResT, SafeJsonError> {\n const args = this.resolveArgs<ResT>(arg1, arg2, arg3);\n return Result.wrap(this.requestJson<ResT>('get', args)).transform(\n (response) => Result.ok(response.body),\n );\n }\n\n /**\n * @deprecated use `head` instead\n */\n headJson(url: string, httpOptions?: JSONOpts): Promise<HttpResponse<never>> {\n return this.requestJson<never>('head', { url, httpOptions });\n }\n\n postJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n postJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n postJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n postJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('post', args);\n }\n\n putJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n putJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n putJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n putJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: ZodType,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('put', args);\n }\n\n patchJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n patchJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n patchJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n patchJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('patch', args);\n }\n\n deleteJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n deleteJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n deleteJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n deleteJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('delete', args);\n }\n\n stream(url: string, options?: HttpOptions): NodeJS.ReadableStream {\n let combinedOptions: Merge<\n GotStreamOptions,\n SetRequired<InternalHttpOptions, 'method'>\n > = {\n ...this.options,\n hostType: this.hostType,\n ...options,\n method: 'get',\n };\n\n const resolvedUrl = this.resolveUrl(url, options).toString();\n\n applyDefaultHeaders(combinedOptions);\n\n // v8 ignore else -- TODO: add test #40625\n if (\n isUndefined(combinedOptions.readOnly) &&\n ['head', 'get'].includes(combinedOptions.method)\n ) {\n combinedOptions.readOnly = true;\n }\n\n const hostRule = findMatchingRule(url, combinedOptions);\n combinedOptions = applyHostRule(resolvedUrl, combinedOptions, hostRule);\n if (combinedOptions.enabled === false) {\n throw new Error(HOST_DISABLED);\n }\n combinedOptions = applyAuthorization(combinedOptions);\n\n return stream(resolvedUrl, combinedOptions);\n }\n\n async getToml<Schema extends ZodType<any, any, any>>(\n url: string,\n schema?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getToml<Schema extends ZodType<any, any, any>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getToml<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const { url, schema, httpOptions } = this.resolveArgs<z.infer<Schema>>(\n arg1,\n arg2,\n arg3,\n );\n\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method: 'get',\n headers: {\n 'Content-Type': 'application/toml',\n ...httpOptions?.headers,\n },\n };\n\n const res = await this.getText(url, opts);\n if (schema) {\n res.body = await Toml.pipe(schema).parseAsync(res.body);\n } else {\n res.body = (await Toml.parseAsync(res.body)) as z.infer<Schema>;\n }\n\n return res;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"http.js","names":["memCache.get"],"sources":["../../../lib/util/http/http.ts"],"sourcesContent":["import { isPlainObject, isUndefined } from '@sindresorhus/is';\nimport merge from 'deepmerge';\nimport type { Options, RetryObject } from 'got';\nimport type { Merge, SetRequired } from 'type-fest';\nimport type { z } from 'zod';\nimport { ZodType } from 'zod';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { HOST_DISABLED } from '../../constants/error-messages.ts';\nimport { pkg } from '../../expose.ts';\nimport { logger } from '../../logger/index.ts';\nimport { ExternalHostError } from '../../types/errors/external-host-error.ts';\nimport * as memCache from '../cache/memory/index.ts';\nimport { getEnv } from '../env.ts';\nimport { hash } from '../hash.ts';\nimport { acquireLock } from '../mutex.ts';\nimport { type AsyncResult, Result } from '../result.ts';\nimport { Toml } from '../schema-utils/index.ts';\nimport { ObsoleteCacheHitLogger } from '../stats.ts';\nimport { isHttpUrl, parseUrl, resolveBaseUrl } from '../url.ts';\nimport { parseSingleYaml } from '../yaml.ts';\nimport { applyAuthorization, removeAuthorization } from './auth.ts';\nimport type { HttpCacheProvider } from './cache/types.ts';\nimport { fetch, stream } from './got.ts';\nimport { applyHostRule, findMatchingRule } from './host-rules.ts';\n\nimport { getQueue } from './queue.ts';\nimport { getRetryAfter, wrapWithRetry } from './retry-after.ts';\nimport { getThrottle } from './throttle.ts';\nimport type {\n GotOptions,\n GotStreamOptions,\n GotTask,\n HttpMethod,\n HttpOptions,\n HttpResponse,\n SafeJsonError,\n} from './types.ts';\nimport { copyResponse } from './util.ts';\n\nexport interface InternalJsonUnsafeOptions<\n Opts extends HttpOptions = HttpOptions,\n> {\n url: string | URL;\n httpOptions?: Opts;\n}\n\nexport interface InternalJsonOptions<\n Opts extends HttpOptions,\n ResT = unknown,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n> extends InternalJsonUnsafeOptions<Opts> {\n schema?: Schema;\n}\n\nexport type InternalGotOptions = SetRequired<GotOptions, 'method' | 'context'>;\n\nexport interface InternalHttpOptions extends HttpOptions {\n json?: HttpOptions['body'];\n\n method?: HttpMethod;\n\n parseJson?: Options['parseJson'];\n}\n\nexport function applyDefaultHeaders(options: Options): void {\n const renovateVersion = pkg.version;\n options.headers = {\n ...options.headers,\n 'user-agent':\n GlobalConfig.get('userAgent') ??\n `Renovate/${renovateVersion} (https://github.com/renovatebot/renovate)`,\n };\n}\n\nexport abstract class HttpBase<\n JSONOpts extends HttpOptions = HttpOptions,\n Opts extends HttpOptions = HttpOptions,\n> {\n private readonly options: InternalGotOptions;\n\n protected get baseUrl(): string | undefined {\n return undefined;\n }\n\n protected hostType: string;\n\n constructor(hostType: string, options: HttpOptions = {}) {\n this.hostType = hostType;\n const retryLimit = getEnv().NODE_ENV === 'test' ? 0 : 2;\n this.options = merge<InternalGotOptions>(\n options,\n {\n method: 'get',\n context: { hostType },\n retry: {\n calculateDelay: (retryObject) =>\n this.calculateRetryDelay(retryObject),\n limit: retryLimit,\n maxRetryAfter: 0, // Don't rely on `got` retry-after handling, just let it fail and then we'll handle it\n },\n },\n { isMergeableObject: isPlainObject },\n );\n }\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions,\n ): Promise<HttpResponse<string>>;\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'text' },\n ): Promise<HttpResponse<string>>;\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'buffer' },\n ): Promise<HttpResponse<Buffer>>;\n private async request<T = unknown>(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'json' },\n ): Promise<HttpResponse<T>>;\n\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions,\n ): Promise<HttpResponse<unknown>> {\n const resolvedUrl = this.resolveUrl(requestUrl, httpOptions);\n const url = resolvedUrl.toString();\n\n this.processOptions(resolvedUrl, httpOptions);\n\n let options = merge<InternalGotOptions, InternalHttpOptions>(\n {\n ...this.options,\n hostType: this.hostType,\n },\n httpOptions,\n { isMergeableObject: isPlainObject },\n );\n\n const method = options.method.toLowerCase();\n const isReadMethod = ['head', 'get'].includes(method);\n\n logger.trace(`HTTP request: ${method.toUpperCase()} ${url}`);\n\n options.hooks = {\n beforeRedirect: [removeAuthorization],\n };\n\n applyDefaultHeaders(options);\n\n if (isUndefined(options.readOnly) && isReadMethod) {\n options.readOnly = true;\n }\n\n const hostRule = findMatchingRule(url, options);\n options = applyHostRule(url, options, hostRule);\n if (options.enabled === false) {\n logger.debug(`Host is disabled - rejecting request. HostUrl: ${url}`);\n throw new Error(HOST_DISABLED);\n }\n options = applyAuthorization(options);\n const timeout = options.timeout ?? 60000;\n options.timeout = timeout;\n\n let cacheProvider: HttpCacheProvider | undefined;\n if (isReadMethod && options.cacheProvider) {\n cacheProvider = options.cacheProvider;\n }\n\n const memCacheKey =\n !process.env.RENOVATE_X_DISABLE_HTTP_MEMCACHE &&\n !cacheProvider &&\n options.memCache !== false &&\n isReadMethod\n ? hash(\n `got-${JSON.stringify({\n url,\n headers: options.headers,\n method,\n })}`,\n )\n : null;\n\n let resPromise: Promise<HttpResponse<unknown>> | null = null;\n\n // Cache GET requests unless memCache=false\n if (memCacheKey) {\n resPromise = memCache.get(memCacheKey);\n\n /* v8 ignore next: temporary code */\n if (resPromise && !cacheProvider) {\n ObsoleteCacheHitLogger.write(url);\n }\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (!resPromise) {\n if (cacheProvider) {\n await cacheProvider.setCacheHeaders(method, url, options);\n }\n\n const startTime = Date.now();\n const httpTask: GotTask = async () => {\n let releaseLock: undefined | (() => void);\n if (isReadMethod) {\n releaseLock = await acquireLock(\n `${options.method} ${url}`,\n 'http-mutex',\n timeout * 2,\n );\n }\n try {\n const cachedResponse = await cacheProvider?.bypassServer<unknown>(\n options.method,\n url,\n );\n if (cachedResponse) {\n return cachedResponse;\n }\n\n const queueMs = Date.now() - startTime;\n return fetch(url, options, { queueMs });\n } finally {\n releaseLock?.();\n }\n };\n\n const throttle = getThrottle(url);\n const throttledTask = throttle ? () => throttle.add(httpTask) : httpTask;\n\n const queue = getQueue(url);\n const queuedTask = queue ? () => queue.add(throttledTask) : throttledTask;\n\n const { maxRetryAfter = 60 } = hostRule;\n resPromise = wrapWithRetry(queuedTask, url, getRetryAfter, maxRetryAfter);\n\n if (memCacheKey) {\n memCache.set(memCacheKey, resPromise);\n }\n }\n\n try {\n const res = await resPromise;\n const deepCopyNeeded = !!memCacheKey && res.statusCode !== 304;\n const resCopy = copyResponse(res, deepCopyNeeded);\n resCopy.authorization = !!options?.headers?.authorization;\n\n if (cacheProvider) {\n return await cacheProvider.wrapServerResponse(method, url, resCopy);\n }\n\n return resCopy;\n } catch (err) {\n const { abortOnError, abortIgnoreStatusCodes } = options;\n if (abortOnError && !abortIgnoreStatusCodes?.includes(err.statusCode)) {\n throw new ExternalHostError(err);\n }\n\n const staleResponse = await cacheProvider?.bypassServer<string | Buffer>(\n method,\n url,\n true,\n );\n if (staleResponse) {\n logger.debug(\n { err },\n `Request error: returning stale cache instead for ${url}`,\n );\n return staleResponse;\n }\n\n this.handleError(requestUrl, httpOptions, err);\n }\n }\n\n protected processOptions(_url: URL, _options: InternalHttpOptions): void {\n // noop\n }\n\n protected handleError(\n _url: string | URL,\n _httpOptions: HttpOptions,\n err: Error,\n ): never {\n throw err;\n }\n\n resolveUrl(\n requestUrl: string | URL,\n options: HttpOptions | undefined = undefined,\n ): URL {\n let url = requestUrl;\n\n if (url instanceof URL) {\n // already a aboslute URL\n return url;\n }\n\n const baseUrl = options?.baseUrl ?? this.baseUrl;\n if (baseUrl) {\n url = resolveBaseUrl(baseUrl, url);\n }\n\n const parsedUrl = parseUrl(url);\n if (!parsedUrl || !isHttpUrl(parsedUrl)) {\n logger.error(\n { url: requestUrl, baseUrl, resolvedUrl: url },\n 'Request Error: cannot parse url',\n );\n throw new Error('Invalid URL');\n }\n return parsedUrl;\n }\n\n protected calculateRetryDelay({ computedValue }: RetryObject): number {\n return computedValue;\n }\n\n get(\n url: string,\n options: HttpOptions = {},\n ): Promise<HttpResponse<string | Buffer>> {\n return this.request(url, options);\n }\n\n head(url: string, options: HttpOptions = {}): Promise<HttpResponse<never>> {\n // to complex to validate\n return this.request(url, {\n ...options,\n responseType: 'text',\n method: 'head',\n }) as Promise<HttpResponse<never>>;\n }\n\n getText(\n url: string | URL,\n options: HttpOptions = {},\n ): Promise<HttpResponse<string>> {\n return this.request(url, { ...options, responseType: 'text' });\n }\n\n getBuffer(\n url: string | URL,\n options: HttpOptions = {},\n ): Promise<HttpResponse<Buffer>> {\n return this.request(url, { ...options, responseType: 'buffer' });\n }\n\n protected requestJsonUnsafe<ResT>(\n method: HttpMethod,\n { url, httpOptions: requestOptions }: InternalJsonUnsafeOptions<JSONOpts>,\n ): Promise<HttpResponse<ResT>> {\n const { body: json, ...httpOptions } = { ...requestOptions };\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method,\n };\n // signal that we expect a json response\n opts.headers = {\n accept: 'application/json',\n ...opts.headers,\n };\n if (json) {\n opts.json = json;\n }\n return this.request<ResT>(url, { ...opts, responseType: 'json' });\n }\n\n private async requestJson<ResT, Schema extends ZodType<ResT> = ZodType<ResT>>(\n method: HttpMethod,\n options: InternalJsonOptions<JSONOpts, ResT, Schema>,\n ): Promise<HttpResponse<ResT>> {\n const res = await this.requestJsonUnsafe<ResT>(method, options);\n\n if (options.schema) {\n res.body = await options.schema.parseAsync(res.body);\n }\n\n return res;\n }\n\n private resolveArgs<ResT = unknown>(\n arg1: string,\n arg2: JSONOpts | ZodType<ResT> | undefined,\n arg3: ZodType<ResT> | undefined,\n ): InternalJsonOptions<JSONOpts, ResT> {\n const res: InternalJsonOptions<JSONOpts, ResT> = { url: arg1 };\n\n if (arg2 instanceof ZodType) {\n res.schema = arg2;\n } else if (arg2) {\n res.httpOptions = arg2;\n }\n\n if (arg3) {\n res.schema = arg3;\n }\n\n return res;\n }\n\n async getPlain(url: string, options?: Opts): Promise<HttpResponse> {\n const opt = options ?? {};\n return await this.getText(url, {\n headers: {\n Accept: 'text/plain',\n },\n ...opt,\n });\n }\n\n /**\n * @deprecated use `getYaml` instead\n */\n async getYamlUnchecked<ResT>(\n url: string,\n options?: Opts,\n ): Promise<HttpResponse<ResT>> {\n const res = await this.getText(url, options);\n const body = parseSingleYaml<ResT>(res.body);\n return { ...res, body };\n }\n\n async getYaml<Schema extends ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getYaml<Schema extends ZodType<any, any, any>>(\n url: string,\n options: Opts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getYaml<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: Opts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const url = arg1;\n let schema: Schema;\n let httpOptions: Opts | undefined;\n if (arg3) {\n schema = arg3;\n httpOptions = arg2 as Opts;\n } else {\n schema = arg2 as Schema;\n }\n\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method: 'get',\n };\n\n const res = await this.getText(url, opts);\n const body = await schema.parseAsync(parseSingleYaml(res.body));\n return { ...res, body };\n }\n\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(url: string, schema: Schema): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(\n url: string,\n options: Opts,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(\n arg1: string,\n arg2: Opts | Schema,\n arg3?: Schema,\n ): AsyncResult<ResT, SafeJsonError> {\n const url = arg1;\n let schema: Schema;\n let httpOptions: Opts | undefined;\n if (arg3) {\n schema = arg3;\n httpOptions = arg2 as Opts;\n } else {\n schema = arg2 as Schema;\n }\n\n let res: AsyncResult<HttpResponse<ResT>, SafeJsonError>;\n if (httpOptions) {\n res = Result.wrap(this.getYaml(url, httpOptions, schema));\n } else {\n res = Result.wrap(this.getYaml(url, schema));\n }\n\n return res.transform((response) => Result.ok(response.body));\n }\n\n /**\n * Request JSON and return the response without any validation.\n *\n * The usage of this method is discouraged, please use `getJson` instead.\n *\n * If you're new to Zod schema validation library:\n * - consult the [documentation of Zod library](https://github.com/colinhacks/zod?tab=readme-ov-file#basic-usage)\n * - search the Renovate codebase for 'zod' module usage\n * - take a look at the `schema-utils.ts` file for Renovate-specific schemas and utilities\n */\n getJsonUnchecked<ResT = unknown>(\n url: string,\n options?: JSONOpts,\n ): Promise<HttpResponse<ResT>> {\n return this.requestJson<ResT>('get', { url, httpOptions: options });\n }\n\n /**\n * Request JSON with a Zod schema for the response,\n * throwing an error if the response is not valid.\n *\n * @param url\n * @param schema Zod schema for the response\n */\n getJson<Schema extends ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n getJson<Schema extends ZodType<any, any, any>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n getJson<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const args = this.resolveArgs<z.infer<Schema>>(arg1, arg2, arg3);\n return this.requestJson<z.infer<Schema>>('get', args);\n }\n\n /**\n * Request JSON with a Zod schema for the response,\n * wrapping response data in a `Result` class.\n *\n * @param url\n * @param schema Zod schema for the response\n */\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n url: string,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): AsyncResult<ResT, SafeJsonError> {\n const args = this.resolveArgs<ResT>(arg1, arg2, arg3);\n return Result.wrap(this.requestJson<ResT>('get', args)).transform(\n (response) => Result.ok(response.body),\n );\n }\n\n /**\n * @deprecated use `head` instead\n */\n headJson(url: string, httpOptions?: JSONOpts): Promise<HttpResponse<never>> {\n return this.requestJson<never>('head', { url, httpOptions });\n }\n\n postJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n postJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n postJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n postJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('post', args);\n }\n\n putJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n putJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n putJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n putJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: ZodType,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('put', args);\n }\n\n patchJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n patchJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n patchJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n patchJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('patch', args);\n }\n\n deleteJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n deleteJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n deleteJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n deleteJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('delete', args);\n }\n\n stream(url: string, options?: HttpOptions): NodeJS.ReadableStream {\n let combinedOptions: Merge<\n GotStreamOptions,\n SetRequired<InternalHttpOptions, 'method'>\n > = {\n ...this.options,\n hostType: this.hostType,\n ...options,\n method: 'get',\n };\n\n const resolvedUrl = this.resolveUrl(url, options).toString();\n\n applyDefaultHeaders(combinedOptions);\n\n // v8 ignore else -- TODO: add test #40625\n if (\n isUndefined(combinedOptions.readOnly) &&\n ['head', 'get'].includes(combinedOptions.method)\n ) {\n combinedOptions.readOnly = true;\n }\n\n const hostRule = findMatchingRule(url, combinedOptions);\n combinedOptions = applyHostRule(resolvedUrl, combinedOptions, hostRule);\n if (combinedOptions.enabled === false) {\n throw new Error(HOST_DISABLED);\n }\n combinedOptions = applyAuthorization(combinedOptions);\n\n return stream(resolvedUrl, combinedOptions);\n }\n\n async getToml<Schema extends ZodType<any, any, any>>(\n url: string,\n schema?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getToml<Schema extends ZodType<any, any, any>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getToml<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const { url, schema, httpOptions } = this.resolveArgs<z.infer<Schema>>(\n arg1,\n arg2,\n arg3,\n );\n\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method: 'get',\n headers: {\n 'Content-Type': 'application/toml',\n ...httpOptions?.headers,\n },\n };\n\n const res = await this.getText(url, opts);\n if (schema) {\n res.body = await Toml.pipe(schema).parseAsync(res.body);\n } else {\n res.body = (await Toml.parseAsync(res.body)) as z.infer<Schema>;\n }\n\n return res;\n }\n}\n"],"mappings":"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"}
|
package/dist/util/mutex.js
CHANGED
|
@@ -2,17 +2,18 @@ import { Mutex, withTimeout } from "async-mutex";
|
|
|
2
2
|
|
|
3
3
|
//#region lib/util/mutex.ts
|
|
4
4
|
const DEFAULT_NAMESPACE = "default";
|
|
5
|
+
const DEFAULT_TIMEOUT_MS = 120 * 1e3;
|
|
5
6
|
let mutexes = {};
|
|
6
7
|
function initMutexes() {
|
|
7
8
|
mutexes = {};
|
|
8
9
|
}
|
|
9
10
|
function getMutex(key, namespace = DEFAULT_NAMESPACE) {
|
|
10
11
|
mutexes[namespace] ??= {};
|
|
11
|
-
mutexes[namespace][key] ??=
|
|
12
|
+
mutexes[namespace][key] ??= new Mutex();
|
|
12
13
|
return mutexes[namespace][key];
|
|
13
14
|
}
|
|
14
|
-
function acquireLock(key, namespace = DEFAULT_NAMESPACE) {
|
|
15
|
-
return getMutex(key, namespace).acquire();
|
|
15
|
+
function acquireLock(key, namespace = DEFAULT_NAMESPACE, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
16
|
+
return withTimeout(getMutex(key, namespace), timeoutMs).acquire();
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
//#endregion
|
package/dist/util/mutex.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutex.js","names":[],"sources":["../../lib/util/mutex.ts"],"sourcesContent":["import { Mutex, type MutexInterface, withTimeout } from 'async-mutex';\n\nconst DEFAULT_NAMESPACE = 'default';\nlet mutexes: Record<string, Record<string,
|
|
1
|
+
{"version":3,"file":"mutex.js","names":[],"sources":["../../lib/util/mutex.ts"],"sourcesContent":["import { Mutex, type MutexInterface, withTimeout } from 'async-mutex';\n\nconst DEFAULT_NAMESPACE = 'default';\nconst DEFAULT_TIMEOUT_MS = 2 * 60 * 1000;\nlet mutexes: Record<string, Record<string, Mutex>> = {};\n\nexport function initMutexes(): void {\n mutexes = {};\n}\n\nexport function getMutex(\n key: string,\n namespace: string = DEFAULT_NAMESPACE,\n): Mutex {\n mutexes[namespace] ??= {};\n mutexes[namespace][key] ??= new Mutex();\n return mutexes[namespace][key];\n}\n\nexport function acquireLock(\n key: string,\n namespace: string = DEFAULT_NAMESPACE,\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n): Promise<MutexInterface.Releaser> {\n return withTimeout(getMutex(key, namespace), timeoutMs).acquire();\n}\n"],"mappings":";;;AAEA,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB,MAAS;AACpC,IAAI,UAAiD,EAAE;AAEvD,SAAgB,cAAoB;AAClC,WAAU,EAAE;;AAGd,SAAgB,SACd,KACA,YAAoB,mBACb;AACP,SAAQ,eAAe,EAAE;AACzB,SAAQ,WAAW,SAAS,IAAI,OAAO;AACvC,QAAO,QAAQ,WAAW;;AAG5B,SAAgB,YACd,KACA,YAAoB,mBACpB,YAAoB,oBACc;AAClC,QAAO,YAAY,SAAS,KAAK,UAAU,EAAE,UAAU,CAAC,SAAS"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "renovate",
|
|
3
3
|
"description": "Automated dependency updates. Flexible so you don't need to be.",
|
|
4
|
-
"version": "43.24.
|
|
4
|
+
"version": "43.24.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"renovate": "dist/renovate.js",
|
|
@@ -226,7 +226,7 @@
|
|
|
226
226
|
"@ls-lint/ls-lint": "2.3.1",
|
|
227
227
|
"@openpgp/web-stream-tools": "0.3.0",
|
|
228
228
|
"@semantic-release/exec": "7.1.0",
|
|
229
|
-
"@smithy/util-stream": "4.5.
|
|
229
|
+
"@smithy/util-stream": "4.5.12",
|
|
230
230
|
"@types/auth-header": "1.0.6",
|
|
231
231
|
"@types/aws4": "1.11.6",
|
|
232
232
|
"@types/better-sqlite3": "7.6.13",
|
|
@@ -264,7 +264,7 @@
|
|
|
264
264
|
"@types/validate-npm-package-name": "4.0.2",
|
|
265
265
|
"@vitest/coverage-v8": "4.0.18",
|
|
266
266
|
"@vitest/eslint-plugin": "1.6.7",
|
|
267
|
-
"ajv": "8.
|
|
267
|
+
"ajv": "8.18.0",
|
|
268
268
|
"ajv-formats": "3.0.1",
|
|
269
269
|
"aws-sdk-client-mock": "4.1.0",
|
|
270
270
|
"callsite": "1.0.0",
|
|
@@ -277,7 +277,7 @@
|
|
|
277
277
|
"eslint-formatter-gha": "2.0.1",
|
|
278
278
|
"eslint-import-resolver-typescript": "4.4.4",
|
|
279
279
|
"eslint-plugin-import-x": "4.16.1",
|
|
280
|
-
"eslint-plugin-oxlint": "1.
|
|
280
|
+
"eslint-plugin-oxlint": "1.46.0",
|
|
281
281
|
"eslint-plugin-promise": "7.2.1",
|
|
282
282
|
"expect-more-jest": "5.5.0",
|
|
283
283
|
"globals": "17.3.0",
|
|
@@ -291,7 +291,7 @@
|
|
|
291
291
|
"nock": "14.0.11",
|
|
292
292
|
"npm-run-all2": "8.0.4",
|
|
293
293
|
"nyc": "17.1.0",
|
|
294
|
-
"oxlint": "1.
|
|
294
|
+
"oxlint": "1.46.0",
|
|
295
295
|
"rimraf": "6.1.2",
|
|
296
296
|
"semantic-release": "25.0.3",
|
|
297
297
|
"tar": "7.5.7",
|
package/renovate-schema.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"title": "JSON schema for Renovate 43.24.
|
|
2
|
+
"title": "JSON schema for Renovate 43.24.1 config files (https://renovatebot.com/)",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
|
-
"x-renovate-version": "43.24.
|
|
4
|
+
"x-renovate-version": "43.24.1",
|
|
5
5
|
"allowComments": true,
|
|
6
6
|
"type": "object",
|
|
7
7
|
"properties": {
|