renovate 43.59.2 → 43.59.4

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.
@@ -105,7 +105,7 @@ var CrateDatasource = class CrateDatasource extends Datasource {
105
105
  const registryConfig = await this.fetchRegistryConfig(info);
106
106
  if (!registryConfig?.api) return null;
107
107
  const crateUrl = `${joinUrlParts(registryConfig.api, "api/v1/")}crates/${packageName}?include=`;
108
- logger.debug({
108
+ logger.trace({
109
109
  crateUrl,
110
110
  packageName,
111
111
  registryUrl: info.rawUrl
@@ -113,7 +113,7 @@ var CrateDatasource = class CrateDatasource extends Datasource {
113
113
  try {
114
114
  return (await this.http.getJsonUnchecked(crateUrl)).body.crate;
115
115
  } catch (err) {
116
- logger.warn({
116
+ logger.debug({
117
117
  err,
118
118
  packageName,
119
119
  registryUrl: info.rawUrl
@@ -133,6 +133,11 @@ var CrateDatasource = class CrateDatasource extends Datasource {
133
133
  if (info.clonePath) return readCacheFile(upath.join(info.clonePath, ...CrateDatasource.getIndexSuffix(packageName)), "utf8");
134
134
  const packageSuffix = CrateDatasource.getIndexSuffix(packageName.toLowerCase());
135
135
  const crateUrl = joinUrlParts(info.rawUrl, ...packageSuffix);
136
+ logger.trace({
137
+ crateUrl,
138
+ packageName,
139
+ registryUrl: info.rawUrl
140
+ }, "fetching crate records from sparse index");
136
141
  try {
137
142
  return (await this.http.getText(crateUrl)).body;
138
143
  } catch (err) {
@@ -297,6 +302,12 @@ var CrateDatasource = class CrateDatasource extends Datasource {
297
302
  const config = get(cacheKey);
298
303
  if (!config?.api) return release;
299
304
  const url = `${joinUrlParts(config.api, "api/v1/")}crates/${packageName}/${release.versionOrig ?? release.version}`;
305
+ logger.trace({
306
+ url,
307
+ packageName,
308
+ version: release.version,
309
+ registryUrl
310
+ }, "fetching crate release timestamp");
300
311
  const { body: releaseTimestamp } = await this.http.getJson(url, { cacheProvider: memCacheProvider }, ReleaseTimestamp);
301
312
  release.releaseTimestamp = releaseTimestamp;
302
313
  return release;
@@ -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 { Json } from '../../../util/schema-utils/index.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 { RegistryConfigSchema, 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 = ['sparse+https://index.crates.io/'];\n\n override defaultVersioning = cargoVersioning.id;\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.isCratesIo(config.registryUrl),\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n /**\n * Fetches the registry's config.json which provides the API base URL\n * and download URL template.\n * See: https://doc.rust-lang.org/cargo/reference/registry-index.html#index-configuration\n */\n private async fetchRegistryConfig(\n info: RegistryInfo,\n ): Promise<RegistryConfigSchema | null> {\n const cacheKey = `crate-datasource/registry-config/${info.rawUrl}`;\n const cached = memCache.get<RegistryConfigSchema>(cacheKey);\n if (cached) {\n return cached;\n }\n\n if (info.clonePath) {\n try {\n const configPath = upath.join(info.clonePath, 'config.json');\n const content = await readCacheFile(configPath, 'utf8');\n const parsed = Json.pipe(RegistryConfigSchema).parse(content);\n memCache.set(cacheKey, parsed);\n return parsed;\n } catch {\n logger.debug(\n { registryUrl: info.rawUrl },\n 'Could not read config.json from cloned registry',\n );\n }\n } else {\n try {\n const configUrl = joinUrlParts(info.rawUrl, 'config.json');\n const { body } = await this.http.getJson(\n configUrl,\n RegistryConfigSchema,\n );\n memCache.set(cacheKey, body);\n return body;\n } catch {\n logger.debug(\n { registryUrl: info.rawUrl },\n 'Could not fetch registry config.json',\n );\n }\n }\n\n return null;\n }\n\n private async _getCrateMetadata(\n info: RegistryInfo,\n packageName: string,\n ): Promise<CrateMetadata | null> {\n const registryConfig = await this.fetchRegistryConfig(info);\n if (!registryConfig?.api) {\n return null;\n }\n\n const apiBaseUrl = joinUrlParts(registryConfig.api, 'api/v1/');\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 = `${apiBaseUrl}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: info.flavor === 'crates.io',\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 // sparse index\n const packageSuffix = CrateDatasource.getIndexSuffix(\n packageName.toLowerCase(),\n );\n const crateUrl = joinUrlParts(info.rawUrl, ...packageSuffix);\n try {\n return (await this.http.getText(crateUrl)).body;\n } catch (err) {\n this.handleGenericErrors(err);\n }\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.url}/${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 === 'index.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 };\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 (!isSparseRegistry) {\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 isCratesIo(registryUrl: string | undefined): boolean {\n if (!registryUrl) {\n return false;\n }\n const normalized = registryUrl.replace(regEx(/^sparse\\+/), '');\n const parsed = parseUrl(normalized);\n return parsed?.hostname === 'index.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) {\n return release;\n }\n\n // Look up the registry config from cache (populated during getReleases)\n const rawUrl = registryUrl?.replace(/^sparse\\+/, '');\n if (!rawUrl) {\n return release;\n }\n const cacheKey = `crate-datasource/registry-config/${rawUrl}`;\n const config = memCache.get<{ dl: string; api?: string }>(cacheKey);\n if (!config?.api) {\n return release;\n }\n\n const apiBaseUrl = joinUrlParts(config.api, 'api/v1/');\n const url = `${apiBaseUrl}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: CrateDatasource.isCratesIo(config.registryUrl ?? undefined),\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 { Json } from '../../../util/schema-utils/index.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 { RegistryConfigSchema, 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 = ['sparse+https://index.crates.io/'];\n\n override defaultVersioning = cargoVersioning.id;\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.isCratesIo(config.registryUrl),\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n /**\n * Fetches the registry's config.json which provides the API base URL\n * and download URL template.\n * See: https://doc.rust-lang.org/cargo/reference/registry-index.html#index-configuration\n */\n private async fetchRegistryConfig(\n info: RegistryInfo,\n ): Promise<RegistryConfigSchema | null> {\n const cacheKey = `crate-datasource/registry-config/${info.rawUrl}`;\n const cached = memCache.get<RegistryConfigSchema>(cacheKey);\n if (cached) {\n return cached;\n }\n\n if (info.clonePath) {\n try {\n const configPath = upath.join(info.clonePath, 'config.json');\n const content = await readCacheFile(configPath, 'utf8');\n const parsed = Json.pipe(RegistryConfigSchema).parse(content);\n memCache.set(cacheKey, parsed);\n return parsed;\n } catch {\n logger.debug(\n { registryUrl: info.rawUrl },\n 'Could not read config.json from cloned registry',\n );\n }\n } else {\n try {\n const configUrl = joinUrlParts(info.rawUrl, 'config.json');\n const { body } = await this.http.getJson(\n configUrl,\n RegistryConfigSchema,\n );\n memCache.set(cacheKey, body);\n return body;\n } catch {\n logger.debug(\n { registryUrl: info.rawUrl },\n 'Could not fetch registry config.json',\n );\n }\n }\n\n return null;\n }\n\n private async _getCrateMetadata(\n info: RegistryInfo,\n packageName: string,\n ): Promise<CrateMetadata | null> {\n const registryConfig = await this.fetchRegistryConfig(info);\n if (!registryConfig?.api) {\n return null;\n }\n\n const apiBaseUrl = joinUrlParts(registryConfig.api, 'api/v1/');\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 = `${apiBaseUrl}crates/${packageName}?include=`;\n\n logger.trace(\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.debug(\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: info.flavor === 'crates.io',\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 // sparse index\n const packageSuffix = CrateDatasource.getIndexSuffix(\n packageName.toLowerCase(),\n );\n const crateUrl = joinUrlParts(info.rawUrl, ...packageSuffix);\n logger.trace(\n { crateUrl, packageName, registryUrl: info.rawUrl },\n 'fetching crate records from sparse index',\n );\n try {\n return (await this.http.getText(crateUrl)).body;\n } catch (err) {\n this.handleGenericErrors(err);\n }\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.url}/${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 === 'index.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 };\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 (!isSparseRegistry) {\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 isCratesIo(registryUrl: string | undefined): boolean {\n if (!registryUrl) {\n return false;\n }\n const normalized = registryUrl.replace(regEx(/^sparse\\+/), '');\n const parsed = parseUrl(normalized);\n return parsed?.hostname === 'index.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) {\n return release;\n }\n\n // Look up the registry config from cache (populated during getReleases)\n const rawUrl = registryUrl?.replace(/^sparse\\+/, '');\n if (!rawUrl) {\n return release;\n }\n const cacheKey = `crate-datasource/registry-config/${rawUrl}`;\n const config = memCache.get<{ dl: string; api?: string }>(cacheKey);\n if (!config?.api) {\n return release;\n }\n\n const apiBaseUrl = joinUrlParts(config.api, 'api/v1/');\n const url = `${apiBaseUrl}crates/${packageName}/${release.versionOrig ?? release.version}`;\n logger.trace(\n { url, packageName, version: release.version, registryUrl },\n 'fetching crate release timestamp',\n );\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: CrateDatasource.isCratesIo(config.registryUrl ?? undefined),\n },\n () => this._postprocessRelease(config, release),\n );\n }\n}\n"],"mappings":"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"}
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.59.2",
4
+ "version": "43.59.4",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "renovate": "dist/renovate.js",
@@ -146,7 +146,7 @@
146
146
  "dequal": "2.0.3",
147
147
  "detect-indent": "7.0.2",
148
148
  "diff": "8.0.3",
149
- "editorconfig": "3.0.1",
149
+ "editorconfig": "3.0.2",
150
150
  "email-addresses": "5.0.0",
151
151
  "emoji-regex": "10.6.0",
152
152
  "emojibase": "17.0.0",
@@ -192,7 +192,7 @@
192
192
  "remark-gfm": "4.0.1",
193
193
  "remark-github": "12.0.0",
194
194
  "safe-stable-stringify": "2.5.0",
195
- "sax": "1.4.4",
195
+ "sax": "1.5.0",
196
196
  "semver": "7.7.4",
197
197
  "semver-stable": "3.0.0",
198
198
  "semver-utils": "1.1.4",
@@ -253,7 +253,7 @@
253
253
  "@types/mdast": "4.0.4",
254
254
  "@types/moo": "0.5.10",
255
255
  "@types/ms": "2.1.0",
256
- "@types/node": "24.10.15",
256
+ "@types/node": "24.11.0",
257
257
  "@types/parse-link-header": "2.0.3",
258
258
  "@types/punycode": "2.1.4",
259
259
  "@types/sax": "1.2.7",
@@ -268,7 +268,7 @@
268
268
  "aws-sdk-client-mock": "4.1.0",
269
269
  "callsite": "1.0.0",
270
270
  "common-tags": "1.8.2",
271
- "conventional-changelog-conventionalcommits": "9.1.0",
271
+ "conventional-changelog-conventionalcommits": "9.2.0",
272
272
  "emojibase-data": "17.0.0",
273
273
  "esbuild": "0.27.3",
274
274
  "eslint": "9.39.3",
@@ -279,11 +279,11 @@
279
279
  "eslint-plugin-oxlint": "1.50.0",
280
280
  "eslint-plugin-promise": "7.2.1",
281
281
  "expect-more-jest": "5.5.0",
282
- "globals": "17.3.0",
282
+ "globals": "17.4.0",
283
283
  "graphql": "16.13.0",
284
284
  "husky": "9.1.7",
285
285
  "jest-extended": "7.0.0",
286
- "lint-staged": "16.2.7",
286
+ "lint-staged": "16.3.1",
287
287
  "markdownlint-cli2": "0.21.0",
288
288
  "markdownlint-cli2-formatter-template": "0.0.4",
289
289
  "memfs": "4.56.10",
@@ -1,7 +1,7 @@
1
1
  {
2
- "title": "JSON schema for Renovate 43.59.2 config files (https://renovatebot.com/)",
2
+ "title": "JSON schema for Renovate 43.59.4 config files (https://renovatebot.com/)",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
- "x-renovate-version": "43.59.2",
4
+ "x-renovate-version": "43.59.4",
5
5
  "allowComments": true,
6
6
  "type": "object",
7
7
  "properties": {