renovate 44.149.1 → 44.149.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/dist/config/presets/index.js +2 -1
  2. package/dist/config/presets/index.js.map +1 -1
  3. package/dist/modules/datasource/artifactory/index.js +2 -1
  4. package/dist/modules/datasource/artifactory/index.js.map +1 -1
  5. package/dist/modules/datasource/aws-eks-addon/index.js +6 -5
  6. package/dist/modules/datasource/aws-eks-addon/index.js.map +1 -1
  7. package/dist/modules/datasource/aws-machine-image/index.js +4 -3
  8. package/dist/modules/datasource/aws-machine-image/index.js.map +1 -1
  9. package/dist/modules/datasource/aws-rds/index.js +2 -1
  10. package/dist/modules/datasource/aws-rds/index.js.map +1 -1
  11. package/dist/modules/datasource/azure-bicep-resource/index.js +2 -1
  12. package/dist/modules/datasource/azure-bicep-resource/index.js.map +1 -1
  13. package/dist/modules/datasource/bazel/index.js +2 -1
  14. package/dist/modules/datasource/bazel/index.js.map +1 -1
  15. package/dist/modules/datasource/bitrise/index.js +2 -1
  16. package/dist/modules/datasource/bitrise/index.js.map +1 -1
  17. package/dist/modules/datasource/buildpacks-registry/index.js +2 -1
  18. package/dist/modules/datasource/buildpacks-registry/index.js.map +1 -1
  19. package/dist/modules/datasource/cdnjs/index.js +3 -2
  20. package/dist/modules/datasource/cdnjs/index.js.map +1 -1
  21. package/dist/modules/datasource/conan/index.js +3 -2
  22. package/dist/modules/datasource/conan/index.js.map +1 -1
  23. package/dist/modules/datasource/conda/index.js +2 -1
  24. package/dist/modules/datasource/conda/index.js.map +1 -1
  25. package/dist/modules/datasource/cpan/index.js +1 -1
  26. package/dist/modules/datasource/cpan/index.js.map +1 -1
  27. package/dist/modules/datasource/crate/index.js +17 -9
  28. package/dist/modules/datasource/crate/index.js.map +1 -1
  29. package/dist/modules/datasource/deb/index.js +3 -2
  30. package/dist/modules/datasource/deb/index.js.map +1 -1
  31. package/dist/modules/datasource/deno/index.js +4 -3
  32. package/dist/modules/datasource/deno/index.js.map +1 -1
  33. package/dist/modules/datasource/docker/index.js +9 -9
  34. package/dist/modules/datasource/docker/index.js.map +1 -1
  35. package/dist/modules/datasource/dotnet-version/index.js +2 -1
  36. package/dist/modules/datasource/dotnet-version/index.js.map +1 -1
  37. package/dist/modules/datasource/elm-package/index.js +2 -1
  38. package/dist/modules/datasource/elm-package/index.js.map +1 -1
  39. package/dist/modules/datasource/endoflife-date/index.js +2 -1
  40. package/dist/modules/datasource/endoflife-date/index.js.map +1 -1
  41. package/dist/modules/datasource/galaxy-collection/index.js +3 -2
  42. package/dist/modules/datasource/galaxy-collection/index.js.map +1 -1
  43. package/dist/modules/datasource/git-host-tags.js +6 -5
  44. package/dist/modules/datasource/git-host-tags.js.map +1 -1
  45. package/dist/modules/datasource/gitea-tags/base.js +5 -4
  46. package/dist/modules/datasource/gitea-tags/base.js.map +1 -1
  47. package/dist/modules/datasource/gitea-tags/util.js +2 -5
  48. package/dist/modules/datasource/gitea-tags/util.js.map +1 -1
  49. package/dist/modules/datasource/github-digest/index.js +3 -5
  50. package/dist/modules/datasource/github-digest/index.js.map +1 -1
  51. package/dist/modules/datasource/github-release-attachments/index.js +3 -2
  52. package/dist/modules/datasource/github-release-attachments/index.js.map +1 -1
  53. package/dist/modules/datasource/gitlab-packages/index.js +2 -1
  54. package/dist/modules/datasource/gitlab-packages/index.js.map +1 -1
  55. package/dist/modules/datasource/gitlab-releases/index.js +2 -1
  56. package/dist/modules/datasource/gitlab-releases/index.js.map +1 -1
  57. package/dist/modules/datasource/gitlab-tags/index.js +3 -2
  58. package/dist/modules/datasource/gitlab-tags/index.js.map +1 -1
  59. package/dist/modules/datasource/glasskube-packages/index.js +2 -1
  60. package/dist/modules/datasource/glasskube-packages/index.js.map +1 -1
  61. package/dist/modules/datasource/go/goproxy-parser.js +3 -2
  62. package/dist/modules/datasource/go/goproxy-parser.js.map +1 -1
  63. package/dist/modules/datasource/go/index.js +4 -3
  64. package/dist/modules/datasource/go/index.js.map +1 -1
  65. package/dist/modules/datasource/go/releases-goproxy.js +6 -3
  66. package/dist/modules/datasource/go/releases-goproxy.js.map +1 -1
  67. package/dist/modules/datasource/go/timestamp-cache.js +3 -1
  68. package/dist/modules/datasource/go/timestamp-cache.js.map +1 -1
  69. package/dist/modules/datasource/golang-version/index.js +1 -1
  70. package/dist/modules/datasource/golang-version/index.js.map +1 -1
  71. package/dist/modules/datasource/gradle-version/index.js +1 -1
  72. package/dist/modules/datasource/gradle-version/index.js.map +1 -1
  73. package/dist/modules/datasource/helm/index.js +2 -1
  74. package/dist/modules/datasource/helm/index.js.map +1 -1
  75. package/dist/modules/datasource/hermit/index.js +3 -2
  76. package/dist/modules/datasource/hermit/index.js.map +1 -1
  77. package/dist/modules/datasource/hex/index.js +3 -2
  78. package/dist/modules/datasource/hex/index.js.map +1 -1
  79. package/dist/modules/datasource/hexpm-bob/index.js +2 -1
  80. package/dist/modules/datasource/hexpm-bob/index.js.map +1 -1
  81. package/dist/modules/datasource/index.js +4 -3
  82. package/dist/modules/datasource/index.js.map +1 -1
  83. package/dist/modules/datasource/java-version/index.js +2 -1
  84. package/dist/modules/datasource/java-version/index.js.map +1 -1
  85. package/dist/modules/datasource/jsr/index.js +2 -1
  86. package/dist/modules/datasource/jsr/index.js.map +1 -1
  87. package/dist/modules/datasource/maven/index.js +2 -1
  88. package/dist/modules/datasource/maven/index.js.map +1 -1
  89. package/dist/modules/datasource/nextcloud/index.js +2 -1
  90. package/dist/modules/datasource/nextcloud/index.js.map +1 -1
  91. package/dist/modules/datasource/node-version/index.js +1 -1
  92. package/dist/modules/datasource/node-version/index.js.map +1 -1
  93. package/dist/modules/datasource/nuget/v3.js +3 -2
  94. package/dist/modules/datasource/nuget/v3.js.map +1 -1
  95. package/dist/modules/datasource/orb/index.js +2 -1
  96. package/dist/modules/datasource/orb/index.js.map +1 -1
  97. package/dist/modules/datasource/packagist/index.js +4 -3
  98. package/dist/modules/datasource/packagist/index.js.map +1 -1
  99. package/dist/modules/datasource/pod/index.js +2 -1
  100. package/dist/modules/datasource/pod/index.js.map +1 -1
  101. package/dist/modules/datasource/python-version/index.js +1 -1
  102. package/dist/modules/datasource/python-version/index.js.map +1 -1
  103. package/dist/modules/datasource/repology/index.js +2 -1
  104. package/dist/modules/datasource/repology/index.js.map +1 -1
  105. package/dist/modules/datasource/rpm/index.js +2 -1
  106. package/dist/modules/datasource/rpm/index.js.map +1 -1
  107. package/dist/modules/datasource/rubygems/index.js +2 -1
  108. package/dist/modules/datasource/rubygems/index.js.map +1 -1
  109. package/dist/modules/datasource/rubygems/metadata-cache.js +2 -1
  110. package/dist/modules/datasource/rubygems/metadata-cache.js.map +1 -1
  111. package/dist/modules/datasource/sbt-package/index.js +11 -10
  112. package/dist/modules/datasource/sbt-package/index.js.map +1 -1
  113. package/dist/modules/datasource/terraform-module/index.js +2 -1
  114. package/dist/modules/datasource/terraform-module/index.js.map +1 -1
  115. package/dist/modules/datasource/terraform-provider/index.js +6 -5
  116. package/dist/modules/datasource/terraform-provider/index.js.map +1 -1
  117. package/dist/modules/datasource/unity3d/index.js +2 -1
  118. package/dist/modules/datasource/unity3d/index.js.map +1 -1
  119. package/dist/modules/datasource/unity3d-packages/index.js +2 -1
  120. package/dist/modules/datasource/unity3d-packages/index.js.map +1 -1
  121. package/dist/modules/manager/bazel/parser.js +3 -1
  122. package/dist/modules/manager/bazel/parser.js.map +1 -1
  123. package/dist/modules/manager/github-actions/extract.js +2 -1
  124. package/dist/modules/manager/github-actions/extract.js.map +1 -1
  125. package/dist/modules/manager/terraform/lockfile/hash.js +2 -1
  126. package/dist/modules/manager/terraform/lockfile/hash.js.map +1 -1
  127. package/dist/modules/platform/bitbucket/pr-cache.js +3 -2
  128. package/dist/modules/platform/bitbucket/pr-cache.js.map +1 -1
  129. package/dist/modules/platform/bitbucket-server/pr-cache.js +3 -2
  130. package/dist/modules/platform/bitbucket-server/pr-cache.js.map +1 -1
  131. package/dist/modules/platform/gitea/pr-cache.js +7 -6
  132. package/dist/modules/platform/gitea/pr-cache.js.map +1 -1
  133. package/dist/modules/platform/gitlab/pr-cache.js +3 -2
  134. package/dist/modules/platform/gitlab/pr-cache.js.map +1 -1
  135. package/dist/util/cache/package/index.js +1 -1
  136. package/dist/util/cache/package/key.js +8 -1
  137. package/dist/util/cache/package/key.js.map +1 -1
  138. package/dist/util/cache/package/with-cache.js +2 -1
  139. package/dist/util/cache/package/with-cache.js.map +1 -1
  140. package/dist/util/exec/containerbase.js +2 -1
  141. package/dist/util/exec/containerbase.js.map +1 -1
  142. package/dist/util/github/graphql/cache-strategies/memory-cache-strategy.js +2 -1
  143. package/dist/util/github/graphql/cache-strategies/memory-cache-strategy.js.map +1 -1
  144. package/dist/util/github/graphql/datasource-fetcher.js +5 -8
  145. package/dist/util/github/graphql/datasource-fetcher.js.map +1 -1
  146. package/dist/util/http/cache/memory-http-cache-provider.js +2 -1
  147. package/dist/util/http/cache/memory-http-cache-provider.js.map +1 -1
  148. package/dist/util/http/cache/package-http-cache-provider.js +2 -1
  149. package/dist/util/http/cache/package-http-cache-provider.js.map +1 -1
  150. package/dist/util/jsonata.js +2 -1
  151. package/dist/util/jsonata.js.map +1 -1
  152. package/dist/util/merge-confidence/index.js +10 -7
  153. package/dist/util/merge-confidence/index.js.map +1 -1
  154. package/dist/workers/repository/update/pr/changelog/release-notes.js +4 -5
  155. package/dist/workers/repository/update/pr/changelog/release-notes.js.map +1 -1
  156. package/dist/workers/repository/update/pr/changelog/source.js +2 -1
  157. package/dist/workers/repository/update/pr/changelog/source.js.map +1 -1
  158. package/package.json +1 -1
  159. package/renovate-schema.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"releases-goproxy.js","names":["p.map","HttpError","goVersioning"],"sources":["../../../../lib/modules/datasource/go/releases-goproxy.ts"],"sourcesContent":["import {\n isNonEmptyString,\n isNonEmptyStringAndNotWhitespace,\n isTruthy,\n} from '@sindresorhus/is';\nimport type { ConstraintsFilter } from '../../../config/types.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { detectPlatform } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport { filterMap } from '../../../util/filter-map.ts';\nimport {\n queryReleases,\n queryTags,\n} from '../../../util/github/graphql/index.ts';\nimport { GithubHttp } from '../../../util/http/github.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport * as p from '../../../util/promises.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport type { Timestamp } from '../../../util/timestamp.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport {\n joinUrlParts,\n parseUrl,\n trimLeadingSlash,\n trimTrailingSlash,\n} from '../../../util/url.ts';\nimport goVersioning from '../../versioning/go-mod-directive/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport { GithubReleasesDatasource } from '../github-releases/index.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\nimport { BaseGoDatasource } from './base.ts';\nimport { getSourceUrl, isPublicGoPackage, publicGoproxyUrl } from './common.ts';\nimport { parseGoproxy, parseNoproxy } from './goproxy-parser.ts';\nimport { GoDirectDatasource } from './releases-direct.ts';\nimport { VersionInfo } from './schema.ts';\nimport { GoVersionTimestampCache } from './timestamp-cache.ts';\n\n/** TODO #42566 */\nconst goVersionRegex = regEx(/^\\s*go\\s+(?<version>[^\\s]+)\\s*$/);\n\nconst modRegex = regEx(/^(?<baseMod>.*?)(?:[./]v(?<majorVersion>\\d+))?$/);\n\nconst versionTagRegex = regEx(/^v\\d/);\n\n/**\n * Modules with a major version of v2 or above which have no `go.mod` are reported by a Go proxy with a `+incompatible` suffix, which is absent from the tag they were published as.\n *\n * @see https://go.dev/ref/mod#non-module-compat\n */\nconst incompatibleSuffixRegex = regEx(/\\+incompatible$/);\n\n/**\n * @see https://go.dev/ref/mod#pseudo-versions\n */\nconst pseudoVersionRegex = regEx(\n /v\\d+\\.\\d+\\.\\d+-(?:\\w+\\.)?(?:0\\.)?(?<timestamp>\\d{14})-(?<digest>[a-f0-9]{12})/i,\n);\n\nexport function pseudoVersionToRelease(pseudoVersion: string): Release | null {\n const match = pseudoVersion.match(pseudoVersionRegex)?.groups;\n if (!match) {\n return null;\n }\n\n const { digest: newDigest, timestamp } = match;\n const releaseTimestamp = asTimestamp(timestamp);\n\n return {\n version: pseudoVersion,\n newDigest,\n releaseTimestamp,\n };\n}\n\n/**\n * A Go module which lives in a subdirectory of its repository is tagged with that subdirectory as a prefix, so `github.com/aws/aws-sdk-go-v2/service/s3` publishes `v1.2.3` as the tag `service/s3/v1.2.3`.\n *\n * @see https://go.dev/ref/mod#vcs-version\n *\n * Because we can't tell from the module path alone where the repository ends and the subdirectory begins, we try each candidate prefix - longest first - against the tags we actually found, in the same way as `filterByPrefix` does for direct lookups.\n */\nexport function getTagPrefix(goModule: string, tags: Iterable<string>): string {\n const nameParts = goModule\n .replace(regEx(/\\/v\\d+$/), '')\n .split('/')\n .slice(1);\n const tagNames = [...tags];\n\n while (nameParts.length) {\n const prefix = `${nameParts.join('/')}/`;\n\n const isUsed = tagNames.some(\n (tag) =>\n tag.startsWith(prefix) &&\n versionTagRegex.test(tag.slice(prefix.length)),\n );\n if (isUsed) {\n return prefix;\n }\n\n nameParts.shift();\n }\n\n return '';\n}\n\nexport class GoProxyDatasource extends Datasource {\n static readonly id = 'go-proxy';\n\n constructor() {\n super(GoProxyDatasource.id);\n }\n\n readonly direct = new GoDirectDatasource();\n\n private readonly githubHttp = new GithubHttp(GithubReleasesDatasource.id);\n\n private async _getReleases(\n config: GetReleasesConfig,\n ): Promise<ReleaseResult | null> {\n const { packageName } = config;\n logger.trace(`goproxy.getReleases(${packageName})`);\n const goproxy = getEnv().GOPROXY ?? `${publicGoproxyUrl},direct`;\n if (goproxy === 'direct') {\n return this.direct.getReleases(config);\n }\n const proxyList = parseGoproxy(goproxy);\n const noproxy = parseNoproxy();\n\n let result: ReleaseResult | null = null;\n let servedByProxy = false;\n\n if (noproxy?.test(packageName)) {\n logger.debug(`Fetching ${packageName} via GONOPROXY match`);\n result = await this.direct.getReleases(config);\n return result;\n }\n\n for (const { url, fallback } of proxyList) {\n try {\n if (url === 'off') {\n break;\n } else if (url === 'direct') {\n result = await this.direct.getReleases(config);\n break;\n }\n\n const res = await this.getVersionsWithInfo(\n url,\n packageName,\n config.constraintsFiltering,\n );\n if (res.releases.length) {\n result = res;\n servedByProxy = true;\n break;\n }\n } catch (err) {\n const potentialHttpError =\n err instanceof ExternalHostError ? err.err : err;\n const statusCode = potentialHttpError?.response?.statusCode;\n const canFallback =\n fallback === '|' ? true : statusCode === 404 || statusCode === 410;\n if (!canFallback) {\n logger.debug(\n { err },\n 'Goproxy error: not falling back to other URLs provided with GOPROXY, rethrowing',\n );\n this.handleGenericErrors(err);\n }\n logger.debug(\n { err },\n 'Goproxy error: trying next URL provided with GOPROXY',\n );\n }\n }\n\n if (result && !result.sourceUrl) {\n try {\n const datasource = await BaseGoDatasource.getDatasource(packageName);\n const sourceUrl = getSourceUrl(datasource);\n if (sourceUrl) {\n result.sourceUrl = sourceUrl;\n }\n } catch (err) {\n logger.trace({ err }, `Can't get datasource for ${packageName}`);\n }\n }\n\n if (result?.sourceUrl && servedByProxy) {\n await this.addGithubTimestamps(\n packageName,\n result.sourceUrl,\n result.releases,\n );\n }\n\n return result;\n }\n\n /**\n * A Go proxy reports the commit time of the tagged commit as a version's `Time`, which can be much earlier than the point at which that version was released.\n *\n * When the module is hosted on GitHub, a GitHub Release's publication time, or - if there's no Release - the git tag's own creation time (distinct from the commit time for an annotated tag), is a better indicator of when the version became available. A Release is preferred over a tag when both exist for the same version.\n */\n async addGithubTimestamps(\n packageName: string,\n sourceUrl: string,\n releases: Release[],\n ): Promise<void> {\n if (detectPlatform(sourceUrl) !== 'github') {\n return;\n }\n\n const parsedUrl = parseUrl(sourceUrl);\n /* v8 ignore next -- detectPlatform only returns a platform for parseable URLs */\n if (!parsedUrl) {\n return;\n }\n\n const repository = trimTrailingSlash(\n trimLeadingSlash(parsedUrl.pathname),\n ).replace(regEx(/\\.git$/), '');\n const githubConfig = {\n packageName: repository,\n registryUrl: parsedUrl.origin,\n };\n\n const [githubTags, githubReleases] = await Promise.all([\n queryTags(githubConfig, this.githubHttp).catch((err) => {\n logger.debug(\n { err, packageName },\n 'Error fetching GitHub Tags for Go module',\n );\n return [];\n }),\n queryReleases(githubConfig, this.githubHttp).catch((err) => {\n logger.debug(\n { err, packageName },\n 'Error fetching GitHub Releases for Go module',\n );\n return [];\n }),\n ]);\n\n const timestamps = new Map<string, Timestamp>();\n for (const { version, releaseTimestamp } of githubTags) {\n timestamps.set(version, releaseTimestamp);\n }\n for (const { version, releaseTimestamp } of githubReleases) {\n timestamps.set(version, releaseTimestamp);\n }\n\n const tagPrefix = getTagPrefix(packageName, timestamps.keys());\n for (const release of releases) {\n const version = release.version.replace(incompatibleSuffixRegex, '');\n const releaseTimestamp = timestamps.get(`${tagPrefix}${version}`);\n if (\n releaseTimestamp &&\n (!release.releaseTimestamp ||\n releaseTimestamp > release.releaseTimestamp)\n ) {\n release.releaseTimestamp = releaseTimestamp;\n }\n }\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${GoProxyDatasource.id}`,\n key: GoProxyDatasource.getCacheKey(config),\n cacheable: isPublicGoPackage(config.packageName),\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n /**\n * Avoid ambiguity when serving from case-insensitive file systems.\n *\n * @see https://golang.org/ref/mod#goproxy-protocol\n */\n encodeCase(input: string): string {\n return input.replace(regEx(/(?:[A-Z])/g), (x) => `!${x.toLowerCase()}`);\n }\n\n async listVersions(baseUrl: string, packageName: string): Promise<Release[]> {\n const url = joinUrlParts(\n baseUrl,\n this.encodeCase(packageName),\n '@v',\n 'list',\n );\n const { body } = await this.http.getText(url);\n return filterMap(body.split(newlineRegex), (str) => {\n if (!isNonEmptyStringAndNotWhitespace(str)) {\n return null;\n }\n\n const [version, timestamp] = str.trim().split(regEx(/\\s+/));\n const release: Release = pseudoVersionToRelease(version) ?? { version };\n\n const releaseTimestamp = asTimestamp(timestamp);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n\n return release;\n });\n }\n\n async versionInfo(\n baseUrl: string,\n packageName: string,\n version: string,\n ): Promise<Release> {\n const url = joinUrlParts(\n baseUrl,\n this.encodeCase(packageName),\n '@v',\n `${version}.info`,\n );\n const res = await this.http.getJson(url, VersionInfo);\n\n const result: Release = {\n version: res.body.Version,\n };\n\n const releaseTimestamp = asTimestamp(res.body.Time);\n if (releaseTimestamp) {\n result.releaseTimestamp = releaseTimestamp;\n }\n\n return result;\n }\n\n /**\n * Retrieve the `go` directive for a given Go Module.\n *\n * NOTE that this means the `go` directive, not the `toolchain` directive.\n */\n async retrieveGoDirectiveForModule(\n baseUrl: string,\n packageName: string,\n version: string,\n ): Promise<string | undefined> {\n return withCache(\n {\n namespace: `datasource-${GoProxyDatasource.id}`,\n key: GoProxyDatasource.getVersionedCacheKey(packageName, version),\n // a module's `go.mod` should /never/ change after it's published. If going via the Go Proxy and the Go Checksum Database, a change in this value will result in build failures.\n ttlMinutes: 100 * 24 * 60,\n cacheable: isPublicGoPackage(packageName),\n },\n () => this._retrieveGoDirectiveForModule(baseUrl, packageName, version),\n );\n }\n\n async _retrieveGoDirectiveForModule(\n baseUrl: string,\n packageName: string,\n version: string,\n ): Promise<string | undefined> {\n const url = joinUrlParts(\n baseUrl,\n this.encodeCase(packageName),\n '@v',\n `${version}.mod`,\n );\n const res = await this.http.getText(url);\n\n let goDirective: string | undefined = undefined;\n\n for (const line of res.body.split('\\n')) {\n const goVersionMatches = goVersionRegex.exec(line)?.groups;\n if (goVersionMatches) {\n goDirective = goVersionMatches.version;\n break;\n }\n }\n\n if (!goDirective) {\n return goDirective;\n }\n\n // always return it in full SemVer format, which can then be matched on using `semver` or `semver-coerced`\n const parts = goDirective.split('.');\n if (parts.length === 1) {\n return `${parts[0]}.0.0`;\n }\n if (parts.length === 2) {\n return `${parts[0]}.${parts[1]}.0`;\n }\n return `${parts[0]}.${parts[1]}.${parts[2]}`;\n }\n\n async getLatestVersion(\n baseUrl: string,\n packageName: string,\n ): Promise<{ version: string; sourceUrl?: string } | null> {\n try {\n const url = joinUrlParts(\n baseUrl,\n this.encodeCase(packageName),\n '@latest',\n );\n const res = await this.http.getJson(url, VersionInfo);\n const { Version: version, Origin: origin } = res.body;\n // Extract sourceUrl from GOPROXY Origin when present, avoiding go-get to\n // vanity hosts (https://github.com/renovatebot/renovate/discussions/44898)\n const sourceUrl =\n origin?.VCS === 'git' && isNonEmptyString(origin.URL)\n ? origin.URL.replace(regEx(/\\.git$/), '')\n : undefined;\n return { version, sourceUrl };\n } catch (err) {\n logger.trace({ err }, 'Failed to get latest version');\n return null;\n }\n }\n\n async getVersionsWithInfo(\n baseUrl: string,\n packageName: string,\n constraintsFiltering: ConstraintsFilter | undefined,\n ): Promise<ReleaseResult> {\n const isGopkgin = packageName.startsWith('gopkg.in/');\n const majorSuffixSeparator = isGopkgin ? '.' : '/';\n const modParts = packageName.match(modRegex)?.groups;\n /* v8 ignore start: defensive - modRegex matches any non-empty package name, so baseMod is always set */\n const baseMod = modParts?.baseMod ?? packageName;\n /* v8 ignore stop */\n const packageMajor = parseInt(modParts?.majorVersion ?? '0', 10);\n\n const result: ReleaseResult = { releases: [] };\n for (let major = packageMajor; ; major += 1) {\n let pkg = `${baseMod}${majorSuffixSeparator}v${major}`;\n if (!isGopkgin && major < 2) {\n pkg = baseMod;\n major += 1; // v0 and v1 are the same module\n }\n\n let releases: Release[] = [];\n\n try {\n const res = await this.listVersions(baseUrl, pkg);\n\n // Artifactory returns all versions in any major (past and future),\n // so starting from v2, we filter them in order to avoid the infinite loop\n const filteredReleases = res.filter(({ version }) => {\n if (major < 2) {\n return true;\n }\n\n return (\n version.split(regEx(/[^\\d]+/)).find(isTruthy) === major.toString()\n );\n });\n\n const timestamps = await GoVersionTimestampCache.init(baseUrl, pkg);\n\n releases = await p.map(filteredReleases, async (versionInfo) => {\n const { version, newDigest, releaseTimestamp } = versionInfo;\n\n if (releaseTimestamp) {\n return { version, newDigest, releaseTimestamp };\n }\n\n const cachedTimestamp = timestamps.get(version);\n if (cachedTimestamp) {\n return { version, releaseTimestamp: cachedTimestamp };\n }\n\n try {\n const release = await this.versionInfo(baseUrl, pkg, version);\n if (release.releaseTimestamp) {\n timestamps.set(version, release.releaseTimestamp);\n }\n return release;\n } catch (err) {\n logger.trace({ err }, `Can't obtain data from ${baseUrl}`);\n return { version };\n }\n });\n\n await timestamps.save();\n\n if (constraintsFiltering === 'strict') {\n releases = await p.map(releases, async (rel) => {\n try {\n const goDirective = await this.retrieveGoDirectiveForModule(\n baseUrl,\n pkg,\n rel.version,\n );\n if (goDirective) {\n rel.constraints ??= {};\n rel.constraints['%goMod'] ??= [];\n rel.constraints['%goMod'].push(goDirective);\n }\n } catch (err) {\n logger.trace(\n { err },\n `Can't obtain \\`go\\` directive from ${baseUrl}`,\n );\n }\n\n return rel;\n });\n }\n\n result.releases.push(...releases);\n } catch (err) {\n const potentialHttpError =\n err instanceof ExternalHostError ? err.err : err;\n const status = potentialHttpError.response?.statusCode;\n if (\n potentialHttpError instanceof HttpError &&\n (status === 404 || status === 403) &&\n major !== packageMajor\n ) {\n break;\n }\n\n throw err;\n }\n\n const latest = await this.getLatestVersion(baseUrl, pkg);\n if (latest) {\n const { version: latestVersion, sourceUrl } = latest;\n result.tags ??= {};\n result.tags.latest ??= latestVersion;\n if (goVersioning.isGreaterThan(latestVersion, result.tags.latest)) {\n result.tags.latest = latestVersion;\n }\n if (sourceUrl) {\n result.sourceUrl ??= sourceUrl;\n }\n if (!result.releases.length) {\n const releaseFromLatest = pseudoVersionToRelease(latestVersion);\n // v8 ignore else -- needs an empty version list plus a non-pseudo latest\n if (releaseFromLatest) {\n result.releases.push(releaseFromLatest);\n }\n }\n }\n\n if (!releases.length) {\n break;\n }\n }\n\n return result;\n }\n\n static getCacheKey({\n packageName,\n constraintsFiltering,\n }: GetReleasesConfig): string {\n const goproxy = getEnv().GOPROXY;\n const noproxy = parseNoproxy();\n const constraintsFilteringKey =\n constraintsFiltering && constraintsFiltering !== 'none'\n ? `@@${constraintsFiltering}`\n : '';\n // TODO: types (#22198)\n return `${packageName}@@${goproxy}@@${noproxy?.toString()}${constraintsFilteringKey}`;\n }\n\n static getVersionedCacheKey(packageName: string, version: string): string {\n const goproxy = getEnv().GOPROXY;\n const noproxy = parseNoproxy();\n // TODO: types (#22198)\n return `${packageName}@@${version}@@${goproxy}@@${noproxy?.toString()}`;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"releases-goproxy.js","names":["p.map","HttpError","goVersioning"],"sources":["../../../../lib/modules/datasource/go/releases-goproxy.ts"],"sourcesContent":["import {\n isNonEmptyString,\n isNonEmptyStringAndNotWhitespace,\n isTruthy,\n} from '@sindresorhus/is';\nimport type { ConstraintsFilter } from '../../../config/types.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { buildCacheKey } from '../../../util/cache/package/key.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { detectPlatform } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport { filterMap } from '../../../util/filter-map.ts';\nimport {\n queryReleases,\n queryTags,\n} from '../../../util/github/graphql/index.ts';\nimport { GithubHttp } from '../../../util/http/github.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport * as p from '../../../util/promises.ts';\nimport { newlineRegex, regEx } from '../../../util/regex.ts';\nimport type { Timestamp } from '../../../util/timestamp.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport {\n joinUrlParts,\n parseUrl,\n trimLeadingSlash,\n trimTrailingSlash,\n} from '../../../util/url.ts';\nimport goVersioning from '../../versioning/go-mod-directive/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport { GithubReleasesDatasource } from '../github-releases/index.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\nimport { BaseGoDatasource } from './base.ts';\nimport { getSourceUrl, isPublicGoPackage, publicGoproxyUrl } from './common.ts';\nimport { parseGoproxy, parseNoproxy } from './goproxy-parser.ts';\nimport { GoDirectDatasource } from './releases-direct.ts';\nimport { VersionInfo } from './schema.ts';\nimport { GoVersionTimestampCache } from './timestamp-cache.ts';\n\n/** TODO #42566 */\nconst goVersionRegex = regEx(/^\\s*go\\s+(?<version>[^\\s]+)\\s*$/);\n\nconst modRegex = regEx(/^(?<baseMod>.*?)(?:[./]v(?<majorVersion>\\d+))?$/);\n\nconst versionTagRegex = regEx(/^v\\d/);\n\n/**\n * Modules with a major version of v2 or above which have no `go.mod` are reported by a Go proxy with a `+incompatible` suffix, which is absent from the tag they were published as.\n *\n * @see https://go.dev/ref/mod#non-module-compat\n */\nconst incompatibleSuffixRegex = regEx(/\\+incompatible$/);\n\n/**\n * @see https://go.dev/ref/mod#pseudo-versions\n */\nconst pseudoVersionRegex = regEx(\n /v\\d+\\.\\d+\\.\\d+-(?:\\w+\\.)?(?:0\\.)?(?<timestamp>\\d{14})-(?<digest>[a-f0-9]{12})/i,\n);\n\nexport function pseudoVersionToRelease(pseudoVersion: string): Release | null {\n const match = pseudoVersion.match(pseudoVersionRegex)?.groups;\n if (!match) {\n return null;\n }\n\n const { digest: newDigest, timestamp } = match;\n const releaseTimestamp = asTimestamp(timestamp);\n\n return {\n version: pseudoVersion,\n newDigest,\n releaseTimestamp,\n };\n}\n\n/**\n * A Go module which lives in a subdirectory of its repository is tagged with that subdirectory as a prefix, so `github.com/aws/aws-sdk-go-v2/service/s3` publishes `v1.2.3` as the tag `service/s3/v1.2.3`.\n *\n * @see https://go.dev/ref/mod#vcs-version\n *\n * Because we can't tell from the module path alone where the repository ends and the subdirectory begins, we try each candidate prefix - longest first - against the tags we actually found, in the same way as `filterByPrefix` does for direct lookups.\n */\nexport function getTagPrefix(goModule: string, tags: Iterable<string>): string {\n const nameParts = goModule\n .replace(regEx(/\\/v\\d+$/), '')\n .split('/')\n .slice(1);\n const tagNames = [...tags];\n\n while (nameParts.length) {\n const prefix = `${nameParts.join('/')}/`;\n\n const isUsed = tagNames.some(\n (tag) =>\n tag.startsWith(prefix) &&\n versionTagRegex.test(tag.slice(prefix.length)),\n );\n if (isUsed) {\n return prefix;\n }\n\n nameParts.shift();\n }\n\n return '';\n}\n\nexport class GoProxyDatasource extends Datasource {\n static readonly id = 'go-proxy';\n\n constructor() {\n super(GoProxyDatasource.id);\n }\n\n readonly direct = new GoDirectDatasource();\n\n private readonly githubHttp = new GithubHttp(GithubReleasesDatasource.id);\n\n private async _getReleases(\n config: GetReleasesConfig,\n ): Promise<ReleaseResult | null> {\n const { packageName } = config;\n logger.trace(`goproxy.getReleases(${packageName})`);\n const goproxy = getEnv().GOPROXY ?? `${publicGoproxyUrl},direct`;\n if (goproxy === 'direct') {\n return this.direct.getReleases(config);\n }\n const proxyList = parseGoproxy(goproxy);\n const noproxy = parseNoproxy();\n\n let result: ReleaseResult | null = null;\n let servedByProxy = false;\n\n if (noproxy?.test(packageName)) {\n logger.debug(`Fetching ${packageName} via GONOPROXY match`);\n result = await this.direct.getReleases(config);\n return result;\n }\n\n for (const { url, fallback } of proxyList) {\n try {\n if (url === 'off') {\n break;\n } else if (url === 'direct') {\n result = await this.direct.getReleases(config);\n break;\n }\n\n const res = await this.getVersionsWithInfo(\n url,\n packageName,\n config.constraintsFiltering,\n );\n if (res.releases.length) {\n result = res;\n servedByProxy = true;\n break;\n }\n } catch (err) {\n const potentialHttpError =\n err instanceof ExternalHostError ? err.err : err;\n const statusCode = potentialHttpError?.response?.statusCode;\n const canFallback =\n fallback === '|' ? true : statusCode === 404 || statusCode === 410;\n if (!canFallback) {\n logger.debug(\n { err },\n 'Goproxy error: not falling back to other URLs provided with GOPROXY, rethrowing',\n );\n this.handleGenericErrors(err);\n }\n logger.debug(\n { err },\n 'Goproxy error: trying next URL provided with GOPROXY',\n );\n }\n }\n\n if (result && !result.sourceUrl) {\n try {\n const datasource = await BaseGoDatasource.getDatasource(packageName);\n const sourceUrl = getSourceUrl(datasource);\n if (sourceUrl) {\n result.sourceUrl = sourceUrl;\n }\n } catch (err) {\n logger.trace({ err }, `Can't get datasource for ${packageName}`);\n }\n }\n\n if (result?.sourceUrl && servedByProxy) {\n await this.addGithubTimestamps(\n packageName,\n result.sourceUrl,\n result.releases,\n );\n }\n\n return result;\n }\n\n /**\n * A Go proxy reports the commit time of the tagged commit as a version's `Time`, which can be much earlier than the point at which that version was released.\n *\n * When the module is hosted on GitHub, a GitHub Release's publication time, or - if there's no Release - the git tag's own creation time (distinct from the commit time for an annotated tag), is a better indicator of when the version became available. A Release is preferred over a tag when both exist for the same version.\n */\n async addGithubTimestamps(\n packageName: string,\n sourceUrl: string,\n releases: Release[],\n ): Promise<void> {\n if (detectPlatform(sourceUrl) !== 'github') {\n return;\n }\n\n const parsedUrl = parseUrl(sourceUrl);\n /* v8 ignore next -- detectPlatform only returns a platform for parseable URLs */\n if (!parsedUrl) {\n return;\n }\n\n const repository = trimTrailingSlash(\n trimLeadingSlash(parsedUrl.pathname),\n ).replace(regEx(/\\.git$/), '');\n const githubConfig = {\n packageName: repository,\n registryUrl: parsedUrl.origin,\n };\n\n const [githubTags, githubReleases] = await Promise.all([\n queryTags(githubConfig, this.githubHttp).catch((err) => {\n logger.debug(\n { err, packageName },\n 'Error fetching GitHub Tags for Go module',\n );\n return [];\n }),\n queryReleases(githubConfig, this.githubHttp).catch((err) => {\n logger.debug(\n { err, packageName },\n 'Error fetching GitHub Releases for Go module',\n );\n return [];\n }),\n ]);\n\n const timestamps = new Map<string, Timestamp>();\n for (const { version, releaseTimestamp } of githubTags) {\n timestamps.set(version, releaseTimestamp);\n }\n for (const { version, releaseTimestamp } of githubReleases) {\n timestamps.set(version, releaseTimestamp);\n }\n\n const tagPrefix = getTagPrefix(packageName, timestamps.keys());\n for (const release of releases) {\n const version = release.version.replace(incompatibleSuffixRegex, '');\n const releaseTimestamp = timestamps.get(`${tagPrefix}${version}`);\n if (\n releaseTimestamp &&\n (!release.releaseTimestamp ||\n releaseTimestamp > release.releaseTimestamp)\n ) {\n release.releaseTimestamp = releaseTimestamp;\n }\n }\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${GoProxyDatasource.id}`,\n key: GoProxyDatasource.getCacheKey(config),\n cacheable: isPublicGoPackage(config.packageName),\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n /**\n * Avoid ambiguity when serving from case-insensitive file systems.\n *\n * @see https://golang.org/ref/mod#goproxy-protocol\n */\n encodeCase(input: string): string {\n return input.replace(regEx(/(?:[A-Z])/g), (x) => `!${x.toLowerCase()}`);\n }\n\n async listVersions(baseUrl: string, packageName: string): Promise<Release[]> {\n const url = joinUrlParts(\n baseUrl,\n this.encodeCase(packageName),\n '@v',\n 'list',\n );\n const { body } = await this.http.getText(url);\n return filterMap(body.split(newlineRegex), (str) => {\n if (!isNonEmptyStringAndNotWhitespace(str)) {\n return null;\n }\n\n const [version, timestamp] = str.trim().split(regEx(/\\s+/));\n const release: Release = pseudoVersionToRelease(version) ?? { version };\n\n const releaseTimestamp = asTimestamp(timestamp);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n\n return release;\n });\n }\n\n async versionInfo(\n baseUrl: string,\n packageName: string,\n version: string,\n ): Promise<Release> {\n const url = joinUrlParts(\n baseUrl,\n this.encodeCase(packageName),\n '@v',\n `${version}.info`,\n );\n const res = await this.http.getJson(url, VersionInfo);\n\n const result: Release = {\n version: res.body.Version,\n };\n\n const releaseTimestamp = asTimestamp(res.body.Time);\n if (releaseTimestamp) {\n result.releaseTimestamp = releaseTimestamp;\n }\n\n return result;\n }\n\n /**\n * Retrieve the `go` directive for a given Go Module.\n *\n * NOTE that this means the `go` directive, not the `toolchain` directive.\n */\n async retrieveGoDirectiveForModule(\n baseUrl: string,\n packageName: string,\n version: string,\n ): Promise<string | undefined> {\n return withCache(\n {\n namespace: `datasource-${GoProxyDatasource.id}`,\n key: GoProxyDatasource.getVersionedCacheKey(packageName, version),\n // a module's `go.mod` should /never/ change after it's published. If going via the Go Proxy and the Go Checksum Database, a change in this value will result in build failures.\n ttlMinutes: 100 * 24 * 60,\n cacheable: isPublicGoPackage(packageName),\n },\n () => this._retrieveGoDirectiveForModule(baseUrl, packageName, version),\n );\n }\n\n async _retrieveGoDirectiveForModule(\n baseUrl: string,\n packageName: string,\n version: string,\n ): Promise<string | undefined> {\n const url = joinUrlParts(\n baseUrl,\n this.encodeCase(packageName),\n '@v',\n `${version}.mod`,\n );\n const res = await this.http.getText(url);\n\n let goDirective: string | undefined = undefined;\n\n for (const line of res.body.split('\\n')) {\n const goVersionMatches = goVersionRegex.exec(line)?.groups;\n if (goVersionMatches) {\n goDirective = goVersionMatches.version;\n break;\n }\n }\n\n if (!goDirective) {\n return goDirective;\n }\n\n // always return it in full SemVer format, which can then be matched on using `semver` or `semver-coerced`\n const parts = goDirective.split('.');\n if (parts.length === 1) {\n return `${parts[0]}.0.0`;\n }\n if (parts.length === 2) {\n return `${parts[0]}.${parts[1]}.0`;\n }\n return `${parts[0]}.${parts[1]}.${parts[2]}`;\n }\n\n async getLatestVersion(\n baseUrl: string,\n packageName: string,\n ): Promise<{ version: string; sourceUrl?: string } | null> {\n try {\n const url = joinUrlParts(\n baseUrl,\n this.encodeCase(packageName),\n '@latest',\n );\n const res = await this.http.getJson(url, VersionInfo);\n const { Version: version, Origin: origin } = res.body;\n // Extract sourceUrl from GOPROXY Origin when present, avoiding go-get to\n // vanity hosts (https://github.com/renovatebot/renovate/discussions/44898)\n const sourceUrl =\n origin?.VCS === 'git' && isNonEmptyString(origin.URL)\n ? origin.URL.replace(regEx(/\\.git$/), '')\n : undefined;\n return { version, sourceUrl };\n } catch (err) {\n logger.trace({ err }, 'Failed to get latest version');\n return null;\n }\n }\n\n async getVersionsWithInfo(\n baseUrl: string,\n packageName: string,\n constraintsFiltering: ConstraintsFilter | undefined,\n ): Promise<ReleaseResult> {\n const isGopkgin = packageName.startsWith('gopkg.in/');\n const majorSuffixSeparator = isGopkgin ? '.' : '/';\n const modParts = packageName.match(modRegex)?.groups;\n /* v8 ignore start: defensive - modRegex matches any non-empty package name, so baseMod is always set */\n const baseMod = modParts?.baseMod ?? packageName;\n /* v8 ignore stop */\n const packageMajor = parseInt(modParts?.majorVersion ?? '0', 10);\n\n const result: ReleaseResult = { releases: [] };\n for (let major = packageMajor; ; major += 1) {\n let pkg = `${baseMod}${majorSuffixSeparator}v${major}`;\n if (!isGopkgin && major < 2) {\n pkg = baseMod;\n major += 1; // v0 and v1 are the same module\n }\n\n let releases: Release[] = [];\n\n try {\n const res = await this.listVersions(baseUrl, pkg);\n\n // Artifactory returns all versions in any major (past and future),\n // so starting from v2, we filter them in order to avoid the infinite loop\n const filteredReleases = res.filter(({ version }) => {\n if (major < 2) {\n return true;\n }\n\n return (\n version.split(regEx(/[^\\d]+/)).find(isTruthy) === major.toString()\n );\n });\n\n const timestamps = await GoVersionTimestampCache.init(baseUrl, pkg);\n\n releases = await p.map(filteredReleases, async (versionInfo) => {\n const { version, newDigest, releaseTimestamp } = versionInfo;\n\n if (releaseTimestamp) {\n return { version, newDigest, releaseTimestamp };\n }\n\n const cachedTimestamp = timestamps.get(version);\n if (cachedTimestamp) {\n return { version, releaseTimestamp: cachedTimestamp };\n }\n\n try {\n const release = await this.versionInfo(baseUrl, pkg, version);\n if (release.releaseTimestamp) {\n timestamps.set(version, release.releaseTimestamp);\n }\n return release;\n } catch (err) {\n logger.trace({ err }, `Can't obtain data from ${baseUrl}`);\n return { version };\n }\n });\n\n await timestamps.save();\n\n if (constraintsFiltering === 'strict') {\n releases = await p.map(releases, async (rel) => {\n try {\n const goDirective = await this.retrieveGoDirectiveForModule(\n baseUrl,\n pkg,\n rel.version,\n );\n if (goDirective) {\n rel.constraints ??= {};\n rel.constraints['%goMod'] ??= [];\n rel.constraints['%goMod'].push(goDirective);\n }\n } catch (err) {\n logger.trace(\n { err },\n `Can't obtain \\`go\\` directive from ${baseUrl}`,\n );\n }\n\n return rel;\n });\n }\n\n result.releases.push(...releases);\n } catch (err) {\n const potentialHttpError =\n err instanceof ExternalHostError ? err.err : err;\n const status = potentialHttpError.response?.statusCode;\n if (\n potentialHttpError instanceof HttpError &&\n (status === 404 || status === 403) &&\n major !== packageMajor\n ) {\n break;\n }\n\n throw err;\n }\n\n const latest = await this.getLatestVersion(baseUrl, pkg);\n if (latest) {\n const { version: latestVersion, sourceUrl } = latest;\n result.tags ??= {};\n result.tags.latest ??= latestVersion;\n if (goVersioning.isGreaterThan(latestVersion, result.tags.latest)) {\n result.tags.latest = latestVersion;\n }\n if (sourceUrl) {\n result.sourceUrl ??= sourceUrl;\n }\n if (!result.releases.length) {\n const releaseFromLatest = pseudoVersionToRelease(latestVersion);\n // v8 ignore else -- needs an empty version list plus a non-pseudo latest\n if (releaseFromLatest) {\n result.releases.push(releaseFromLatest);\n }\n }\n }\n\n if (!releases.length) {\n break;\n }\n }\n\n return result;\n }\n\n static getCacheKey({\n packageName,\n constraintsFiltering,\n }: GetReleasesConfig): string {\n const goproxy = getEnv().GOPROXY;\n const noproxy = parseNoproxy();\n const constraintsFilteringKey =\n constraintsFiltering === 'none' ? '' : constraintsFiltering;\n return buildCacheKey(\n 'getReleases',\n packageName,\n goproxy,\n noproxy?.toString(),\n constraintsFilteringKey,\n );\n }\n\n static getVersionedCacheKey(packageName: string, version: string): string {\n const goproxy = getEnv().GOPROXY;\n const noproxy = parseNoproxy();\n return buildCacheKey(\n 'goDirective',\n packageName,\n version,\n goproxy,\n noproxy?.toString(),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,MAAM,iBAAiB,MAAM,iCAAiC;AAE9D,MAAM,WAAW,MAAM,iDAAiD;AAExE,MAAM,kBAAkB,MAAM,MAAM;;;;;;AAOpC,MAAM,0BAA0B,MAAM,iBAAiB;;;;AAKvD,MAAM,qBAAqB,MACzB,gFACF;AAEA,SAAgB,uBAAuB,eAAuC;CAC5E,MAAM,QAAQ,cAAc,MAAM,kBAAkB,CAAC,EAAE;CACvD,IAAI,CAAC,OACH,OAAO;CAGT,MAAM,EAAE,QAAQ,WAAW,cAAc;CAGzC,OAAO;EACL,SAAS;EACT;EACA,kBALuB,YAAY,SAKpB;CACjB;AACF;;;;;;;;AASA,SAAgB,aAAa,UAAkB,MAAgC;CAC7E,MAAM,YAAY,SACf,QAAQ,MAAM,SAAS,GAAG,EAAE,CAAC,CAC7B,MAAM,GAAG,CAAC,CACV,MAAM,CAAC;CACV,MAAM,WAAW,CAAC,GAAG,IAAI;CAEzB,OAAO,UAAU,QAAQ;EACvB,MAAM,SAAS,GAAG,UAAU,KAAK,GAAG,EAAE;EAOtC,IALe,SAAS,MACrB,QACC,IAAI,WAAW,MAAM,KACrB,gBAAgB,KAAK,IAAI,MAAM,OAAO,MAAM,CAAC,CAExC,GACP,OAAO;EAGT,UAAU,MAAM;CAClB;CAEA,OAAO;AACT;AAEA,IAAa,oBAAb,MAAa,0BAA0B,WAAW;CAChD,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,kBAAkB,EAAE;CAC5B;CAEA,SAAkB,IAAI,mBAAmB;CAEzC,aAA8B,IAAI,WAAW,yBAAyB,EAAE;CAExE,MAAc,aACZ,QAC+B;EAC/B,MAAM,EAAE,gBAAgB;EACxB,OAAO,MAAM,uBAAuB,YAAY,EAAE;EAClD,MAAM,UAAU,OAAO,CAAC,CAAC,WAAW;EACpC,IAAI,YAAY,UACd,OAAO,KAAK,OAAO,YAAY,MAAM;EAEvC,MAAM,YAAY,aAAa,OAAO;EACtC,MAAM,UAAU,aAAa;EAE7B,IAAI,SAA+B;EACnC,IAAI,gBAAgB;EAEpB,IAAI,SAAS,KAAK,WAAW,GAAG;GAC9B,OAAO,MAAM,YAAY,YAAY,qBAAqB;GAC1D,SAAS,MAAM,KAAK,OAAO,YAAY,MAAM;GAC7C,OAAO;EACT;EAEA,KAAK,MAAM,EAAE,KAAK,cAAc,WAC9B,IAAI;GACF,IAAI,QAAQ,OACV;QACK,IAAI,QAAQ,UAAU;IAC3B,SAAS,MAAM,KAAK,OAAO,YAAY,MAAM;IAC7C;GACF;GAEA,MAAM,MAAM,MAAM,KAAK,oBACrB,KACA,aACA,OAAO,oBACT;GACA,IAAI,IAAI,SAAS,QAAQ;IACvB,SAAS;IACT,gBAAgB;IAChB;GACF;EACF,SAAS,KAAK;GAGZ,MAAM,cADJ,eAAe,oBAAoB,IAAI,MAAM,IAAA,EACR,UAAU;GAGjD,IAAI,EADF,aAAa,MAAM,OAAO,eAAe,OAAO,eAAe,MAC/C;IAChB,OAAO,MACL,EAAE,IAAI,GACN,iFACF;IACA,KAAK,oBAAoB,GAAG;GAC9B;GACA,OAAO,MACL,EAAE,IAAI,GACN,sDACF;EACF;EAGF,IAAI,UAAU,CAAC,OAAO,WACpB,IAAI;GACF,MAAM,aAAa,MAAM,iBAAiB,cAAc,WAAW;GACnE,MAAM,YAAY,aAAa,UAAU;GACzC,IAAI,WACF,OAAO,YAAY;EAEvB,SAAS,KAAK;GACZ,OAAO,MAAM,EAAE,IAAI,GAAG,4BAA4B,aAAa;EACjE;EAGF,IAAI,QAAQ,aAAa,eACvB,MAAM,KAAK,oBACT,aACA,OAAO,WACP,OAAO,QACT;EAGF,OAAO;CACT;;;;;;CAOA,MAAM,oBACJ,aACA,WACA,UACe;EACf,IAAI,eAAe,SAAS,MAAM,UAChC;EAGF,MAAM,YAAY,SAAS,SAAS;;EAEpC,IAAI,CAAC,WACH;EAMF,MAAM,eAAe;GACnB,aAJiB,kBACjB,iBAAiB,UAAU,QAAQ,CACrC,CAAC,CAAC,QAAQ,MAAM,QAAQ,GAAG,EAEH;GACtB,aAAa,UAAU;EACzB;EAEA,MAAM,CAAC,YAAY,kBAAkB,MAAM,QAAQ,IAAI,CACrD,UAAU,cAAc,KAAK,UAAU,CAAC,CAAC,OAAO,QAAQ;GACtD,OAAO,MACL;IAAE;IAAK;GAAY,GACnB,0CACF;GACA,OAAO,CAAC;EACV,CAAC,GACD,cAAc,cAAc,KAAK,UAAU,CAAC,CAAC,OAAO,QAAQ;GAC1D,OAAO,MACL;IAAE;IAAK;GAAY,GACnB,8CACF;GACA,OAAO,CAAC;EACV,CAAC,CACH,CAAC;EAED,MAAM,6BAAa,IAAI,IAAuB;EAC9C,KAAK,MAAM,EAAE,SAAS,sBAAsB,YAC1C,WAAW,IAAI,SAAS,gBAAgB;EAE1C,KAAK,MAAM,EAAE,SAAS,sBAAsB,gBAC1C,WAAW,IAAI,SAAS,gBAAgB;EAG1C,MAAM,YAAY,aAAa,aAAa,WAAW,KAAK,CAAC;EAC7D,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,UAAU,QAAQ,QAAQ,QAAQ,yBAAyB,EAAE;GACnE,MAAM,mBAAmB,WAAW,IAAI,GAAG,YAAY,SAAS;GAChE,IACE,qBACC,CAAC,QAAQ,oBACR,mBAAmB,QAAQ,mBAE7B,QAAQ,mBAAmB;EAE/B;CACF;CAEA,YAAY,QAA0D;EACpE,OAAO,UACL;GACE,WAAW,cAAc,kBAAkB;GAC3C,KAAK,kBAAkB,YAAY,MAAM;GACzC,WAAW,kBAAkB,OAAO,WAAW;GAC/C,UAAU;EACZ,SACM,KAAK,aAAa,MAAM,CAChC;CACF;;;;;;CAOA,WAAW,OAAuB;EAChC,OAAO,MAAM,QAAQ,MAAM,YAAY,IAAI,MAAM,IAAI,EAAE,YAAY,GAAG;CACxE;CAEA,MAAM,aAAa,SAAiB,aAAyC;EAC3E,MAAM,MAAM,aACV,SACA,KAAK,WAAW,WAAW,GAC3B,MACA,MACF;EACA,MAAM,EAAE,SAAS,MAAM,KAAK,KAAK,QAAQ,GAAG;EAC5C,OAAO,UAAU,KAAK,MAAM,YAAY,IAAI,QAAQ;GAClD,IAAI,CAAC,iCAAiC,GAAG,GACvC,OAAO;GAGT,MAAM,CAAC,SAAS,aAAa,IAAI,KAAK,CAAC,CAAC,MAAM,MAAM,KAAK,CAAC;GAC1D,MAAM,UAAmB,uBAAuB,OAAO,KAAK,EAAE,QAAQ;GAEtE,MAAM,mBAAmB,YAAY,SAAS;GAC9C,IAAI,kBACF,QAAQ,mBAAmB;GAG7B,OAAO;EACT,CAAC;CACH;CAEA,MAAM,YACJ,SACA,aACA,SACkB;EAClB,MAAM,MAAM,aACV,SACA,KAAK,WAAW,WAAW,GAC3B,MACA,GAAG,QAAQ,MACb;EACA,MAAM,MAAM,MAAM,KAAK,KAAK,QAAQ,KAAK,WAAW;EAEpD,MAAM,SAAkB,EACtB,SAAS,IAAI,KAAK,QACpB;EAEA,MAAM,mBAAmB,YAAY,IAAI,KAAK,IAAI;EAClD,IAAI,kBACF,OAAO,mBAAmB;EAG5B,OAAO;CACT;;;;;;CAOA,MAAM,6BACJ,SACA,aACA,SAC6B;EAC7B,OAAO,UACL;GACE,WAAW,cAAc,kBAAkB;GAC3C,KAAK,kBAAkB,qBAAqB,aAAa,OAAO;GAEhE,YAAY;GACZ,WAAW,kBAAkB,WAAW;EAC1C,SACM,KAAK,8BAA8B,SAAS,aAAa,OAAO,CACxE;CACF;CAEA,MAAM,8BACJ,SACA,aACA,SAC6B;EAC7B,MAAM,MAAM,aACV,SACA,KAAK,WAAW,WAAW,GAC3B,MACA,GAAG,QAAQ,KACb;EACA,MAAM,MAAM,MAAM,KAAK,KAAK,QAAQ,GAAG;EAEvC,IAAI,cAAkC,KAAA;EAEtC,KAAK,MAAM,QAAQ,IAAI,KAAK,MAAM,IAAI,GAAG;GACvC,MAAM,mBAAmB,eAAe,KAAK,IAAI,CAAC,EAAE;GACpD,IAAI,kBAAkB;IACpB,cAAc,iBAAiB;IAC/B;GACF;EACF;EAEA,IAAI,CAAC,aACH,OAAO;EAIT,MAAM,QAAQ,YAAY,MAAM,GAAG;EACnC,IAAI,MAAM,WAAW,GACnB,OAAO,GAAG,MAAM,GAAG;EAErB,IAAI,MAAM,WAAW,GACnB,OAAO,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG;EAEjC,OAAO,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM;CAC1C;CAEA,MAAM,iBACJ,SACA,aACyD;EACzD,IAAI;GACF,MAAM,MAAM,aACV,SACA,KAAK,WAAW,WAAW,GAC3B,SACF;GAEA,MAAM,EAAE,SAAS,SAAS,QAAQ,YAAW,MAD3B,KAAK,KAAK,QAAQ,KAAK,WAAW,EAAA,CACH;GAOjD,OAAO;IAAE;IAAS,WAHhB,QAAQ,QAAQ,SAAS,iBAAiB,OAAO,GAAG,IAChD,OAAO,IAAI,QAAQ,MAAM,QAAQ,GAAG,EAAE,IACtC,KAAA;GACsB;EAC9B,SAAS,KAAK;GACZ,OAAO,MAAM,EAAE,IAAI,GAAG,8BAA8B;GACpD,OAAO;EACT;CACF;CAEA,MAAM,oBACJ,SACA,aACA,sBACwB;EACxB,MAAM,YAAY,YAAY,WAAW,WAAW;EACpD,MAAM,uBAAuB,YAAY,MAAM;EAC/C,MAAM,WAAW,YAAY,MAAM,QAAQ,CAAC,EAAE;;EAE9C,MAAM,UAAU,UAAU,WAAW;;EAErC,MAAM,eAAe,SAAS,UAAU,gBAAgB,KAAK,EAAE;EAE/D,MAAM,SAAwB,EAAE,UAAU,CAAC,EAAE;EAC7C,KAAK,IAAI,QAAQ,eAAgB,SAAS,GAAG;GAC3C,IAAI,MAAM,GAAG,UAAU,qBAAqB,GAAG;GAC/C,IAAI,CAAC,aAAa,QAAQ,GAAG;IAC3B,MAAM;IACN,SAAS;GACX;GAEA,IAAI,WAAsB,CAAC;GAE3B,IAAI;IAKF,MAAM,oBAAmB,MAJP,KAAK,aAAa,SAAS,GAAG,EAAA,CAInB,QAAQ,EAAE,cAAc;KACnD,IAAI,QAAQ,GACV,OAAO;KAGT,OACE,QAAQ,MAAM,MAAM,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,MAAM,MAAM,SAAS;IAErE,CAAC;IAED,MAAM,aAAa,MAAM,wBAAwB,KAAK,SAAS,GAAG;IAElE,WAAW,MAAMA,IAAM,kBAAkB,OAAO,gBAAgB;KAC9D,MAAM,EAAE,SAAS,WAAW,qBAAqB;KAEjD,IAAI,kBACF,OAAO;MAAE;MAAS;MAAW;KAAiB;KAGhD,MAAM,kBAAkB,WAAW,IAAI,OAAO;KAC9C,IAAI,iBACF,OAAO;MAAE;MAAS,kBAAkB;KAAgB;KAGtD,IAAI;MACF,MAAM,UAAU,MAAM,KAAK,YAAY,SAAS,KAAK,OAAO;MAC5D,IAAI,QAAQ,kBACV,WAAW,IAAI,SAAS,QAAQ,gBAAgB;MAElD,OAAO;KACT,SAAS,KAAK;MACZ,OAAO,MAAM,EAAE,IAAI,GAAG,0BAA0B,SAAS;MACzD,OAAO,EAAE,QAAQ;KACnB;IACF,CAAC;IAED,MAAM,WAAW,KAAK;IAEtB,IAAI,yBAAyB,UAC3B,WAAW,MAAMA,IAAM,UAAU,OAAO,QAAQ;KAC9C,IAAI;MACF,MAAM,cAAc,MAAM,KAAK,6BAC7B,SACA,KACA,IAAI,OACN;MACA,IAAI,aAAa;OACf,IAAI,gBAAgB,CAAC;OACrB,IAAI,YAAY,cAAc,CAAC;OAC/B,IAAI,YAAY,SAAS,CAAC,KAAK,WAAW;MAC5C;KACF,SAAS,KAAK;MACZ,OAAO,MACL,EAAE,IAAI,GACN,sCAAsC,SACxC;KACF;KAEA,OAAO;IACT,CAAC;IAGH,OAAO,SAAS,KAAK,GAAG,QAAQ;GAClC,SAAS,KAAK;IACZ,MAAM,qBACJ,eAAe,oBAAoB,IAAI,MAAM;IAC/C,MAAM,SAAS,mBAAmB,UAAU;IAC5C,IACE,8BAA8BC,iBAC7B,WAAW,OAAO,WAAW,QAC9B,UAAU,cAEV;IAGF,MAAM;GACR;GAEA,MAAM,SAAS,MAAM,KAAK,iBAAiB,SAAS,GAAG;GACvD,IAAI,QAAQ;IACV,MAAM,EAAE,SAAS,eAAe,cAAc;IAC9C,OAAO,SAAS,CAAC;IACjB,OAAO,KAAK,WAAW;IACvB,IAAIC,IAAa,cAAc,eAAe,OAAO,KAAK,MAAM,GAC9D,OAAO,KAAK,SAAS;IAEvB,IAAI,WACF,OAAO,cAAc;IAEvB,IAAI,CAAC,OAAO,SAAS,QAAQ;KAC3B,MAAM,oBAAoB,uBAAuB,aAAa;;KAE9D,IAAI,mBACF,OAAO,SAAS,KAAK,iBAAiB;IAE1C;GACF;GAEA,IAAI,CAAC,SAAS,QACZ;EAEJ;EAEA,OAAO;CACT;CAEA,OAAO,YAAY,EACjB,aACA,wBAC4B;EAC5B,MAAM,UAAU,OAAO,CAAC,CAAC;EACzB,MAAM,UAAU,aAAa;EAC7B,MAAM,0BACJ,yBAAyB,SAAS,KAAK;EACzC,OAAO,cACL,eACA,aACA,SACA,SAAS,SAAS,GAClB,uBACF;CACF;CAEA,OAAO,qBAAqB,aAAqB,SAAyB;EACxE,MAAM,UAAU,OAAO,CAAC,CAAC;EACzB,MAAM,UAAU,aAAa;EAC7B,OAAO,cACL,eACA,aACA,SACA,SACA,SAAS,SAAS,CACpB;CACF;AACF"}
@@ -1,5 +1,6 @@
1
1
  import { GlobalConfig } from "../../../config/global.js";
2
2
  import { parseUrl, trimTrailingSlash } from "../../../util/url.js";
3
+ import { buildCacheKey } from "../../../util/cache/package/key.js";
3
4
  import { acquireLock } from "../../../util/mutex.js";
4
5
  import { get, set } from "../../../util/cache/package/index.js";
5
6
  import { isPublicGoPackage } from "./common.js";
@@ -59,7 +60,8 @@ function getCacheKey(baseUrl, packageName) {
59
60
  if (!GlobalConfig.get("cachePrivatePackages") && !isPublicGoPackage(packageName)) return null;
60
61
  const parsedUrl = parseUrl(baseUrl);
61
62
  if (!parsedUrl) return null;
62
- return `${`${parsedUrl.origin}${trimTrailingSlash(parsedUrl.pathname)}`}@@${packageName}`;
63
+ const proxy = `${parsedUrl.origin}${trimTrailingSlash(parsedUrl.pathname)}`;
64
+ return buildCacheKey(proxy, packageName);
63
65
  }
64
66
  //#endregion
65
67
  export { GoVersionTimestampCache };
@@ -1 +1 @@
1
- {"version":3,"file":"timestamp-cache.js","names":["packageCache.set","packageCache.get"],"sources":["../../../../lib/modules/datasource/go/timestamp-cache.ts"],"sourcesContent":["import { GlobalConfig } from '../../../config/global.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { acquireLock } from '../../../util/mutex.ts';\nimport type { Timestamp } from '../../../util/timestamp.ts';\nimport { parseUrl, trimTrailingSlash } from '../../../util/url.ts';\nimport { isPublicGoPackage } from './common.ts';\nimport { VersionTimestamps } from './schema.ts';\n\nconst cacheNamespace = 'datasource-go-proxy-timestamps';\n\n// a module's `go.mod` should /never/ change after it's published. If going via the Go Proxy and the Go Checksum Database, a change in this value will result in build failures.\nconst ttlMinutes = 100 * 24 * 60;\n\n/**\n * The publication times we already know for a module, so that a run only fetches the `.info` file of a version it has never seen before.\n *\n * This is intentionally separate from the Go module's releases cache, as the current releases list changes (somewhat frequently), whereas the release timestamp for a given Go module shouldn't change after publication.\n */\nexport class GoVersionTimestampCache {\n private isChanged = false;\n private cacheKey: string | null;\n private timestamps: Record<string, Timestamp>;\n\n private constructor(\n cacheKey: string | null,\n timestamps: Record<string, Timestamp>,\n ) {\n this.cacheKey = cacheKey;\n this.timestamps = timestamps;\n }\n\n static async init(\n baseUrl: string,\n packageName: string,\n ): Promise<GoVersionTimestampCache> {\n const cacheKey = getCacheKey(baseUrl, packageName);\n if (!cacheKey) {\n return new GoVersionTimestampCache(null, {});\n }\n\n return new GoVersionTimestampCache(cacheKey, await read(cacheKey));\n }\n\n get(version: string): Timestamp | undefined {\n return this.timestamps[version];\n }\n\n set(version: string, timestamp: Timestamp): void {\n this.timestamps[version] = timestamp;\n this.isChanged = true;\n }\n\n async save(): Promise<void> {\n if (!this.cacheKey || !this.isChanged) {\n return;\n }\n\n // `foo` and `foo/v2` are separate lookups which both walk the `v2` module, so another one of them may have written its own timestamps while we were fetching ours. The lock only protects against concurrent writes within this process, not across separate Renovate processes/machines sharing the same cache backend.\n const releaseLock = await acquireLock(this.cacheKey, cacheNamespace);\n try {\n const current = await read(this.cacheKey);\n\n await packageCache.set(\n cacheNamespace,\n this.cacheKey,\n { ...current, ...this.timestamps },\n ttlMinutes,\n );\n } finally {\n releaseLock();\n }\n }\n}\n\nasync function read(cacheKey: string): Promise<Record<string, Timestamp>> {\n const cached = await packageCache.get<unknown>(cacheNamespace, cacheKey);\n return cached ? VersionTimestamps.parse(cached) : {};\n}\n\n/**\n * Timestamps are only shared between modules served by the same proxy, and only stored at all for modules we may cache.\n *\n * Any credentials in the proxy URL are left out, as the key is stored as-is by the cache backends.\n */\nfunction getCacheKey(baseUrl: string, packageName: string): string | null {\n const cachePrivatePackages = GlobalConfig.get('cachePrivatePackages');\n if (!cachePrivatePackages && !isPublicGoPackage(packageName)) {\n return null;\n }\n\n const parsedUrl = parseUrl(baseUrl);\n if (!parsedUrl) {\n return null;\n }\n\n const proxy = `${parsedUrl.origin}${trimTrailingSlash(parsedUrl.pathname)}`;\n return `${proxy}@@${packageName}`;\n}\n"],"mappings":";;;;;;;AAQA,MAAM,iBAAiB;AAGvB,MAAM,aAAa;;;;;;AAOnB,IAAa,0BAAb,MAAa,wBAAwB;CACnC,YAAoB;CACpB;CACA;CAEA,YACE,UACA,YACA;EACA,KAAK,WAAW;EAChB,KAAK,aAAa;CACpB;CAEA,aAAa,KACX,SACA,aACkC;EAClC,MAAM,WAAW,YAAY,SAAS,WAAW;EACjD,IAAI,CAAC,UACH,OAAO,IAAI,wBAAwB,MAAM,CAAC,CAAC;EAG7C,OAAO,IAAI,wBAAwB,UAAU,MAAM,KAAK,QAAQ,CAAC;CACnE;CAEA,IAAI,SAAwC;EAC1C,OAAO,KAAK,WAAW;CACzB;CAEA,IAAI,SAAiB,WAA4B;EAC/C,KAAK,WAAW,WAAW;EAC3B,KAAK,YAAY;CACnB;CAEA,MAAM,OAAsB;EAC1B,IAAI,CAAC,KAAK,YAAY,CAAC,KAAK,WAC1B;EAIF,MAAM,cAAc,MAAM,YAAY,KAAK,UAAU,cAAc;EACnE,IAAI;GACF,MAAM,UAAU,MAAM,KAAK,KAAK,QAAQ;GAExC,MAAMA,IACJ,gBACA,KAAK,UACL;IAAE,GAAG;IAAS,GAAG,KAAK;GAAW,GACjC,UACF;EACF,UAAU;GACR,YAAY;EACd;CACF;AACF;AAEA,eAAe,KAAK,UAAsD;CACxE,MAAM,SAAS,MAAMC,IAA0B,gBAAgB,QAAQ;CACvE,OAAO,SAAS,kBAAkB,MAAM,MAAM,IAAI,CAAC;AACrD;;;;;;AAOA,SAAS,YAAY,SAAiB,aAAoC;CAExE,IAAI,CADyB,aAAa,IAAI,sBACtB,KAAK,CAAC,kBAAkB,WAAW,GACzD,OAAO;CAGT,MAAM,YAAY,SAAS,OAAO;CAClC,IAAI,CAAC,WACH,OAAO;CAIT,OAAO,GAAG,GADO,UAAU,SAAS,kBAAkB,UAAU,QAAQ,IACxD,IAAI;AACtB"}
1
+ {"version":3,"file":"timestamp-cache.js","names":["packageCache.set","packageCache.get"],"sources":["../../../../lib/modules/datasource/go/timestamp-cache.ts"],"sourcesContent":["import { GlobalConfig } from '../../../config/global.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { buildCacheKey } from '../../../util/cache/package/key.ts';\nimport { acquireLock } from '../../../util/mutex.ts';\nimport type { Timestamp } from '../../../util/timestamp.ts';\nimport { parseUrl, trimTrailingSlash } from '../../../util/url.ts';\nimport { isPublicGoPackage } from './common.ts';\nimport { VersionTimestamps } from './schema.ts';\n\nconst cacheNamespace = 'datasource-go-proxy-timestamps';\n\n// a module's `go.mod` should /never/ change after it's published. If going via the Go Proxy and the Go Checksum Database, a change in this value will result in build failures.\nconst ttlMinutes = 100 * 24 * 60;\n\n/**\n * The publication times we already know for a module, so that a run only fetches the `.info` file of a version it has never seen before.\n *\n * This is intentionally separate from the Go module's releases cache, as the current releases list changes (somewhat frequently), whereas the release timestamp for a given Go module shouldn't change after publication.\n */\nexport class GoVersionTimestampCache {\n private isChanged = false;\n private cacheKey: string | null;\n private timestamps: Record<string, Timestamp>;\n\n private constructor(\n cacheKey: string | null,\n timestamps: Record<string, Timestamp>,\n ) {\n this.cacheKey = cacheKey;\n this.timestamps = timestamps;\n }\n\n static async init(\n baseUrl: string,\n packageName: string,\n ): Promise<GoVersionTimestampCache> {\n const cacheKey = getCacheKey(baseUrl, packageName);\n if (!cacheKey) {\n return new GoVersionTimestampCache(null, {});\n }\n\n return new GoVersionTimestampCache(cacheKey, await read(cacheKey));\n }\n\n get(version: string): Timestamp | undefined {\n return this.timestamps[version];\n }\n\n set(version: string, timestamp: Timestamp): void {\n this.timestamps[version] = timestamp;\n this.isChanged = true;\n }\n\n async save(): Promise<void> {\n if (!this.cacheKey || !this.isChanged) {\n return;\n }\n\n // `foo` and `foo/v2` are separate lookups which both walk the `v2` module, so another one of them may have written its own timestamps while we were fetching ours. The lock only protects against concurrent writes within this process, not across separate Renovate processes/machines sharing the same cache backend.\n const releaseLock = await acquireLock(this.cacheKey, cacheNamespace);\n try {\n const current = await read(this.cacheKey);\n\n await packageCache.set(\n cacheNamespace,\n this.cacheKey,\n { ...current, ...this.timestamps },\n ttlMinutes,\n );\n } finally {\n releaseLock();\n }\n }\n}\n\nasync function read(cacheKey: string): Promise<Record<string, Timestamp>> {\n const cached = await packageCache.get<unknown>(cacheNamespace, cacheKey);\n return cached ? VersionTimestamps.parse(cached) : {};\n}\n\n/**\n * Timestamps are only shared between modules served by the same proxy, and only stored at all for modules we may cache.\n *\n * Any credentials in the proxy URL are left out, as the key is stored as-is by the cache backends.\n */\nfunction getCacheKey(baseUrl: string, packageName: string): string | null {\n const cachePrivatePackages = GlobalConfig.get('cachePrivatePackages');\n if (!cachePrivatePackages && !isPublicGoPackage(packageName)) {\n return null;\n }\n\n const parsedUrl = parseUrl(baseUrl);\n if (!parsedUrl) {\n return null;\n }\n\n const proxy = `${parsedUrl.origin}${trimTrailingSlash(parsedUrl.pathname)}`;\n return buildCacheKey(proxy, packageName);\n}\n"],"mappings":";;;;;;;;AASA,MAAM,iBAAiB;AAGvB,MAAM,aAAa;;;;;;AAOnB,IAAa,0BAAb,MAAa,wBAAwB;CACnC,YAAoB;CACpB;CACA;CAEA,YACE,UACA,YACA;EACA,KAAK,WAAW;EAChB,KAAK,aAAa;CACpB;CAEA,aAAa,KACX,SACA,aACkC;EAClC,MAAM,WAAW,YAAY,SAAS,WAAW;EACjD,IAAI,CAAC,UACH,OAAO,IAAI,wBAAwB,MAAM,CAAC,CAAC;EAG7C,OAAO,IAAI,wBAAwB,UAAU,MAAM,KAAK,QAAQ,CAAC;CACnE;CAEA,IAAI,SAAwC;EAC1C,OAAO,KAAK,WAAW;CACzB;CAEA,IAAI,SAAiB,WAA4B;EAC/C,KAAK,WAAW,WAAW;EAC3B,KAAK,YAAY;CACnB;CAEA,MAAM,OAAsB;EAC1B,IAAI,CAAC,KAAK,YAAY,CAAC,KAAK,WAC1B;EAIF,MAAM,cAAc,MAAM,YAAY,KAAK,UAAU,cAAc;EACnE,IAAI;GACF,MAAM,UAAU,MAAM,KAAK,KAAK,QAAQ;GAExC,MAAMA,IACJ,gBACA,KAAK,UACL;IAAE,GAAG;IAAS,GAAG,KAAK;GAAW,GACjC,UACF;EACF,UAAU;GACR,YAAY;EACd;CACF;AACF;AAEA,eAAe,KAAK,UAAsD;CACxE,MAAM,SAAS,MAAMC,IAA0B,gBAAgB,QAAQ;CACvE,OAAO,SAAS,kBAAkB,MAAM,MAAM,IAAI,CAAC;AACrD;;;;;;AAOA,SAAS,YAAY,SAAiB,aAAoC;CAExE,IAAI,CADyB,aAAa,IAAI,sBACtB,KAAK,CAAC,kBAAkB,WAAW,GACzD,OAAO;CAGT,MAAM,YAAY,SAAS,OAAO;CAClC,IAAI,CAAC,WACH,OAAO;CAGT,MAAM,QAAQ,GAAG,UAAU,SAAS,kBAAkB,UAAU,QAAQ;CACxE,OAAO,cAAc,OAAO,WAAW;AACzC"}
@@ -74,7 +74,7 @@ var GolangVersionDatasource = class GolangVersionDatasource extends Datasource {
74
74
  }
75
75
  getReleases(config) {
76
76
  return this.cached({
77
- key: `${config.registryUrl}`,
77
+ key: config.registryUrl,
78
78
  fallback: true
79
79
  }, () => this.fetchReleases(config));
80
80
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["semverVersioningId"],"sources":["../../../../lib/modules/datasource/golang-version/index.ts"],"sourcesContent":["import { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { joinUrlParts } from '../../../util/url.ts';\nimport {\n isVersion,\n id as semverVersioningId,\n} from '../../versioning/semver/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\n\nconst lineTerminationRegex = regEx(`\\r?\\n`);\nconst releaseBeginningChar = '\\t{';\nconst releaseTerminationChar = '\\t},';\nconst releaseDateRegex = regEx(\n `Date\\\\{(?<year>\\\\d+),\\\\s+(?<month>\\\\d+),\\\\s+(?<day>\\\\d+)\\\\}`,\n);\nconst releaseVersionRegex = regEx(\n `Version\\\\{(?<versionMajor>\\\\d+),\\\\s+(?<versionMinor>\\\\d+),\\\\s+(?<patch>\\\\d+)\\\\}`,\n);\nconst releaseFutureRegex = regEx(`Future:\\\\s+true`);\n\nexport class GolangVersionDatasource extends Datasource {\n static readonly id = 'golang-version';\n\n constructor() {\n super(GolangVersionDatasource.id);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://raw.githubusercontent.com/golang/website'];\n }\n\n override supportsCustomRegistry(_packageName: string): boolean {\n return true;\n }\n\n override readonly defaultVersioning = semverVersioningId;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `Date` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'We use the URL: https://github.com/golang/go.';\n\n private async fetchReleases({\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore next -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const res: ReleaseResult = {\n homepage: 'https://go.dev/',\n sourceUrl: 'https://github.com/golang/go',\n releases: [],\n };\n\n const golangVersionsUrl = joinUrlParts(\n registryUrl,\n '/HEAD/internal/history/release.go',\n );\n\n const response = await this.http.getText(golangVersionsUrl);\n\n const lines = response.body.split(lineTerminationRegex);\n\n const startOfReleases = lines.indexOf('var Releases = []*Release{');\n if (startOfReleases === -1) {\n throw new ExternalHostError(\n new Error('Invalid file - could not find the Releases section'),\n );\n }\n\n // Remove part before releases\n lines.splice(0, startOfReleases + 1);\n\n // Parse the release list\n let release: Omit<Release, 'version'> & { version?: string | undefined } = {\n version: undefined,\n };\n let skipFutureRelease = false;\n while (lines.length !== 0) {\n const line = lines.shift()!;\n if (line === releaseBeginningChar) {\n if (release.version !== undefined) {\n throw new ExternalHostError(\n new Error(\n 'Invalid file - unexpected error while parsing a release',\n ),\n );\n }\n } else if (line === releaseTerminationChar) {\n if (skipFutureRelease) {\n skipFutureRelease = false;\n } else {\n if (release.version === undefined) {\n throw new ExternalHostError(\n new Error('Invalid file - release has empty version'),\n );\n }\n res.releases.push(release as Release);\n }\n release = { version: undefined };\n } else {\n const isFutureRelease = releaseFutureRegex.test(line);\n if (isFutureRelease) {\n skipFutureRelease = true;\n }\n const releaseDateMatch = releaseDateRegex.exec(line);\n if (releaseDateMatch?.groups) {\n // Make a valid UTC timestamp\n const year = releaseDateMatch.groups.year.padStart(4, '0');\n const month = releaseDateMatch.groups.month.padStart(2, '0');\n const day = releaseDateMatch.groups.day.padStart(2, '0');\n release.releaseTimestamp = asTimestamp(\n `${year}-${month}-${day}T00:00:00.000Z`,\n );\n }\n const releaseVersionMatch = releaseVersionRegex.exec(line);\n if (releaseVersionMatch?.groups) {\n release.version = `${releaseVersionMatch.groups.versionMajor}.${releaseVersionMatch.groups.versionMinor}.${releaseVersionMatch.groups.patch}`;\n if (!isVersion(release.version)) {\n throw new ExternalHostError(\n new Error(`Version ${release.version} is not a valid semver`),\n );\n }\n }\n }\n }\n\n if (res.releases.length === 0) {\n throw new ExternalHostError(\n new Error(`Invalid file - zero releases extracted`),\n );\n }\n\n return res;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return this.cached(\n {\n key: `${config.registryUrl}`,\n fallback: true,\n },\n () => this.fetchReleases(config),\n );\n }\n}\n"],"mappings":";;;;;;;AAWA,MAAM,uBAAuB,MAAM,OAAO;AAC1C,MAAM,uBAAuB;AAC7B,MAAM,yBAAyB;AAC/B,MAAM,mBAAmB,MACvB,6DACF;AACA,MAAM,sBAAsB,MAC1B,iFACF;AACA,MAAM,qBAAqB,MAAM,iBAAiB;AAElD,IAAa,0BAAb,MAAa,gCAAgC,WAAW;CACtD,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,wBAAwB,EAAE;CAClC;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,kDAAkD;CAC5D;CAEA,uBAAgC,cAA+B;EAC7D,OAAO;CACT;CAEA,oBAAsCA;CAEtC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,cAAc,EAC1B,eACmD;;EAEnD,IAAI,CAAC,aACH,OAAO;EAGT,MAAM,MAAqB;GACzB,UAAU;GACV,WAAW;GACX,UAAU,CAAC;EACb;EAEA,MAAM,oBAAoB,aACxB,aACA,mCACF;EAIA,MAAM,SAAQ,MAFS,KAAK,KAAK,QAAQ,iBAAiB,EAAA,CAEnC,KAAK,MAAM,oBAAoB;EAEtD,MAAM,kBAAkB,MAAM,QAAQ,4BAA4B;EAClE,IAAI,oBAAoB,IACtB,MAAM,IAAI,kCACR,IAAI,MAAM,oDAAoD,CAChE;EAIF,MAAM,OAAO,GAAG,kBAAkB,CAAC;EAGnC,IAAI,UAAuE,EACzE,SAAS,KAAA,EACX;EACA,IAAI,oBAAoB;EACxB,OAAO,MAAM,WAAW,GAAG;GACzB,MAAM,OAAO,MAAM,MAAM;GACzB,IAAI,SAAS,sBACP;QAAA,QAAQ,YAAY,KAAA,GACtB,MAAM,IAAI,kCACR,IAAI,MACF,yDACF,CACF;GAAA,OAEG,IAAI,SAAS,wBAAwB;IAC1C,IAAI,mBACF,oBAAoB;SACf;KACL,IAAI,QAAQ,YAAY,KAAA,GACtB,MAAM,IAAI,kCACR,IAAI,MAAM,0CAA0C,CACtD;KAEF,IAAI,SAAS,KAAK,OAAkB;IACtC;IACA,UAAU,EAAE,SAAS,KAAA,EAAU;GACjC,OAAO;IAEL,IADwB,mBAAmB,KAAK,IAC9B,GAChB,oBAAoB;IAEtB,MAAM,mBAAmB,iBAAiB,KAAK,IAAI;IACnD,IAAI,kBAAkB,QAAQ;KAE5B,MAAM,OAAO,iBAAiB,OAAO,KAAK,SAAS,GAAG,GAAG;KACzD,MAAM,QAAQ,iBAAiB,OAAO,MAAM,SAAS,GAAG,GAAG;KAC3D,MAAM,MAAM,iBAAiB,OAAO,IAAI,SAAS,GAAG,GAAG;KACvD,QAAQ,mBAAmB,YACzB,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,eAC1B;IACF;IACA,MAAM,sBAAsB,oBAAoB,KAAK,IAAI;IACzD,IAAI,qBAAqB,QAAQ;KAC/B,QAAQ,UAAU,GAAG,oBAAoB,OAAO,aAAa,GAAG,oBAAoB,OAAO,aAAa,GAAG,oBAAoB,OAAO;KACtI,IAAI,CAAC,UAAU,QAAQ,OAAO,GAC5B,MAAM,IAAI,kCACR,IAAI,MAAM,WAAW,QAAQ,QAAQ,uBAAuB,CAC9D;IAEJ;GACF;EACF;EAEA,IAAI,IAAI,SAAS,WAAW,GAC1B,MAAM,IAAI,kCACR,IAAI,MAAM,wCAAwC,CACpD;EAGF,OAAO;CACT;CAEA,YAAY,QAA0D;EACpE,OAAO,KAAK,OACV;GACE,KAAK,GAAG,OAAO;GACf,UAAU;EACZ,SACM,KAAK,cAAc,MAAM,CACjC;CACF;AACF"}
1
+ {"version":3,"file":"index.js","names":["semverVersioningId"],"sources":["../../../../lib/modules/datasource/golang-version/index.ts"],"sourcesContent":["import { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { joinUrlParts } from '../../../util/url.ts';\nimport {\n isVersion,\n id as semverVersioningId,\n} from '../../versioning/semver/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\n\nconst lineTerminationRegex = regEx(`\\r?\\n`);\nconst releaseBeginningChar = '\\t{';\nconst releaseTerminationChar = '\\t},';\nconst releaseDateRegex = regEx(\n `Date\\\\{(?<year>\\\\d+),\\\\s+(?<month>\\\\d+),\\\\s+(?<day>\\\\d+)\\\\}`,\n);\nconst releaseVersionRegex = regEx(\n `Version\\\\{(?<versionMajor>\\\\d+),\\\\s+(?<versionMinor>\\\\d+),\\\\s+(?<patch>\\\\d+)\\\\}`,\n);\nconst releaseFutureRegex = regEx(`Future:\\\\s+true`);\n\nexport class GolangVersionDatasource extends Datasource {\n static readonly id = 'golang-version';\n\n constructor() {\n super(GolangVersionDatasource.id);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://raw.githubusercontent.com/golang/website'];\n }\n\n override supportsCustomRegistry(_packageName: string): boolean {\n return true;\n }\n\n override readonly defaultVersioning = semverVersioningId;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `Date` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'We use the URL: https://github.com/golang/go.';\n\n private async fetchReleases({\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore next -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const res: ReleaseResult = {\n homepage: 'https://go.dev/',\n sourceUrl: 'https://github.com/golang/go',\n releases: [],\n };\n\n const golangVersionsUrl = joinUrlParts(\n registryUrl,\n '/HEAD/internal/history/release.go',\n );\n\n const response = await this.http.getText(golangVersionsUrl);\n\n const lines = response.body.split(lineTerminationRegex);\n\n const startOfReleases = lines.indexOf('var Releases = []*Release{');\n if (startOfReleases === -1) {\n throw new ExternalHostError(\n new Error('Invalid file - could not find the Releases section'),\n );\n }\n\n // Remove part before releases\n lines.splice(0, startOfReleases + 1);\n\n // Parse the release list\n let release: Omit<Release, 'version'> & { version?: string | undefined } = {\n version: undefined,\n };\n let skipFutureRelease = false;\n while (lines.length !== 0) {\n const line = lines.shift()!;\n if (line === releaseBeginningChar) {\n if (release.version !== undefined) {\n throw new ExternalHostError(\n new Error(\n 'Invalid file - unexpected error while parsing a release',\n ),\n );\n }\n } else if (line === releaseTerminationChar) {\n if (skipFutureRelease) {\n skipFutureRelease = false;\n } else {\n if (release.version === undefined) {\n throw new ExternalHostError(\n new Error('Invalid file - release has empty version'),\n );\n }\n res.releases.push(release as Release);\n }\n release = { version: undefined };\n } else {\n const isFutureRelease = releaseFutureRegex.test(line);\n if (isFutureRelease) {\n skipFutureRelease = true;\n }\n const releaseDateMatch = releaseDateRegex.exec(line);\n if (releaseDateMatch?.groups) {\n // Make a valid UTC timestamp\n const year = releaseDateMatch.groups.year.padStart(4, '0');\n const month = releaseDateMatch.groups.month.padStart(2, '0');\n const day = releaseDateMatch.groups.day.padStart(2, '0');\n release.releaseTimestamp = asTimestamp(\n `${year}-${month}-${day}T00:00:00.000Z`,\n );\n }\n const releaseVersionMatch = releaseVersionRegex.exec(line);\n if (releaseVersionMatch?.groups) {\n release.version = `${releaseVersionMatch.groups.versionMajor}.${releaseVersionMatch.groups.versionMinor}.${releaseVersionMatch.groups.patch}`;\n if (!isVersion(release.version)) {\n throw new ExternalHostError(\n new Error(`Version ${release.version} is not a valid semver`),\n );\n }\n }\n }\n }\n\n if (res.releases.length === 0) {\n throw new ExternalHostError(\n new Error(`Invalid file - zero releases extracted`),\n );\n }\n\n return res;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return this.cached(\n {\n key: config.registryUrl!,\n fallback: true,\n },\n () => this.fetchReleases(config),\n );\n }\n}\n"],"mappings":";;;;;;;AAWA,MAAM,uBAAuB,MAAM,OAAO;AAC1C,MAAM,uBAAuB;AAC7B,MAAM,yBAAyB;AAC/B,MAAM,mBAAmB,MACvB,6DACF;AACA,MAAM,sBAAsB,MAC1B,iFACF;AACA,MAAM,qBAAqB,MAAM,iBAAiB;AAElD,IAAa,0BAAb,MAAa,gCAAgC,WAAW;CACtD,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,wBAAwB,EAAE;CAClC;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,kDAAkD;CAC5D;CAEA,uBAAgC,cAA+B;EAC7D,OAAO;CACT;CAEA,oBAAsCA;CAEtC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,cAAc,EAC1B,eACmD;;EAEnD,IAAI,CAAC,aACH,OAAO;EAGT,MAAM,MAAqB;GACzB,UAAU;GACV,WAAW;GACX,UAAU,CAAC;EACb;EAEA,MAAM,oBAAoB,aACxB,aACA,mCACF;EAIA,MAAM,SAAQ,MAFS,KAAK,KAAK,QAAQ,iBAAiB,EAAA,CAEnC,KAAK,MAAM,oBAAoB;EAEtD,MAAM,kBAAkB,MAAM,QAAQ,4BAA4B;EAClE,IAAI,oBAAoB,IACtB,MAAM,IAAI,kCACR,IAAI,MAAM,oDAAoD,CAChE;EAIF,MAAM,OAAO,GAAG,kBAAkB,CAAC;EAGnC,IAAI,UAAuE,EACzE,SAAS,KAAA,EACX;EACA,IAAI,oBAAoB;EACxB,OAAO,MAAM,WAAW,GAAG;GACzB,MAAM,OAAO,MAAM,MAAM;GACzB,IAAI,SAAS,sBACP;QAAA,QAAQ,YAAY,KAAA,GACtB,MAAM,IAAI,kCACR,IAAI,MACF,yDACF,CACF;GAAA,OAEG,IAAI,SAAS,wBAAwB;IAC1C,IAAI,mBACF,oBAAoB;SACf;KACL,IAAI,QAAQ,YAAY,KAAA,GACtB,MAAM,IAAI,kCACR,IAAI,MAAM,0CAA0C,CACtD;KAEF,IAAI,SAAS,KAAK,OAAkB;IACtC;IACA,UAAU,EAAE,SAAS,KAAA,EAAU;GACjC,OAAO;IAEL,IADwB,mBAAmB,KAAK,IAC9B,GAChB,oBAAoB;IAEtB,MAAM,mBAAmB,iBAAiB,KAAK,IAAI;IACnD,IAAI,kBAAkB,QAAQ;KAE5B,MAAM,OAAO,iBAAiB,OAAO,KAAK,SAAS,GAAG,GAAG;KACzD,MAAM,QAAQ,iBAAiB,OAAO,MAAM,SAAS,GAAG,GAAG;KAC3D,MAAM,MAAM,iBAAiB,OAAO,IAAI,SAAS,GAAG,GAAG;KACvD,QAAQ,mBAAmB,YACzB,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,eAC1B;IACF;IACA,MAAM,sBAAsB,oBAAoB,KAAK,IAAI;IACzD,IAAI,qBAAqB,QAAQ;KAC/B,QAAQ,UAAU,GAAG,oBAAoB,OAAO,aAAa,GAAG,oBAAoB,OAAO,aAAa,GAAG,oBAAoB,OAAO;KACtI,IAAI,CAAC,UAAU,QAAQ,OAAO,GAC5B,MAAM,IAAI,kCACR,IAAI,MAAM,WAAW,QAAQ,QAAQ,uBAAuB,CAC9D;IAEJ;GACF;EACF;EAEA,IAAI,IAAI,SAAS,WAAW,GAC1B,MAAM,IAAI,kCACR,IAAI,MAAM,wCAAwC,CACpD;EAGF,OAAO;CACT;CAEA,YAAY,QAA0D;EACpE,OAAO,KAAK,OACV;GACE,KAAK,OAAO;GACZ,UAAU;EACZ,SACM,KAAK,cAAc,MAAM,CACjC;CACF;AACF"}
@@ -42,7 +42,7 @@ var GradleVersionDatasource = class GradleVersionDatasource extends Datasource {
42
42
  getReleases(config) {
43
43
  return withCache({
44
44
  namespace: `datasource-${GradleVersionDatasource.id}`,
45
- key: `${config.registryUrl}`,
45
+ key: config.registryUrl,
46
46
  fallback: true
47
47
  }, () => this._getReleases(config));
48
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["gradleVersioning.id"],"sources":["../../../../lib/modules/datasource/gradle-version/index.ts"],"sourcesContent":["import { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport * as gradleVersioning from '../../versioning/gradle/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\nimport { GradleReleases } from './schema.ts';\n\nexport class GradleVersionDatasource extends Datasource {\n static readonly id = 'gradle-version';\n\n constructor() {\n super(GradleVersionDatasource.id);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://services.gradle.org/versions/all'];\n }\n\n override readonly defaultVersioning = gradleVersioning.id;\n\n override readonly registryStrategy = 'merge';\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `buildTime` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'We use the URL: https://github.com/gradle/gradle.';\n\n private async _getReleases({\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore next -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const body = await this.fetchJson(registryUrl, GradleReleases);\n const releases = body\n .filter((release) => !release.snapshot && !release.nightly)\n .map((release) => {\n const { version, buildTime } = release;\n\n const gitRef = GradleVersionDatasource.getGitRef(release.version);\n\n const releaseTimestamp = asTimestamp(buildTime);\n\n const result: Release = { version, gitRef, releaseTimestamp };\n\n if (release.broken) {\n result.isDeprecated = true;\n }\n\n return result;\n });\n\n const res: ReleaseResult = {\n releases,\n homepage: 'https://gradle.org',\n sourceUrl: 'https://github.com/gradle/gradle',\n };\n if (res.releases.length) {\n return res;\n }\n return null;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${GradleVersionDatasource.id}`,\n // TODO: types (#22198)\n key: `${config.registryUrl}`,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n /**\n * Calculate `gitTag` based on `version`:\n * - `8.1.2` -> `v8.1.2`\n * - `8.2` -> `v8.2.0`\n * - `8.2-rc-1` -> `v8.2.0-RC1`\n * - `8.2-milestone-1` -> `v8.2.0-M1`\n */\n private static getGitRef(version: string): string {\n const [versionPart, typePart, unstablePart] = version.split(\n regEx(/-(?<type>[a-z]+)-/),\n );\n\n let suffix = '';\n if (typePart === 'rc') {\n suffix = `-RC${unstablePart}`;\n } else if (typePart === 'milestone') {\n suffix = `-M${unstablePart}`;\n }\n\n const [major, minor, patch = '0'] = versionPart.split('.');\n return `v${major}.${minor}.${patch}${suffix}`;\n }\n}\n"],"mappings":";;;;;;;AAQA,IAAa,0BAAb,MAAa,gCAAgC,WAAW;CACtD,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,wBAAwB,EAAE;CAClC;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,0CAA0C;CACpD;CAEA,oBAAsCA;CAEtC,mBAAqC;CAErC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,aAAa,EACzB,eACmD;;EAEnD,IAAI,CAAC,aACH,OAAO;EAsBT,MAAM,MAAqB;GACzB,WAnBe,MADE,KAAK,UAAU,aAAa,cAAc,EAAA,CAE1D,QAAQ,YAAY,CAAC,QAAQ,YAAY,CAAC,QAAQ,OAAO,CAAC,CAC1D,KAAK,YAAY;IAChB,MAAM,EAAE,SAAS,cAAc;IAM/B,MAAM,SAAkB;KAAE;KAAS,QAJpB,wBAAwB,UAAU,QAAQ,OAIjB;KAAG,kBAFlB,YAAY,SAEqB;IAAE;IAE5D,IAAI,QAAQ,QACV,OAAO,eAAe;IAGxB,OAAO;GACT,CAGO;GACP,UAAU;GACV,WAAW;EACb;EACA,IAAI,IAAI,SAAS,QACf,OAAO;EAET,OAAO;CACT;CAEA,YAAY,QAA0D;EACpE,OAAO,UACL;GACE,WAAW,cAAc,wBAAwB;GAEjD,KAAK,GAAG,OAAO;GACf,UAAU;EACZ,SACM,KAAK,aAAa,MAAM,CAChC;CACF;;;;;;;;CASA,OAAe,UAAU,SAAyB;EAChD,MAAM,CAAC,aAAa,UAAU,gBAAgB,QAAQ,MACpD,MAAM,mBAAmB,CAC3B;EAEA,IAAI,SAAS;EACb,IAAI,aAAa,MACf,SAAS,MAAM;OACV,IAAI,aAAa,aACtB,SAAS,KAAK;EAGhB,MAAM,CAAC,OAAO,OAAO,QAAQ,OAAO,YAAY,MAAM,GAAG;EACzD,OAAO,IAAI,MAAM,GAAG,MAAM,GAAG,QAAQ;CACvC;AACF"}
1
+ {"version":3,"file":"index.js","names":["gradleVersioning.id"],"sources":["../../../../lib/modules/datasource/gradle-version/index.ts"],"sourcesContent":["import { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport * as gradleVersioning from '../../versioning/gradle/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\nimport { GradleReleases } from './schema.ts';\n\nexport class GradleVersionDatasource extends Datasource {\n static readonly id = 'gradle-version';\n\n constructor() {\n super(GradleVersionDatasource.id);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://services.gradle.org/versions/all'];\n }\n\n override readonly defaultVersioning = gradleVersioning.id;\n\n override readonly registryStrategy = 'merge';\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `buildTime` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'We use the URL: https://github.com/gradle/gradle.';\n\n private async _getReleases({\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore next -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const body = await this.fetchJson(registryUrl, GradleReleases);\n const releases = body\n .filter((release) => !release.snapshot && !release.nightly)\n .map((release) => {\n const { version, buildTime } = release;\n\n const gitRef = GradleVersionDatasource.getGitRef(release.version);\n\n const releaseTimestamp = asTimestamp(buildTime);\n\n const result: Release = { version, gitRef, releaseTimestamp };\n\n if (release.broken) {\n result.isDeprecated = true;\n }\n\n return result;\n });\n\n const res: ReleaseResult = {\n releases,\n homepage: 'https://gradle.org',\n sourceUrl: 'https://github.com/gradle/gradle',\n };\n if (res.releases.length) {\n return res;\n }\n return null;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${GradleVersionDatasource.id}`,\n key: config.registryUrl!,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n /**\n * Calculate `gitTag` based on `version`:\n * - `8.1.2` -> `v8.1.2`\n * - `8.2` -> `v8.2.0`\n * - `8.2-rc-1` -> `v8.2.0-RC1`\n * - `8.2-milestone-1` -> `v8.2.0-M1`\n */\n private static getGitRef(version: string): string {\n const [versionPart, typePart, unstablePart] = version.split(\n regEx(/-(?<type>[a-z]+)-/),\n );\n\n let suffix = '';\n if (typePart === 'rc') {\n suffix = `-RC${unstablePart}`;\n } else if (typePart === 'milestone') {\n suffix = `-M${unstablePart}`;\n }\n\n const [major, minor, patch = '0'] = versionPart.split('.');\n return `v${major}.${minor}.${patch}${suffix}`;\n }\n}\n"],"mappings":";;;;;;;AAQA,IAAa,0BAAb,MAAa,gCAAgC,WAAW;CACtD,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,wBAAwB,EAAE;CAClC;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,0CAA0C;CACpD;CAEA,oBAAsCA;CAEtC,mBAAqC;CAErC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,aAAa,EACzB,eACmD;;EAEnD,IAAI,CAAC,aACH,OAAO;EAsBT,MAAM,MAAqB;GACzB,WAnBe,MADE,KAAK,UAAU,aAAa,cAAc,EAAA,CAE1D,QAAQ,YAAY,CAAC,QAAQ,YAAY,CAAC,QAAQ,OAAO,CAAC,CAC1D,KAAK,YAAY;IAChB,MAAM,EAAE,SAAS,cAAc;IAM/B,MAAM,SAAkB;KAAE;KAAS,QAJpB,wBAAwB,UAAU,QAAQ,OAIjB;KAAG,kBAFlB,YAAY,SAEqB;IAAE;IAE5D,IAAI,QAAQ,QACV,OAAO,eAAe;IAGxB,OAAO;GACT,CAGO;GACP,UAAU;GACV,WAAW;EACb;EACA,IAAI,IAAI,SAAS,QACf,OAAO;EAET,OAAO;CACT;CAEA,YAAY,QAA0D;EACpE,OAAO,UACL;GACE,WAAW,cAAc,wBAAwB;GACjD,KAAK,OAAO;GACZ,UAAU;EACZ,SACM,KAAK,aAAa,MAAM,CAChC;CACF;;;;;;;;CASA,OAAe,UAAU,SAAyB;EAChD,MAAM,CAAC,aAAa,UAAU,gBAAgB,QAAQ,MACpD,MAAM,mBAAmB,CAC3B;EAEA,IAAI,SAAS;EACb,IAAI,aAAa,MACf,SAAS,MAAM;OACV,IAAI,aAAa,aACtB,SAAS,KAAK;EAGhB,MAAM,CAAC,OAAO,OAAO,QAAQ,OAAO,YAAY,MAAM,GAAG;EACzD,OAAO,IAAI,MAAM,GAAG,MAAM,GAAG,QAAQ;CACvC;AACF"}
@@ -2,6 +2,7 @@ import { logger } from "../../../logger/index.js";
2
2
  import { ensureTrailingSlash } from "../../../util/url.js";
3
3
  import { find } from "../../../util/host-rules.js";
4
4
  import { parseSingleYaml } from "../../../util/yaml.js";
5
+ import { buildCacheKey } from "../../../util/cache/package/key.js";
5
6
  import { ExternalHostError } from "../../../types/errors/external-host-error.js";
6
7
  import { id } from "../../versioning/helm/index.js";
7
8
  import { withCache } from "../../../util/cache/package/with-cache.js";
@@ -38,7 +39,7 @@ var HelmDatasource = class HelmDatasource extends Datasource {
38
39
  getRepositoryData(helmRepository) {
39
40
  return withCache({
40
41
  namespace: `datasource-${HelmDatasource.id}`,
41
- key: `repository-data:${helmRepository}`
42
+ key: buildCacheKey("repository-data", helmRepository)
42
43
  }, () => this._getRepositoryData(helmRepository));
43
44
  }
44
45
  async getReleases({ packageName, registryUrl: helmRepository }) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["helmVersioning.id","hostRules.find"],"sources":["../../../../lib/modules/datasource/helm/index.ts"],"sourcesContent":["import { Readable } from 'node:stream';\nimport type {\n GetObjectCommandOutput,\n S3ClientConfig,\n} from '@aws-sdk/client-s3';\nimport { GetObjectCommand } from '@aws-sdk/client-s3';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport type { S3UrlParts } from '../../../util/s3.ts';\nimport { getS3Client, parseS3Url } from '../../../util/s3.ts';\nimport { streamToString } from '../../../util/streams.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { parseSingleYaml } from '../../../util/yaml.ts';\nimport * as helmVersioning from '../../versioning/helm/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport { HelmRepository } from './schema.ts';\n\nexport class HelmDatasource extends Datasource {\n static readonly id = 'helm';\n\n constructor() {\n super(HelmDatasource.id);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://charts.helm.sh/stable'];\n }\n\n override readonly defaultConfig = {\n commitMessageTopic: 'Helm release {{depName}}',\n };\n\n override readonly defaultVersioning = helmVersioning.id;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timstamp is determined from the `created` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `home` field or the `sources` field in the results.';\n\n private async _getRepositoryData(\n helmRepository: string,\n ): Promise<HelmRepository> {\n const baseUrl = ensureTrailingSlash(helmRepository);\n const indexUrl = `${baseUrl}index.yaml`;\n\n const s3Url = parseS3Url(indexUrl);\n if (s3Url) {\n return await getS3RepositoryData(s3Url, indexUrl);\n }\n\n const { val, err } = await this.http\n .getYamlSafe('index.yaml', { baseUrl }, HelmRepository)\n .unwrap();\n\n if (err) {\n this.handleGenericErrors(err);\n }\n\n return val;\n }\n\n getRepositoryData(helmRepository: string): Promise<HelmRepository> {\n return withCache(\n {\n namespace: `datasource-${HelmDatasource.id}`,\n key: `repository-data:${helmRepository}`,\n },\n () => this._getRepositoryData(helmRepository),\n );\n }\n\n async getReleases({\n packageName,\n registryUrl: helmRepository,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore next -- should never happen */\n if (!helmRepository) {\n return null;\n }\n\n const repositoryData = await this.getRepositoryData(helmRepository);\n const releases = repositoryData[packageName];\n if (!releases) {\n logger.debug(\n { dependency: packageName },\n `Entry ${packageName} doesn't exist in index.yaml from ${helmRepository}`,\n );\n return null;\n }\n return releases;\n }\n}\n\nasync function getS3RepositoryData(\n s3Url: S3UrlParts,\n indexUrl: string,\n): Promise<HelmRepository> {\n const client = getS3Client(undefined, undefined, getS3Credentials(indexUrl));\n\n let res: GetObjectCommandOutput;\n try {\n res = await client.send(new GetObjectCommand(s3Url));\n } catch (err) {\n throw classifyS3Error(err, indexUrl);\n }\n\n if (res.DeleteMarker) {\n logger.debug(\n { indexUrl },\n 'Helm S3 lookup error: DeleteMarker encountered',\n );\n throw new Error(`No index.yaml found at ${indexUrl}`);\n }\n\n if (!(res.Body instanceof Readable)) {\n logger.debug({ indexUrl }, 'Helm S3 lookup error: unsupported Body type');\n throw new Error(`Unsupported S3 response body for ${indexUrl}`);\n }\n\n return parseSingleYaml(await streamToString(res.Body), {\n customSchema: HelmRepository,\n });\n}\n\n/**\n * Only a missing object means \"this chart repository has no releases\", so that\n * error is rethrown as-is and the lookup resolves to `null`.\n * Everything else becomes an `ExternalHostError` to abort the run, otherwise a\n * transient S3 failure looks like a deleted chart and closes open PRs.\n */\nfunction classifyS3Error(\n // `name` holds the S3 error code, `message` holds server-supplied prose\n err: Error & { $metadata?: { httpStatusCode?: number } },\n indexUrl: string,\n): Error {\n if (err.name === 'NotFound' || err.name === 'NoSuchKey') {\n logger.debug({ indexUrl }, 'Helm S3 lookup error: object not found');\n return err;\n }\n\n if (\n err.name === 'CredentialsProviderError' ||\n err.$metadata?.httpStatusCode === 403\n ) {\n logger.debug(\n { indexUrl, err },\n 'Helm S3 lookup error: credentials error, check \"AWS_ACCESS_KEY_ID\" and \"AWS_SECRET_ACCESS_KEY\" variables or the matching `hostRules` entry',\n );\n } else if (err.message === 'Region is missing') {\n // Thrown client-side by the SDK region resolver, so this string is stable\n logger.debug(\n { indexUrl },\n 'Helm S3 lookup error: missing region, check \"AWS_REGION\" variable',\n );\n } else {\n logger.debug({ indexUrl, err }, 'Helm S3 lookup error: unknown error');\n }\n\n return new ExternalHostError(err, HelmDatasource.id);\n}\n\nfunction getS3Credentials(\n indexUrl: string,\n): S3ClientConfig['credentials'] | undefined {\n const { username, password, token } = hostRules.find({\n hostType: HelmDatasource.id,\n url: indexUrl,\n });\n\n // Fall back to the default AWS credential provider chain\n if (!username || !password) {\n return undefined;\n }\n\n return {\n accessKeyId: username,\n secretAccessKey: password,\n sessionToken: token,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;AAoBA,IAAa,iBAAb,MAAa,uBAAuB,WAAW;CAC7C,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,eAAe,EAAE;CACzB;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,+BAA+B;CACzC;CAEA,gBAAkC,EAChC,oBAAoB,2BACtB;CAEA,oBAAsCA;CAEtC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,mBACZ,gBACyB;EACzB,MAAM,UAAU,oBAAoB,cAAc;EAClD,MAAM,WAAW,GAAG,QAAQ;EAE5B,MAAM,QAAQ,WAAW,QAAQ;EACjC,IAAI,OACF,OAAO,MAAM,oBAAoB,OAAO,QAAQ;EAGlD,MAAM,EAAE,KAAK,QAAQ,MAAM,KAAK,KAC7B,YAAY,cAAc,EAAE,QAAQ,GAAG,cAAc,CAAC,CACtD,OAAO;EAEV,IAAI,KACF,KAAK,oBAAoB,GAAG;EAG9B,OAAO;CACT;CAEA,kBAAkB,gBAAiD;EACjE,OAAO,UACL;GACE,WAAW,cAAc,eAAe;GACxC,KAAK,mBAAmB;EAC1B,SACM,KAAK,mBAAmB,cAAc,CAC9C;CACF;CAEA,MAAM,YAAY,EAChB,aACA,aAAa,kBACsC;;EAEnD,IAAI,CAAC,gBACH,OAAO;EAIT,MAAM,YAAW,MADY,KAAK,kBAAkB,cAAc,EAAA,CAClC;EAChC,IAAI,CAAC,UAAU;GACb,OAAO,MACL,EAAE,YAAY,YAAY,GAC1B,SAAS,YAAY,oCAAoC,gBAC3D;GACA,OAAO;EACT;EACA,OAAO;CACT;AACF;AAEA,eAAe,oBACb,OACA,UACyB;CACzB,MAAM,SAAS,YAAY,KAAA,GAAW,KAAA,GAAW,iBAAiB,QAAQ,CAAC;CAE3E,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,OAAO,KAAK,IAAI,iBAAiB,KAAK,CAAC;CACrD,SAAS,KAAK;EACZ,MAAM,gBAAgB,KAAK,QAAQ;CACrC;CAEA,IAAI,IAAI,cAAc;EACpB,OAAO,MACL,EAAE,SAAS,GACX,gDACF;EACA,MAAM,IAAI,MAAM,0BAA0B,UAAU;CACtD;CAEA,IAAI,EAAE,IAAI,gBAAgB,WAAW;EACnC,OAAO,MAAM,EAAE,SAAS,GAAG,6CAA6C;EACxE,MAAM,IAAI,MAAM,oCAAoC,UAAU;CAChE;CAEA,OAAO,gBAAgB,MAAM,eAAe,IAAI,IAAI,GAAG,EACrD,cAAc,eAChB,CAAC;AACH;;;;;;;AAQA,SAAS,gBAEP,KACA,UACO;CACP,IAAI,IAAI,SAAS,cAAc,IAAI,SAAS,aAAa;EACvD,OAAO,MAAM,EAAE,SAAS,GAAG,wCAAwC;EACnE,OAAO;CACT;CAEA,IACE,IAAI,SAAS,8BACb,IAAI,WAAW,mBAAmB,KAElC,OAAO,MACL;EAAE;EAAU;CAAI,GAChB,gJACF;MACK,IAAI,IAAI,YAAY,qBAEzB,OAAO,MACL,EAAE,SAAS,GACX,qEACF;MAEA,OAAO,MAAM;EAAE;EAAU;CAAI,GAAG,qCAAqC;CAGvE,OAAO,IAAI,kBAAkB,KAAK,eAAe,EAAE;AACrD;AAEA,SAAS,iBACP,UAC2C;CAC3C,MAAM,EAAE,UAAU,UAAU,UAAUC,KAAe;EACnD,UAAU,eAAe;EACzB,KAAK;CACP,CAAC;CAGD,IAAI,CAAC,YAAY,CAAC,UAChB;CAGF,OAAO;EACL,aAAa;EACb,iBAAiB;EACjB,cAAc;CAChB;AACF"}
1
+ {"version":3,"file":"index.js","names":["helmVersioning.id","hostRules.find"],"sources":["../../../../lib/modules/datasource/helm/index.ts"],"sourcesContent":["import { Readable } from 'node:stream';\nimport type {\n GetObjectCommandOutput,\n S3ClientConfig,\n} from '@aws-sdk/client-s3';\nimport { GetObjectCommand } from '@aws-sdk/client-s3';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { buildCacheKey } from '../../../util/cache/package/key.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport type { S3UrlParts } from '../../../util/s3.ts';\nimport { getS3Client, parseS3Url } from '../../../util/s3.ts';\nimport { streamToString } from '../../../util/streams.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { parseSingleYaml } from '../../../util/yaml.ts';\nimport * as helmVersioning from '../../versioning/helm/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport { HelmRepository } from './schema.ts';\n\nexport class HelmDatasource extends Datasource {\n static readonly id = 'helm';\n\n constructor() {\n super(HelmDatasource.id);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://charts.helm.sh/stable'];\n }\n\n override readonly defaultConfig = {\n commitMessageTopic: 'Helm release {{depName}}',\n };\n\n override readonly defaultVersioning = helmVersioning.id;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timstamp is determined from the `created` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `home` field or the `sources` field in the results.';\n\n private async _getRepositoryData(\n helmRepository: string,\n ): Promise<HelmRepository> {\n const baseUrl = ensureTrailingSlash(helmRepository);\n const indexUrl = `${baseUrl}index.yaml`;\n\n const s3Url = parseS3Url(indexUrl);\n if (s3Url) {\n return await getS3RepositoryData(s3Url, indexUrl);\n }\n\n const { val, err } = await this.http\n .getYamlSafe('index.yaml', { baseUrl }, HelmRepository)\n .unwrap();\n\n if (err) {\n this.handleGenericErrors(err);\n }\n\n return val;\n }\n\n getRepositoryData(helmRepository: string): Promise<HelmRepository> {\n return withCache(\n {\n namespace: `datasource-${HelmDatasource.id}`,\n key: buildCacheKey('repository-data', helmRepository),\n },\n () => this._getRepositoryData(helmRepository),\n );\n }\n\n async getReleases({\n packageName,\n registryUrl: helmRepository,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore next -- should never happen */\n if (!helmRepository) {\n return null;\n }\n\n const repositoryData = await this.getRepositoryData(helmRepository);\n const releases = repositoryData[packageName];\n if (!releases) {\n logger.debug(\n { dependency: packageName },\n `Entry ${packageName} doesn't exist in index.yaml from ${helmRepository}`,\n );\n return null;\n }\n return releases;\n }\n}\n\nasync function getS3RepositoryData(\n s3Url: S3UrlParts,\n indexUrl: string,\n): Promise<HelmRepository> {\n const client = getS3Client(undefined, undefined, getS3Credentials(indexUrl));\n\n let res: GetObjectCommandOutput;\n try {\n res = await client.send(new GetObjectCommand(s3Url));\n } catch (err) {\n throw classifyS3Error(err, indexUrl);\n }\n\n if (res.DeleteMarker) {\n logger.debug(\n { indexUrl },\n 'Helm S3 lookup error: DeleteMarker encountered',\n );\n throw new Error(`No index.yaml found at ${indexUrl}`);\n }\n\n if (!(res.Body instanceof Readable)) {\n logger.debug({ indexUrl }, 'Helm S3 lookup error: unsupported Body type');\n throw new Error(`Unsupported S3 response body for ${indexUrl}`);\n }\n\n return parseSingleYaml(await streamToString(res.Body), {\n customSchema: HelmRepository,\n });\n}\n\n/**\n * Only a missing object means \"this chart repository has no releases\", so that\n * error is rethrown as-is and the lookup resolves to `null`.\n * Everything else becomes an `ExternalHostError` to abort the run, otherwise a\n * transient S3 failure looks like a deleted chart and closes open PRs.\n */\nfunction classifyS3Error(\n // `name` holds the S3 error code, `message` holds server-supplied prose\n err: Error & { $metadata?: { httpStatusCode?: number } },\n indexUrl: string,\n): Error {\n if (err.name === 'NotFound' || err.name === 'NoSuchKey') {\n logger.debug({ indexUrl }, 'Helm S3 lookup error: object not found');\n return err;\n }\n\n if (\n err.name === 'CredentialsProviderError' ||\n err.$metadata?.httpStatusCode === 403\n ) {\n logger.debug(\n { indexUrl, err },\n 'Helm S3 lookup error: credentials error, check \"AWS_ACCESS_KEY_ID\" and \"AWS_SECRET_ACCESS_KEY\" variables or the matching `hostRules` entry',\n );\n } else if (err.message === 'Region is missing') {\n // Thrown client-side by the SDK region resolver, so this string is stable\n logger.debug(\n { indexUrl },\n 'Helm S3 lookup error: missing region, check \"AWS_REGION\" variable',\n );\n } else {\n logger.debug({ indexUrl, err }, 'Helm S3 lookup error: unknown error');\n }\n\n return new ExternalHostError(err, HelmDatasource.id);\n}\n\nfunction getS3Credentials(\n indexUrl: string,\n): S3ClientConfig['credentials'] | undefined {\n const { username, password, token } = hostRules.find({\n hostType: HelmDatasource.id,\n url: indexUrl,\n });\n\n // Fall back to the default AWS credential provider chain\n if (!username || !password) {\n return undefined;\n }\n\n return {\n accessKeyId: username,\n secretAccessKey: password,\n sessionToken: token,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,IAAa,iBAAb,MAAa,uBAAuB,WAAW;CAC7C,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,eAAe,EAAE;CACzB;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,+BAA+B;CACzC;CAEA,gBAAkC,EAChC,oBAAoB,2BACtB;CAEA,oBAAsCA;CAEtC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,mBACZ,gBACyB;EACzB,MAAM,UAAU,oBAAoB,cAAc;EAClD,MAAM,WAAW,GAAG,QAAQ;EAE5B,MAAM,QAAQ,WAAW,QAAQ;EACjC,IAAI,OACF,OAAO,MAAM,oBAAoB,OAAO,QAAQ;EAGlD,MAAM,EAAE,KAAK,QAAQ,MAAM,KAAK,KAC7B,YAAY,cAAc,EAAE,QAAQ,GAAG,cAAc,CAAC,CACtD,OAAO;EAEV,IAAI,KACF,KAAK,oBAAoB,GAAG;EAG9B,OAAO;CACT;CAEA,kBAAkB,gBAAiD;EACjE,OAAO,UACL;GACE,WAAW,cAAc,eAAe;GACxC,KAAK,cAAc,mBAAmB,cAAc;EACtD,SACM,KAAK,mBAAmB,cAAc,CAC9C;CACF;CAEA,MAAM,YAAY,EAChB,aACA,aAAa,kBACsC;;EAEnD,IAAI,CAAC,gBACH,OAAO;EAIT,MAAM,YAAW,MADY,KAAK,kBAAkB,cAAc,EAAA,CAClC;EAChC,IAAI,CAAC,UAAU;GACb,OAAO,MACL,EAAE,YAAY,YAAY,GAC1B,SAAS,YAAY,oCAAoC,gBAC3D;GACA,OAAO;EACT;EACA,OAAO;CACT;AACF;AAEA,eAAe,oBACb,OACA,UACyB;CACzB,MAAM,SAAS,YAAY,KAAA,GAAW,KAAA,GAAW,iBAAiB,QAAQ,CAAC;CAE3E,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,OAAO,KAAK,IAAI,iBAAiB,KAAK,CAAC;CACrD,SAAS,KAAK;EACZ,MAAM,gBAAgB,KAAK,QAAQ;CACrC;CAEA,IAAI,IAAI,cAAc;EACpB,OAAO,MACL,EAAE,SAAS,GACX,gDACF;EACA,MAAM,IAAI,MAAM,0BAA0B,UAAU;CACtD;CAEA,IAAI,EAAE,IAAI,gBAAgB,WAAW;EACnC,OAAO,MAAM,EAAE,SAAS,GAAG,6CAA6C;EACxE,MAAM,IAAI,MAAM,oCAAoC,UAAU;CAChE;CAEA,OAAO,gBAAgB,MAAM,eAAe,IAAI,IAAI,GAAG,EACrD,cAAc,eAChB,CAAC;AACH;;;;;;;AAQA,SAAS,gBAEP,KACA,UACO;CACP,IAAI,IAAI,SAAS,cAAc,IAAI,SAAS,aAAa;EACvD,OAAO,MAAM,EAAE,SAAS,GAAG,wCAAwC;EACnE,OAAO;CACT;CAEA,IACE,IAAI,SAAS,8BACb,IAAI,WAAW,mBAAmB,KAElC,OAAO,MACL;EAAE;EAAU;CAAI,GAChB,gJACF;MACK,IAAI,IAAI,YAAY,qBAEzB,OAAO,MACL,EAAE,SAAS,GACX,qEACF;MAEA,OAAO,MAAM;EAAE;EAAU;CAAI,GAAG,qCAAqC;CAGvE,OAAO,IAAI,kBAAkB,KAAK,eAAe,EAAE;AACrD;AAEA,SAAS,iBACP,UAC2C;CAC3C,MAAM,EAAE,UAAU,UAAU,UAAUC,KAAe;EACnD,UAAU,eAAe;EACzB,KAAK;CACP,CAAC;CAGD,IAAI,CAAC,YAAY,CAAC,UAChB;CAGF,OAAO;EACL,aAAa;EACb,iBAAiB;EACjB,cAAc;CAChB;AACF"}
@@ -2,6 +2,7 @@ import { regEx } from "../../../util/regex.js";
2
2
  import { coerceString } from "../../../util/string.js";
3
3
  import { logger } from "../../../logger/index.js";
4
4
  import { parseUrl } from "../../../util/url.js";
5
+ import { buildCacheKey } from "../../../util/cache/package/key.js";
5
6
  import { id } from "../../versioning/hermit/index.js";
6
7
  import { withCache } from "../../../util/cache/package/with-cache.js";
7
8
  import { Datasource } from "../datasource.js";
@@ -67,7 +68,7 @@ var HermitDatasource = class HermitDatasource extends Datasource {
67
68
  getReleases(config) {
68
69
  return withCache({
69
70
  namespace: `datasource-${HermitDatasource.id}`,
70
- key: `getReleases:${config.registryUrl ?? ""}-${config.packageName}`,
71
+ key: buildCacheKey("getReleases", config.registryUrl, config.packageName),
71
72
  fallback: true
72
73
  }, () => this._getReleases(config));
73
74
  }
@@ -101,7 +102,7 @@ var HermitDatasource = class HermitDatasource extends Datasource {
101
102
  getHermitSearchManifest(u) {
102
103
  return withCache({
103
104
  namespace: `datasource-${HermitDatasource.id}`,
104
- key: `getHermitSearchManifest:${u.toString()}`
105
+ key: buildCacheKey("getHermitSearchManifest", u.toString())
105
106
  }, () => this._getHermitSearchManifest(u));
106
107
  }
107
108
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../lib/modules/datasource/hermit/index.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport type { GithubRestRelease } from '../../../util/github/types.ts';\nimport { getApiBaseUrl } from '../../../util/github/url.ts';\nimport { GithubHttp } from '../../../util/http/github.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { streamToString } from '../../../util/streams.ts';\nimport { coerceString } from '../../../util/string.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { id } from '../../versioning/hermit/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport type { HermitSearchResult } from './types.ts';\n\n/**\n * Hermit Datasource searches a given package from the specified `hermit-packages`\n * repository. It expects the search manifest to come from an asset `index.json` from\n * a release named index.\n */\nexport class HermitDatasource extends Datasource<GithubHttp> {\n static readonly id = 'hermit';\n\n override supportsCustomRegistry(_packageName: string): boolean {\n return true;\n }\n\n override readonly defaultVersioning = id;\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://github.com/cashapp/hermit-packages'];\n }\n\n override readonly sourceUrlSupport = 'release';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `Repository` field in the results.';\n\n pathRegex: RegExp;\n\n constructor() {\n super(HermitDatasource.id, new GithubHttp(id));\n this.pathRegex = regEx('^/(?<owner>[^/]+)/(?<repo>[^/]+)$');\n }\n\n private async _getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n logger.trace(`HermitDataSource.getReleases()`);\n\n if (!registryUrl) {\n logger.error('registryUrl must be supplied');\n return null;\n }\n\n const parsedUrl = parseUrl(registryUrl);\n if (parsedUrl === null) {\n logger.warn({ registryUrl }, 'invalid registryUrl given');\n return null;\n }\n\n if (!registryUrl.startsWith('https://github.com/')) {\n logger.warn({ registryUrl }, 'Only Github registryUrl is supported');\n return null;\n }\n\n const items = await this.getHermitSearchManifest(parsedUrl);\n\n if (items === null) {\n return null;\n }\n\n const res = items.find((i) => i.Name === packageName);\n\n if (!res) {\n logger.debug(\n `Could not find hermit package ${packageName} at URL ${registryUrl}`,\n );\n return null;\n }\n\n const sourceUrl = res.Repository;\n\n return {\n sourceUrl,\n releases: [\n ...res.Versions.map((v) => ({\n version: v,\n sourceUrl,\n })),\n ...res.Channels.map((v) => ({\n version: v,\n sourceUrl,\n })),\n ],\n };\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${HermitDatasource.id}`,\n key: `getReleases:${config.registryUrl ?? ''}-${config.packageName}`,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n /**\n * getHermitSearchManifest fetch the index.json from release\n * named index, parses it and returned the parsed JSON result\n */\n private async _getHermitSearchManifest(\n u: URL,\n ): Promise<HermitSearchResult[] | null> {\n const registryUrl = u.toString();\n const host = coerceString(u.host);\n const groups = this.pathRegex.exec(coerceString(u.pathname))?.groups;\n if (!groups) {\n logger.warn(\n { registryUrl },\n 'failed to get owner and repo from given url',\n );\n return null;\n }\n\n const { owner, repo } = groups;\n\n const apiBaseUrl = getApiBaseUrl(`https://${host}`);\n\n const indexRelease = await this.http.getJsonUnchecked<GithubRestRelease>(\n `${apiBaseUrl}repos/${owner}/${repo}/releases/tags/index`,\n );\n\n // finds asset with name index.json\n const asset = indexRelease.body.assets.find(\n (asset) => asset.name === 'index.json',\n );\n\n if (!asset) {\n logger.warn(\n { registryUrl },\n `can't find asset index.json in the given registryUrl`,\n );\n return null;\n }\n\n // stream down the content of index.json\n // Note: need to use stream here with\n // the accept header as octet-stream to\n // download asset from private github repository\n // see GithubDoc:\n // https://docs.github.com/en/rest/releases/assets#get-a-release-asset\n const indexContent = await streamToString(\n this.http.stream(asset.url, {\n headers: {\n accept: 'application/octet-stream',\n },\n }),\n );\n\n try {\n return JSON.parse(indexContent) as HermitSearchResult[];\n } catch {\n logger.warn('error parsing hermit search manifest from remote respond');\n }\n\n return null;\n }\n\n getHermitSearchManifest(u: URL): Promise<HermitSearchResult[] | null> {\n return withCache(\n {\n namespace: `datasource-${HermitDatasource.id}`,\n key: `getHermitSearchManifest:${u.toString()}`,\n },\n () => this._getHermitSearchManifest(u),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,IAAa,mBAAb,MAAa,yBAAyB,WAAuB;CAC3D,OAAgB,KAAK;CAErB,uBAAgC,cAA+B;EAC7D,OAAO;CACT;CAEA,oBAAsC;CAEtC,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,4CAA4C;CACtD;CAEA,mBAAqC;CACrC,gBACE;CAEF;CAEA,cAAc;EACZ,MAAM,iBAAiB,IAAI,IAAI,WAAW,EAAE,CAAC;EAC7C,KAAK,YAAY,MAAM,mCAAmC;CAC5D;CAEA,MAAc,aAAa,EACzB,aACA,eACmD;EACnD,OAAO,MAAM,gCAAgC;EAE7C,IAAI,CAAC,aAAa;GAChB,OAAO,MAAM,8BAA8B;GAC3C,OAAO;EACT;EAEA,MAAM,YAAY,SAAS,WAAW;EACtC,IAAI,cAAc,MAAM;GACtB,OAAO,KAAK,EAAE,YAAY,GAAG,2BAA2B;GACxD,OAAO;EACT;EAEA,IAAI,CAAC,YAAY,WAAW,qBAAqB,GAAG;GAClD,OAAO,KAAK,EAAE,YAAY,GAAG,sCAAsC;GACnE,OAAO;EACT;EAEA,MAAM,QAAQ,MAAM,KAAK,wBAAwB,SAAS;EAE1D,IAAI,UAAU,MACZ,OAAO;EAGT,MAAM,MAAM,MAAM,MAAM,MAAM,EAAE,SAAS,WAAW;EAEpD,IAAI,CAAC,KAAK;GACR,OAAO,MACL,iCAAiC,YAAY,UAAU,aACzD;GACA,OAAO;EACT;EAEA,MAAM,YAAY,IAAI;EAEtB,OAAO;GACL;GACA,UAAU,CACR,GAAG,IAAI,SAAS,KAAK,OAAO;IAC1B,SAAS;IACT;GACF,EAAE,GACF,GAAG,IAAI,SAAS,KAAK,OAAO;IAC1B,SAAS;IACT;GACF,EAAE,CACJ;EACF;CACF;CAEA,YAAY,QAA0D;EACpE,OAAO,UACL;GACE,WAAW,cAAc,iBAAiB;GAC1C,KAAK,eAAe,OAAO,eAAe,GAAG,GAAG,OAAO;GACvD,UAAU;EACZ,SACM,KAAK,aAAa,MAAM,CAChC;CACF;;;;;CAMA,MAAc,yBACZ,GACsC;EACtC,MAAM,cAAc,EAAE,SAAS;EAC/B,MAAM,OAAO,aAAa,EAAE,IAAI;EAChC,MAAM,SAAS,KAAK,UAAU,KAAK,aAAa,EAAE,QAAQ,CAAC,CAAC,EAAE;EAC9D,IAAI,CAAC,QAAQ;GACX,OAAO,KACL,EAAE,YAAY,GACd,6CACF;GACA,OAAO;EACT;EAEA,MAAM,EAAE,OAAO,SAAS;EAExB,MAAM,aAAa,cAAc,WAAW,MAAM;EAOlD,MAAM,SAAQ,MALa,KAAK,KAAK,iBACnC,GAAG,WAAW,QAAQ,MAAM,GAAG,KAAK,qBACtC,EAAA,CAG2B,KAAK,OAAO,MACpC,UAAU,MAAM,SAAS,YAC5B;EAEA,IAAI,CAAC,OAAO;GACV,OAAO,KACL,EAAE,YAAY,GACd,sDACF;GACA,OAAO;EACT;EAQA,MAAM,eAAe,MAAM,eACzB,KAAK,KAAK,OAAO,MAAM,KAAK,EAC1B,SAAS,EACP,QAAQ,2BACV,EACF,CAAC,CACH;EAEA,IAAI;GACF,OAAO,KAAK,MAAM,YAAY;EAChC,QAAQ;GACN,OAAO,KAAK,0DAA0D;EACxE;EAEA,OAAO;CACT;CAEA,wBAAwB,GAA8C;EACpE,OAAO,UACL;GACE,WAAW,cAAc,iBAAiB;GAC1C,KAAK,2BAA2B,EAAE,SAAS;EAC7C,SACM,KAAK,yBAAyB,CAAC,CACvC;CACF;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../lib/modules/datasource/hermit/index.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport { buildCacheKey } from '../../../util/cache/package/key.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport type { GithubRestRelease } from '../../../util/github/types.ts';\nimport { getApiBaseUrl } from '../../../util/github/url.ts';\nimport { GithubHttp } from '../../../util/http/github.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { streamToString } from '../../../util/streams.ts';\nimport { coerceString } from '../../../util/string.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { id } from '../../versioning/hermit/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport type { HermitSearchResult } from './types.ts';\n\n/**\n * Hermit Datasource searches a given package from the specified `hermit-packages`\n * repository. It expects the search manifest to come from an asset `index.json` from\n * a release named index.\n */\nexport class HermitDatasource extends Datasource<GithubHttp> {\n static readonly id = 'hermit';\n\n override supportsCustomRegistry(_packageName: string): boolean {\n return true;\n }\n\n override readonly defaultVersioning = id;\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://github.com/cashapp/hermit-packages'];\n }\n\n override readonly sourceUrlSupport = 'release';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `Repository` field in the results.';\n\n pathRegex: RegExp;\n\n constructor() {\n super(HermitDatasource.id, new GithubHttp(id));\n this.pathRegex = regEx('^/(?<owner>[^/]+)/(?<repo>[^/]+)$');\n }\n\n private async _getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n logger.trace(`HermitDataSource.getReleases()`);\n\n if (!registryUrl) {\n logger.error('registryUrl must be supplied');\n return null;\n }\n\n const parsedUrl = parseUrl(registryUrl);\n if (parsedUrl === null) {\n logger.warn({ registryUrl }, 'invalid registryUrl given');\n return null;\n }\n\n if (!registryUrl.startsWith('https://github.com/')) {\n logger.warn({ registryUrl }, 'Only Github registryUrl is supported');\n return null;\n }\n\n const items = await this.getHermitSearchManifest(parsedUrl);\n\n if (items === null) {\n return null;\n }\n\n const res = items.find((i) => i.Name === packageName);\n\n if (!res) {\n logger.debug(\n `Could not find hermit package ${packageName} at URL ${registryUrl}`,\n );\n return null;\n }\n\n const sourceUrl = res.Repository;\n\n return {\n sourceUrl,\n releases: [\n ...res.Versions.map((v) => ({\n version: v,\n sourceUrl,\n })),\n ...res.Channels.map((v) => ({\n version: v,\n sourceUrl,\n })),\n ],\n };\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${HermitDatasource.id}`,\n key: buildCacheKey(\n 'getReleases',\n config.registryUrl,\n config.packageName,\n ),\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n /**\n * getHermitSearchManifest fetch the index.json from release\n * named index, parses it and returned the parsed JSON result\n */\n private async _getHermitSearchManifest(\n u: URL,\n ): Promise<HermitSearchResult[] | null> {\n const registryUrl = u.toString();\n const host = coerceString(u.host);\n const groups = this.pathRegex.exec(coerceString(u.pathname))?.groups;\n if (!groups) {\n logger.warn(\n { registryUrl },\n 'failed to get owner and repo from given url',\n );\n return null;\n }\n\n const { owner, repo } = groups;\n\n const apiBaseUrl = getApiBaseUrl(`https://${host}`);\n\n const indexRelease = await this.http.getJsonUnchecked<GithubRestRelease>(\n `${apiBaseUrl}repos/${owner}/${repo}/releases/tags/index`,\n );\n\n // finds asset with name index.json\n const asset = indexRelease.body.assets.find(\n (asset) => asset.name === 'index.json',\n );\n\n if (!asset) {\n logger.warn(\n { registryUrl },\n `can't find asset index.json in the given registryUrl`,\n );\n return null;\n }\n\n // stream down the content of index.json\n // Note: need to use stream here with\n // the accept header as octet-stream to\n // download asset from private github repository\n // see GithubDoc:\n // https://docs.github.com/en/rest/releases/assets#get-a-release-asset\n const indexContent = await streamToString(\n this.http.stream(asset.url, {\n headers: {\n accept: 'application/octet-stream',\n },\n }),\n );\n\n try {\n return JSON.parse(indexContent) as HermitSearchResult[];\n } catch {\n logger.warn('error parsing hermit search manifest from remote respond');\n }\n\n return null;\n }\n\n getHermitSearchManifest(u: URL): Promise<HermitSearchResult[] | null> {\n return withCache(\n {\n namespace: `datasource-${HermitDatasource.id}`,\n key: buildCacheKey('getHermitSearchManifest', u.toString()),\n },\n () => this._getHermitSearchManifest(u),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,IAAa,mBAAb,MAAa,yBAAyB,WAAuB;CAC3D,OAAgB,KAAK;CAErB,uBAAgC,cAA+B;EAC7D,OAAO;CACT;CAEA,oBAAsC;CAEtC,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,4CAA4C;CACtD;CAEA,mBAAqC;CACrC,gBACE;CAEF;CAEA,cAAc;EACZ,MAAM,iBAAiB,IAAI,IAAI,WAAW,EAAE,CAAC;EAC7C,KAAK,YAAY,MAAM,mCAAmC;CAC5D;CAEA,MAAc,aAAa,EACzB,aACA,eACmD;EACnD,OAAO,MAAM,gCAAgC;EAE7C,IAAI,CAAC,aAAa;GAChB,OAAO,MAAM,8BAA8B;GAC3C,OAAO;EACT;EAEA,MAAM,YAAY,SAAS,WAAW;EACtC,IAAI,cAAc,MAAM;GACtB,OAAO,KAAK,EAAE,YAAY,GAAG,2BAA2B;GACxD,OAAO;EACT;EAEA,IAAI,CAAC,YAAY,WAAW,qBAAqB,GAAG;GAClD,OAAO,KAAK,EAAE,YAAY,GAAG,sCAAsC;GACnE,OAAO;EACT;EAEA,MAAM,QAAQ,MAAM,KAAK,wBAAwB,SAAS;EAE1D,IAAI,UAAU,MACZ,OAAO;EAGT,MAAM,MAAM,MAAM,MAAM,MAAM,EAAE,SAAS,WAAW;EAEpD,IAAI,CAAC,KAAK;GACR,OAAO,MACL,iCAAiC,YAAY,UAAU,aACzD;GACA,OAAO;EACT;EAEA,MAAM,YAAY,IAAI;EAEtB,OAAO;GACL;GACA,UAAU,CACR,GAAG,IAAI,SAAS,KAAK,OAAO;IAC1B,SAAS;IACT;GACF,EAAE,GACF,GAAG,IAAI,SAAS,KAAK,OAAO;IAC1B,SAAS;IACT;GACF,EAAE,CACJ;EACF;CACF;CAEA,YAAY,QAA0D;EACpE,OAAO,UACL;GACE,WAAW,cAAc,iBAAiB;GAC1C,KAAK,cACH,eACA,OAAO,aACP,OAAO,WACT;GACA,UAAU;EACZ,SACM,KAAK,aAAa,MAAM,CAChC;CACF;;;;;CAMA,MAAc,yBACZ,GACsC;EACtC,MAAM,cAAc,EAAE,SAAS;EAC/B,MAAM,OAAO,aAAa,EAAE,IAAI;EAChC,MAAM,SAAS,KAAK,UAAU,KAAK,aAAa,EAAE,QAAQ,CAAC,CAAC,EAAE;EAC9D,IAAI,CAAC,QAAQ;GACX,OAAO,KACL,EAAE,YAAY,GACd,6CACF;GACA,OAAO;EACT;EAEA,MAAM,EAAE,OAAO,SAAS;EAExB,MAAM,aAAa,cAAc,WAAW,MAAM;EAOlD,MAAM,SAAQ,MALa,KAAK,KAAK,iBACnC,GAAG,WAAW,QAAQ,MAAM,GAAG,KAAK,qBACtC,EAAA,CAG2B,KAAK,OAAO,MACpC,UAAU,MAAM,SAAS,YAC5B;EAEA,IAAI,CAAC,OAAO;GACV,OAAO,KACL,EAAE,YAAY,GACd,sDACF;GACA,OAAO;EACT;EAQA,MAAM,eAAe,MAAM,eACzB,KAAK,KAAK,OAAO,MAAM,KAAK,EAC1B,SAAS,EACP,QAAQ,2BACV,EACF,CAAC,CACH;EAEA,IAAI;GACF,OAAO,KAAK,MAAM,YAAY;EAChC,QAAQ;GACN,OAAO,KAAK,0DAA0D;EACxE;EAEA,OAAO;CACT;CAEA,wBAAwB,GAA8C;EACpE,OAAO,UACL;GACE,WAAW,cAAc,iBAAiB;GAC1C,KAAK,cAAc,2BAA2B,EAAE,SAAS,CAAC;EAC5D,SACM,KAAK,yBAAyB,CAAC,CACvC;CACF;AACF"}
@@ -1,5 +1,6 @@
1
1
  import { logger } from "../../../logger/index.js";
2
2
  import { joinUrlParts, parseUrl } from "../../../util/url.js";
3
+ import { buildCacheKey } from "../../../util/cache/package/key.js";
3
4
  import "../../versioning/hex/index.js";
4
5
  import { withCache } from "../../../util/cache/package/with-cache.js";
5
6
  import { Datasource } from "../datasource.js";
@@ -159,10 +160,10 @@ var HexDatasource = class HexDatasource extends Datasource {
159
160
  }
160
161
  getReleases(config) {
161
162
  const isDefault = HexDatasource.isDefaultRegistry(config.registryUrl);
162
- const key = isDefault ? config.packageName : `${config.registryUrl}:${config.packageName}`;
163
+ const registryUrl = isDefault ? defaultRegistryUrl : config.registryUrl;
163
164
  return withCache({
164
165
  namespace: `datasource-${HexDatasource.id}`,
165
- key,
166
+ key: buildCacheKey(registryUrl, config.packageName),
166
167
  cacheable: isDefault,
167
168
  fallback: true
168
169
  }, () => this._getReleases(config));
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["verifySignature"],"sources":["../../../../lib/modules/datasource/hex/index.ts"],"sourcesContent":["import { verify as verifySignature } from 'node:crypto';\nimport { promisify } from 'node:util';\nimport { gunzip } from 'node:zlib';\nimport { logger } from '../../../logger/index.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { joinUrlParts, parseUrl } from '../../../util/url.ts';\nimport * as hexVersioning from '../../versioning/hex/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\nimport { HexRelease } from './schema.ts';\nimport { Package } from './v2/package.ts';\nimport { Signed } from './v2/signed.ts';\n\nconst defaultRegistryUrl = 'https://hex.pm';\nconst defaultHexRepositoryUrl = 'https://repo.hex.pm';\nconst defaultHexRepositoryName = 'hexpm';\nconst defaultHexRepositoryHostname = parseUrl(\n defaultHexRepositoryUrl,\n)?.hostname;\nconst defaultHexPublicKey = `-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApqREcFDt5vV21JVe2QNB\nEdvzk6w36aNFhVGWN5toNJRjRJ6m4hIuG4KaXtDWVLjnvct6MYMfqhC79HAGwyF+\nIqR6Q6a5bbFSsImgBJwz1oadoVKD6ZNetAuCIK84cjMrEFRkELtEIPNHblCzUkkM\n3rS9+DPlnfG8hBvGi6tvQIuZmXGCxF/73hU0/MyGhbmEjIKRtG6b0sJYKelRLTPW\nXgK7s5pESgiwf2YC/2MGDXjAJfpfCd0RpLdvd4eRiXtVlE9qO9bND94E7PgQ/xqZ\nJ1i2xWFndWa6nfFnRxZmCStCOZWYYPlaxr+FZceFbpMwzTNs4g3d4tLNUcbKAIH4\n0wIDAQAB\n-----END PUBLIC KEY-----`;\nconst gunzipAsync = promisify(gunzip);\n\ninterface ParsedPackageName {\n hexPackageName: string;\n organizationName: string | null;\n organizationUrlPrefix: string;\n}\n\nfunction parsePackageName(packageName: string): ParsedPackageName {\n const [hexPackageName, organizationName] = packageName.split(':');\n const organizationUrlPrefix = organizationName\n ? `repos/${organizationName}/`\n : '';\n return {\n hexPackageName,\n organizationName: organizationName ?? null,\n organizationUrlPrefix,\n };\n}\n\nfunction getExpectedRepositoryName(\n registryUrl: string,\n organizationName: string | null,\n): string | null {\n if (organizationName) {\n return organizationName;\n }\n\n const hostname = parseUrl(registryUrl)?.hostname;\n return hostname === defaultHexRepositoryHostname\n ? defaultHexRepositoryName\n : null;\n}\n\nfunction isSignedPayloadValid(\n signed: Signed,\n publicKey: string,\n packageName: string,\n): boolean {\n if (!signed.signature?.length) {\n logger.warn({ packageName }, 'hex: missing signature in V2 response');\n return false;\n }\n\n try {\n return verifySignature(\n 'RSA-SHA512',\n signed.payload,\n publicKey,\n signed.signature,\n );\n } catch (err) {\n logger.warn({ err, packageName }, 'hex: invalid public key or signature');\n return false;\n }\n}\n\nfunction mapV2Releases(pkg: Package): Release[] {\n const releases: Release[] = [];\n\n for (const release of pkg.releases) {\n if (!release.version) {\n continue;\n }\n\n releases.push({\n version: release.version,\n ...(release.retired && { isDeprecated: true }),\n });\n }\n\n return releases;\n}\n\nexport class HexDatasource extends Datasource {\n static readonly id = 'hex';\n\n constructor() {\n super(HexDatasource.id);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return [defaultRegistryUrl];\n }\n\n override readonly defaultVersioning = hexVersioning.id;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined the `inserted_at` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `Github` field in the results.';\n\n private async getReleasesViaJsonApi({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore if -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const { hexPackageName, organizationUrlPrefix } =\n parsePackageName(packageName);\n\n const hexUrl = joinUrlParts(\n registryUrl,\n `/api/${organizationUrlPrefix}packages/${hexPackageName}`,\n );\n\n return this.fetchJsonOrNull(hexUrl, HexRelease);\n }\n\n private async getReleasesViaV2Protocol({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore if -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const { hexPackageName, organizationName, organizationUrlPrefix } =\n parsePackageName(packageName);\n\n const url = joinUrlParts(\n registryUrl,\n `/${organizationUrlPrefix}packages/${hexPackageName}`,\n );\n\n const { body } = await this.http.getBuffer(url);\n const decompressed = await gunzipAsync(body);\n const signed = Signed.decode(decompressed);\n\n const publicKey = await this.getPublicKey(registryUrl);\n if (publicKey && !isSignedPayloadValid(signed, publicKey, packageName)) {\n return null;\n }\n\n const pkg = Package.decode(signed.payload);\n\n if (pkg.name !== hexPackageName) {\n logger.warn(\n {\n packageName,\n registryUrl,\n expectedPackageName: hexPackageName,\n actualPackageName: pkg.name,\n },\n 'hex: V2 package name mismatch',\n );\n return null;\n }\n\n const expectedRepositoryName = getExpectedRepositoryName(\n registryUrl,\n organizationName,\n );\n if (expectedRepositoryName && pkg.repository !== expectedRepositoryName) {\n logger.warn(\n {\n packageName,\n registryUrl,\n expectedRepositoryName,\n actualRepositoryName: pkg.repository,\n },\n 'hex: V2 repository mismatch',\n );\n return null;\n }\n\n const releases = mapV2Releases(pkg);\n\n if (releases.length === 0) {\n return null;\n }\n\n return { releases };\n }\n\n private async getPublicKey(registryUrl: string): Promise<string | null> {\n if (registryUrl === defaultHexRepositoryUrl) {\n return defaultHexPublicKey;\n }\n\n const url = joinUrlParts(registryUrl, '/public_key');\n\n try {\n const { body } = await this.http.getText(url, {\n cacheProvider: memCacheProvider,\n });\n const publicKey = body.trim();\n\n if (publicKey.length === 0) {\n logger.warn({ registryUrl, url }, 'hex: empty V2 public key response');\n return null;\n }\n\n return publicKey;\n } catch (err) {\n logger.warn(\n { err, registryUrl, url },\n 'hex: failed to fetch V2 public key, falling back to unsigned payload',\n );\n return null;\n }\n }\n\n private async _getReleases(\n config: GetReleasesConfig,\n ): Promise<ReleaseResult | null> {\n if (HexDatasource.isDefaultRegistry(config.registryUrl)) {\n return this.getReleasesViaJsonApi(config);\n }\n\n try {\n return await this.getReleasesViaV2Protocol(config);\n } catch (err) {\n logger.warn(\n {\n registryUrl: config.registryUrl,\n packageName: config.packageName,\n err,\n },\n 'hex: error fetching package via V2 protocol',\n );\n this.handleGenericErrors(err as Error);\n }\n }\n\n private static isDefaultRegistry(registryUrl: string | undefined): boolean {\n return !registryUrl || registryUrl === defaultRegistryUrl;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n const isDefault = HexDatasource.isDefaultRegistry(config.registryUrl);\n const key = isDefault\n ? config.packageName\n : `${config.registryUrl}:${config.packageName}`;\n\n return withCache(\n {\n namespace: `datasource-${HexDatasource.id}`,\n key,\n cacheable: isDefault,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["verifySignature"],"sources":["../../../../lib/modules/datasource/hex/index.ts"],"sourcesContent":["import { verify as verifySignature } from 'node:crypto';\nimport { promisify } from 'node:util';\nimport { gunzip } from 'node:zlib';\nimport { logger } from '../../../logger/index.ts';\nimport { buildCacheKey } from '../../../util/cache/package/key.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { joinUrlParts, parseUrl } from '../../../util/url.ts';\nimport * as hexVersioning from '../../versioning/hex/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';\nimport { HexRelease } from './schema.ts';\nimport { Package } from './v2/package.ts';\nimport { Signed } from './v2/signed.ts';\n\nconst defaultRegistryUrl = 'https://hex.pm';\nconst defaultHexRepositoryUrl = 'https://repo.hex.pm';\nconst defaultHexRepositoryName = 'hexpm';\nconst defaultHexRepositoryHostname = parseUrl(\n defaultHexRepositoryUrl,\n)?.hostname;\nconst defaultHexPublicKey = `-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApqREcFDt5vV21JVe2QNB\nEdvzk6w36aNFhVGWN5toNJRjRJ6m4hIuG4KaXtDWVLjnvct6MYMfqhC79HAGwyF+\nIqR6Q6a5bbFSsImgBJwz1oadoVKD6ZNetAuCIK84cjMrEFRkELtEIPNHblCzUkkM\n3rS9+DPlnfG8hBvGi6tvQIuZmXGCxF/73hU0/MyGhbmEjIKRtG6b0sJYKelRLTPW\nXgK7s5pESgiwf2YC/2MGDXjAJfpfCd0RpLdvd4eRiXtVlE9qO9bND94E7PgQ/xqZ\nJ1i2xWFndWa6nfFnRxZmCStCOZWYYPlaxr+FZceFbpMwzTNs4g3d4tLNUcbKAIH4\n0wIDAQAB\n-----END PUBLIC KEY-----`;\nconst gunzipAsync = promisify(gunzip);\n\ninterface ParsedPackageName {\n hexPackageName: string;\n organizationName: string | null;\n organizationUrlPrefix: string;\n}\n\nfunction parsePackageName(packageName: string): ParsedPackageName {\n const [hexPackageName, organizationName] = packageName.split(':');\n const organizationUrlPrefix = organizationName\n ? `repos/${organizationName}/`\n : '';\n return {\n hexPackageName,\n organizationName: organizationName ?? null,\n organizationUrlPrefix,\n };\n}\n\nfunction getExpectedRepositoryName(\n registryUrl: string,\n organizationName: string | null,\n): string | null {\n if (organizationName) {\n return organizationName;\n }\n\n const hostname = parseUrl(registryUrl)?.hostname;\n return hostname === defaultHexRepositoryHostname\n ? defaultHexRepositoryName\n : null;\n}\n\nfunction isSignedPayloadValid(\n signed: Signed,\n publicKey: string,\n packageName: string,\n): boolean {\n if (!signed.signature?.length) {\n logger.warn({ packageName }, 'hex: missing signature in V2 response');\n return false;\n }\n\n try {\n return verifySignature(\n 'RSA-SHA512',\n signed.payload,\n publicKey,\n signed.signature,\n );\n } catch (err) {\n logger.warn({ err, packageName }, 'hex: invalid public key or signature');\n return false;\n }\n}\n\nfunction mapV2Releases(pkg: Package): Release[] {\n const releases: Release[] = [];\n\n for (const release of pkg.releases) {\n if (!release.version) {\n continue;\n }\n\n releases.push({\n version: release.version,\n ...(release.retired && { isDeprecated: true }),\n });\n }\n\n return releases;\n}\n\nexport class HexDatasource extends Datasource {\n static readonly id = 'hex';\n\n constructor() {\n super(HexDatasource.id);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return [defaultRegistryUrl];\n }\n\n override readonly defaultVersioning = hexVersioning.id;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined the `inserted_at` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `Github` field in the results.';\n\n private async getReleasesViaJsonApi({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore if -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const { hexPackageName, organizationUrlPrefix } =\n parsePackageName(packageName);\n\n const hexUrl = joinUrlParts(\n registryUrl,\n `/api/${organizationUrlPrefix}packages/${hexPackageName}`,\n );\n\n return this.fetchJsonOrNull(hexUrl, HexRelease);\n }\n\n private async getReleasesViaV2Protocol({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore if -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n const { hexPackageName, organizationName, organizationUrlPrefix } =\n parsePackageName(packageName);\n\n const url = joinUrlParts(\n registryUrl,\n `/${organizationUrlPrefix}packages/${hexPackageName}`,\n );\n\n const { body } = await this.http.getBuffer(url);\n const decompressed = await gunzipAsync(body);\n const signed = Signed.decode(decompressed);\n\n const publicKey = await this.getPublicKey(registryUrl);\n if (publicKey && !isSignedPayloadValid(signed, publicKey, packageName)) {\n return null;\n }\n\n const pkg = Package.decode(signed.payload);\n\n if (pkg.name !== hexPackageName) {\n logger.warn(\n {\n packageName,\n registryUrl,\n expectedPackageName: hexPackageName,\n actualPackageName: pkg.name,\n },\n 'hex: V2 package name mismatch',\n );\n return null;\n }\n\n const expectedRepositoryName = getExpectedRepositoryName(\n registryUrl,\n organizationName,\n );\n if (expectedRepositoryName && pkg.repository !== expectedRepositoryName) {\n logger.warn(\n {\n packageName,\n registryUrl,\n expectedRepositoryName,\n actualRepositoryName: pkg.repository,\n },\n 'hex: V2 repository mismatch',\n );\n return null;\n }\n\n const releases = mapV2Releases(pkg);\n\n if (releases.length === 0) {\n return null;\n }\n\n return { releases };\n }\n\n private async getPublicKey(registryUrl: string): Promise<string | null> {\n if (registryUrl === defaultHexRepositoryUrl) {\n return defaultHexPublicKey;\n }\n\n const url = joinUrlParts(registryUrl, '/public_key');\n\n try {\n const { body } = await this.http.getText(url, {\n cacheProvider: memCacheProvider,\n });\n const publicKey = body.trim();\n\n if (publicKey.length === 0) {\n logger.warn({ registryUrl, url }, 'hex: empty V2 public key response');\n return null;\n }\n\n return publicKey;\n } catch (err) {\n logger.warn(\n { err, registryUrl, url },\n 'hex: failed to fetch V2 public key, falling back to unsigned payload',\n );\n return null;\n }\n }\n\n private async _getReleases(\n config: GetReleasesConfig,\n ): Promise<ReleaseResult | null> {\n if (HexDatasource.isDefaultRegistry(config.registryUrl)) {\n return this.getReleasesViaJsonApi(config);\n }\n\n try {\n return await this.getReleasesViaV2Protocol(config);\n } catch (err) {\n logger.warn(\n {\n registryUrl: config.registryUrl,\n packageName: config.packageName,\n err,\n },\n 'hex: error fetching package via V2 protocol',\n );\n this.handleGenericErrors(err as Error);\n }\n }\n\n private static isDefaultRegistry(registryUrl: string | undefined): boolean {\n return !registryUrl || registryUrl === defaultRegistryUrl;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n const isDefault = HexDatasource.isDefaultRegistry(config.registryUrl);\n const registryUrl = isDefault ? defaultRegistryUrl : config.registryUrl;\n\n return withCache(\n {\n namespace: `datasource-${HexDatasource.id}`,\n key: buildCacheKey(registryUrl, config.packageName),\n cacheable: isDefault,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { regEx } from "../../../util/regex.js";
2
2
  import { logger } from "../../../logger/index.js";
3
+ import { buildCacheKey } from "../../../util/cache/package/key.js";
3
4
  import { ExternalHostError } from "../../../types/errors/external-host-error.js";
4
5
  import { id } from "../../versioning/semver/index.js";
5
6
  import { RequestError } from "../../../util/http/got.js";
@@ -56,7 +57,7 @@ var HexpmBobDatasource = class HexpmBobDatasource extends Datasource {
56
57
  }
57
58
  getReleases(config) {
58
59
  return this.cached({
59
- key: `${config.registryUrl}:${config.packageName}`,
60
+ key: buildCacheKey(config.registryUrl, config.packageName),
60
61
  fallback: true
61
62
  }, () => this.fetchReleases(config));
62
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["semverId","HttpError"],"sources":["../../../../lib/modules/datasource/hexpm-bob/index.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { id as semverId } from '../../versioning/semver/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport { datasource, defaultRegistryUrl } from './common.ts';\nimport type { PackageType } from './types.ts';\n\nexport class HexpmBobDatasource extends Datasource {\n static readonly id = datasource;\n\n constructor() {\n super(datasource);\n }\n\n override supportsCustomRegistry(_packageName: string): boolean {\n return true;\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return [defaultRegistryUrl];\n }\n\n override readonly defaultVersioning = semverId;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `buildDate` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'We use the URL https://github.com/elixir-lang/elixir.git for the `elixir` package and the https://github.com/erlang/otp.git URL for the `erlang` package.';\n\n private async fetchReleases({\n registryUrl,\n packageName,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n const packageType = HexpmBobDatasource.getPackageType(packageName);\n\n if (!packageType) {\n return null;\n }\n\n logger.trace(\n { registryUrl, packageName },\n `fetching hex.pm bob ${packageName} release`,\n );\n\n const url = `${registryUrl!}/builds/${packageName}/builds.txt`;\n\n const result: ReleaseResult = {\n releases: [],\n ...HexpmBobDatasource.getPackageDetails(packageType),\n };\n try {\n const { body } = await this.http.getText(url);\n result.releases = body\n .split('\\n')\n .map((line) => line.trim())\n .filter(isNonEmptyString)\n .map((line) => {\n const [version, gitRef, buildDate] = line.split(' ');\n\n return {\n gitRef,\n isStable: HexpmBobDatasource.isStable(version, packageType),\n releaseTimestamp: asTimestamp(buildDate),\n version: HexpmBobDatasource.cleanVersion(version, packageType),\n };\n });\n } catch (err) {\n if (err instanceof HttpError && err.response?.statusCode !== 404) {\n throw new ExternalHostError(err);\n }\n this.handleGenericErrors(err);\n }\n\n return result.releases.length > 0 ? result : null;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return this.cached(\n {\n key: `${config.registryUrl}:${config.packageName}`,\n fallback: true,\n },\n () => this.fetchReleases(config),\n );\n }\n\n private static getPackageType(packageName: string): PackageType | null {\n if (packageName === 'elixir') {\n return 'elixir';\n }\n if (regEx(/^otp\\/\\w+-\\d+\\.\\d+$/).test(packageName)) {\n return 'erlang';\n }\n return null;\n }\n\n private static cleanVersion(\n version: string,\n packageType: PackageType,\n ): string {\n switch (packageType) {\n case 'elixir':\n return version.replace(regEx(/^v/), '');\n case 'erlang':\n return version.replace(regEx(/^OTP-/), '');\n }\n }\n\n private static isStable(version: string, packageType: PackageType): boolean {\n switch (packageType) {\n case 'elixir':\n return regEx(/^v\\d+\\.\\d+\\.\\d+(?:$|-otp)/).test(version);\n case 'erlang':\n return version.startsWith('OTP-');\n }\n }\n\n private static getPackageDetails(\n packageType: PackageType,\n ): Omit<ReleaseResult, 'releases'> {\n switch (packageType) {\n case 'elixir':\n return {\n homepage: 'https://elixir-lang.org/',\n sourceUrl: 'https://github.com/elixir-lang/elixir.git',\n };\n case 'erlang':\n return {\n homepage: 'https://www.erlang.org/',\n sourceUrl: 'https://github.com/erlang/otp.git',\n };\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAYA,IAAa,qBAAb,MAAa,2BAA2B,WAAW;CACjD,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,UAAU;CAClB;CAEA,uBAAgC,cAA+B;EAC7D,OAAO;CACT;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,kBAAkB;CAC5B;CAEA,oBAAsCA;CAEtC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,cAAc,EAC1B,aACA,eACmD;EACnD,MAAM,cAAc,mBAAmB,eAAe,WAAW;EAEjE,IAAI,CAAC,aACH,OAAO;EAGT,OAAO,MACL;GAAE;GAAa;EAAY,GAC3B,uBAAuB,YAAY,SACrC;EAEA,MAAM,MAAM,GAAG,YAAa,UAAU,YAAY;EAElD,MAAM,SAAwB;GAC5B,UAAU,CAAC;GACX,GAAG,mBAAmB,kBAAkB,WAAW;EACrD;EACA,IAAI;GACF,MAAM,EAAE,SAAS,MAAM,KAAK,KAAK,QAAQ,GAAG;GAC5C,OAAO,WAAW,KACf,MAAM,IAAI,CAAC,CACX,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,CAC1B,OAAO,gBAAgB,CAAC,CACxB,KAAK,SAAS;IACb,MAAM,CAAC,SAAS,QAAQ,aAAa,KAAK,MAAM,GAAG;IAEnD,OAAO;KACL;KACA,UAAU,mBAAmB,SAAS,SAAS,WAAW;KAC1D,kBAAkB,YAAY,SAAS;KACvC,SAAS,mBAAmB,aAAa,SAAS,WAAW;IAC/D;GACF,CAAC;EACL,SAAS,KAAK;GACZ,IAAI,eAAeC,gBAAa,IAAI,UAAU,eAAe,KAC3D,MAAM,IAAI,kBAAkB,GAAG;GAEjC,KAAK,oBAAoB,GAAG;EAC9B;EAEA,OAAO,OAAO,SAAS,SAAS,IAAI,SAAS;CAC/C;CAEA,YAAY,QAA0D;EACpE,OAAO,KAAK,OACV;GACE,KAAK,GAAG,OAAO,YAAY,GAAG,OAAO;GACrC,UAAU;EACZ,SACM,KAAK,cAAc,MAAM,CACjC;CACF;CAEA,OAAe,eAAe,aAAyC;EACrE,IAAI,gBAAgB,UAClB,OAAO;EAET,IAAI,MAAM,qBAAqB,CAAC,CAAC,KAAK,WAAW,GAC/C,OAAO;EAET,OAAO;CACT;CAEA,OAAe,aACb,SACA,aACQ;EACR,QAAQ,aAAR;GACE,KAAK,UACH,OAAO,QAAQ,QAAQ,MAAM,IAAI,GAAG,EAAE;GACxC,KAAK,UACH,OAAO,QAAQ,QAAQ,MAAM,OAAO,GAAG,EAAE;EAC7C;CACF;CAEA,OAAe,SAAS,SAAiB,aAAmC;EAC1E,QAAQ,aAAR;GACE,KAAK,UACH,OAAO,MAAM,2BAA2B,CAAC,CAAC,KAAK,OAAO;GACxD,KAAK,UACH,OAAO,QAAQ,WAAW,MAAM;EACpC;CACF;CAEA,OAAe,kBACb,aACiC;EACjC,QAAQ,aAAR;GACE,KAAK,UACH,OAAO;IACL,UAAU;IACV,WAAW;GACb;GACF,KAAK,UACH,OAAO;IACL,UAAU;IACV,WAAW;GACb;EACJ;CACF;AACF"}
1
+ {"version":3,"file":"index.js","names":["semverId","HttpError"],"sources":["../../../../lib/modules/datasource/hexpm-bob/index.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { buildCacheKey } from '../../../util/cache/package/key.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { id as semverId } from '../../versioning/semver/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport { datasource, defaultRegistryUrl } from './common.ts';\nimport type { PackageType } from './types.ts';\n\nexport class HexpmBobDatasource extends Datasource {\n static readonly id = datasource;\n\n constructor() {\n super(datasource);\n }\n\n override supportsCustomRegistry(_packageName: string): boolean {\n return true;\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return [defaultRegistryUrl];\n }\n\n override readonly defaultVersioning = semverId;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `buildDate` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'We use the URL https://github.com/elixir-lang/elixir.git for the `elixir` package and the https://github.com/erlang/otp.git URL for the `erlang` package.';\n\n private async fetchReleases({\n registryUrl,\n packageName,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n const packageType = HexpmBobDatasource.getPackageType(packageName);\n\n if (!packageType) {\n return null;\n }\n\n logger.trace(\n { registryUrl, packageName },\n `fetching hex.pm bob ${packageName} release`,\n );\n\n const url = `${registryUrl!}/builds/${packageName}/builds.txt`;\n\n const result: ReleaseResult = {\n releases: [],\n ...HexpmBobDatasource.getPackageDetails(packageType),\n };\n try {\n const { body } = await this.http.getText(url);\n result.releases = body\n .split('\\n')\n .map((line) => line.trim())\n .filter(isNonEmptyString)\n .map((line) => {\n const [version, gitRef, buildDate] = line.split(' ');\n\n return {\n gitRef,\n isStable: HexpmBobDatasource.isStable(version, packageType),\n releaseTimestamp: asTimestamp(buildDate),\n version: HexpmBobDatasource.cleanVersion(version, packageType),\n };\n });\n } catch (err) {\n if (err instanceof HttpError && err.response?.statusCode !== 404) {\n throw new ExternalHostError(err);\n }\n this.handleGenericErrors(err);\n }\n\n return result.releases.length > 0 ? result : null;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return this.cached(\n {\n key: buildCacheKey(config.registryUrl, config.packageName),\n fallback: true,\n },\n () => this.fetchReleases(config),\n );\n }\n\n private static getPackageType(packageName: string): PackageType | null {\n if (packageName === 'elixir') {\n return 'elixir';\n }\n if (regEx(/^otp\\/\\w+-\\d+\\.\\d+$/).test(packageName)) {\n return 'erlang';\n }\n return null;\n }\n\n private static cleanVersion(\n version: string,\n packageType: PackageType,\n ): string {\n switch (packageType) {\n case 'elixir':\n return version.replace(regEx(/^v/), '');\n case 'erlang':\n return version.replace(regEx(/^OTP-/), '');\n }\n }\n\n private static isStable(version: string, packageType: PackageType): boolean {\n switch (packageType) {\n case 'elixir':\n return regEx(/^v\\d+\\.\\d+\\.\\d+(?:$|-otp)/).test(version);\n case 'erlang':\n return version.startsWith('OTP-');\n }\n }\n\n private static getPackageDetails(\n packageType: PackageType,\n ): Omit<ReleaseResult, 'releases'> {\n switch (packageType) {\n case 'elixir':\n return {\n homepage: 'https://elixir-lang.org/',\n sourceUrl: 'https://github.com/elixir-lang/elixir.git',\n };\n case 'erlang':\n return {\n homepage: 'https://www.erlang.org/',\n sourceUrl: 'https://github.com/erlang/otp.git',\n };\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAaA,IAAa,qBAAb,MAAa,2BAA2B,WAAW;CACjD,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,UAAU;CAClB;CAEA,uBAAgC,cAA+B;EAC7D,OAAO;CACT;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,kBAAkB;CAC5B;CAEA,oBAAsCA;CAEtC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,cAAc,EAC1B,aACA,eACmD;EACnD,MAAM,cAAc,mBAAmB,eAAe,WAAW;EAEjE,IAAI,CAAC,aACH,OAAO;EAGT,OAAO,MACL;GAAE;GAAa;EAAY,GAC3B,uBAAuB,YAAY,SACrC;EAEA,MAAM,MAAM,GAAG,YAAa,UAAU,YAAY;EAElD,MAAM,SAAwB;GAC5B,UAAU,CAAC;GACX,GAAG,mBAAmB,kBAAkB,WAAW;EACrD;EACA,IAAI;GACF,MAAM,EAAE,SAAS,MAAM,KAAK,KAAK,QAAQ,GAAG;GAC5C,OAAO,WAAW,KACf,MAAM,IAAI,CAAC,CACX,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,CAC1B,OAAO,gBAAgB,CAAC,CACxB,KAAK,SAAS;IACb,MAAM,CAAC,SAAS,QAAQ,aAAa,KAAK,MAAM,GAAG;IAEnD,OAAO;KACL;KACA,UAAU,mBAAmB,SAAS,SAAS,WAAW;KAC1D,kBAAkB,YAAY,SAAS;KACvC,SAAS,mBAAmB,aAAa,SAAS,WAAW;IAC/D;GACF,CAAC;EACL,SAAS,KAAK;GACZ,IAAI,eAAeC,gBAAa,IAAI,UAAU,eAAe,KAC3D,MAAM,IAAI,kBAAkB,GAAG;GAEjC,KAAK,oBAAoB,GAAG;EAC9B;EAEA,OAAO,OAAO,SAAS,SAAS,IAAI,SAAS;CAC/C;CAEA,YAAY,QAA0D;EACpE,OAAO,KAAK,OACV;GACE,KAAK,cAAc,OAAO,aAAa,OAAO,WAAW;GACzD,UAAU;EACZ,SACM,KAAK,cAAc,MAAM,CACjC;CACF;CAEA,OAAe,eAAe,aAAyC;EACrE,IAAI,gBAAgB,UAClB,OAAO;EAET,IAAI,MAAM,qBAAqB,CAAC,CAAC,KAAK,WAAW,GAC/C,OAAO;EAET,OAAO;CACT;CAEA,OAAe,aACb,SACA,aACQ;EACR,QAAQ,aAAR;GACE,KAAK,UACH,OAAO,QAAQ,QAAQ,MAAM,IAAI,GAAG,EAAE;GACxC,KAAK,UACH,OAAO,QAAQ,QAAQ,MAAM,OAAO,GAAG,EAAE;EAC7C;CACF;CAEA,OAAe,SAAS,SAAiB,aAAmC;EAC1E,QAAQ,aAAR;GACE,KAAK,UACH,OAAO,MAAM,2BAA2B,CAAC,CAAC,KAAK,OAAO;GACxD,KAAK,UACH,OAAO,QAAQ,WAAW,MAAM;EACpC;CACF;CAEA,OAAe,kBACb,aACiC;EACjC,QAAQ,aAAR;GACE,KAAK,UACH,OAAO;IACL,UAAU;IACV,WAAW;GACb;GACF,KAAK,UACH,OAAO;IACL,UAAU;IACV,WAAW;GACb;EACJ;CACF;AACF"}
@@ -9,6 +9,7 @@ import { trimTrailingSlash } from "../../util/url.js";
9
9
  import { ATTR_RENOVATE_DATASOURCE, ATTR_RENOVATE_PACKAGE_NAME, ATTR_RENOVATE_REGISTRY_URL } from "../../instrumentation/types.js";
10
10
  import { DatasourceCacheStats } from "../../util/stats.js";
11
11
  import { instrument } from "../../instrumentation/index.js";
12
+ import { buildCacheKey } from "../../util/cache/package/key.js";
12
13
  import { ExternalHostError } from "../../types/errors/external-host-error.js";
13
14
  import { filterMap } from "../../util/filter-map.js";
14
15
  import { get as get$1 } from "../versioning/index.js";
@@ -72,7 +73,7 @@ function logError(datasource, packageName, err) {
72
73
  }
73
74
  async function getRegistryReleases(datasource, config, registryUrl) {
74
75
  const cacheNamespace = `datasource-releases-${datasource.id}`;
75
- const cacheKey = `${registryUrl}:${config.packageName}`;
76
+ const cacheKey = buildCacheKey(registryUrl, config.packageName);
76
77
  const cacheEnabled = !!datasource.caching;
77
78
  const cacheForced = GlobalConfig.get("cachePrivatePackages");
78
79
  if (cacheEnabled || cacheForced) {
@@ -269,11 +270,11 @@ async function fetchReleases(config) {
269
270
  }
270
271
  function fetchCachedReleases(config) {
271
272
  const { datasource, packageName, registryUrls } = config;
272
- const cacheKey = `datasource-mem:releases:${datasource}:${packageName}:${config.registryStrategy}:${safeStringify([
273
+ const cacheKey = buildCacheKey("datasource-mem", "releases", datasource, packageName, config.registryStrategy, safeStringify([
273
274
  registryUrls,
274
275
  config.defaultRegistryUrls,
275
276
  config.additionalRegistryUrls
276
- ])}`;
277
+ ]));
277
278
  const cachedResult = get(cacheKey);
278
279
  // istanbul ignore if
279
280
  if (cachedResult !== void 0) return cachedResult;