renovate 44.149.0 → 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 (163) hide show
  1. package/dist/config/options/index.js +1 -1
  2. package/dist/config/options/index.js.map +1 -1
  3. package/dist/config/presets/index.js +2 -1
  4. package/dist/config/presets/index.js.map +1 -1
  5. package/dist/global-config-option-defaults.generated.js +1 -1
  6. package/dist/global-config-option-defaults.generated.js.map +1 -1
  7. package/dist/modules/datasource/artifactory/index.js +2 -1
  8. package/dist/modules/datasource/artifactory/index.js.map +1 -1
  9. package/dist/modules/datasource/aws-eks-addon/index.js +6 -5
  10. package/dist/modules/datasource/aws-eks-addon/index.js.map +1 -1
  11. package/dist/modules/datasource/aws-machine-image/index.js +4 -3
  12. package/dist/modules/datasource/aws-machine-image/index.js.map +1 -1
  13. package/dist/modules/datasource/aws-rds/index.js +2 -1
  14. package/dist/modules/datasource/aws-rds/index.js.map +1 -1
  15. package/dist/modules/datasource/azure-bicep-resource/index.js +2 -1
  16. package/dist/modules/datasource/azure-bicep-resource/index.js.map +1 -1
  17. package/dist/modules/datasource/bazel/index.js +2 -1
  18. package/dist/modules/datasource/bazel/index.js.map +1 -1
  19. package/dist/modules/datasource/bitrise/index.js +2 -1
  20. package/dist/modules/datasource/bitrise/index.js.map +1 -1
  21. package/dist/modules/datasource/buildpacks-registry/index.js +2 -1
  22. package/dist/modules/datasource/buildpacks-registry/index.js.map +1 -1
  23. package/dist/modules/datasource/cdnjs/index.js +3 -2
  24. package/dist/modules/datasource/cdnjs/index.js.map +1 -1
  25. package/dist/modules/datasource/conan/index.js +3 -2
  26. package/dist/modules/datasource/conan/index.js.map +1 -1
  27. package/dist/modules/datasource/conda/index.js +2 -1
  28. package/dist/modules/datasource/conda/index.js.map +1 -1
  29. package/dist/modules/datasource/cpan/index.js +1 -1
  30. package/dist/modules/datasource/cpan/index.js.map +1 -1
  31. package/dist/modules/datasource/crate/index.js +17 -9
  32. package/dist/modules/datasource/crate/index.js.map +1 -1
  33. package/dist/modules/datasource/deb/index.js +3 -2
  34. package/dist/modules/datasource/deb/index.js.map +1 -1
  35. package/dist/modules/datasource/deno/index.js +4 -3
  36. package/dist/modules/datasource/deno/index.js.map +1 -1
  37. package/dist/modules/datasource/docker/index.js +9 -9
  38. package/dist/modules/datasource/docker/index.js.map +1 -1
  39. package/dist/modules/datasource/dotnet-version/index.js +2 -1
  40. package/dist/modules/datasource/dotnet-version/index.js.map +1 -1
  41. package/dist/modules/datasource/elm-package/index.js +2 -1
  42. package/dist/modules/datasource/elm-package/index.js.map +1 -1
  43. package/dist/modules/datasource/endoflife-date/index.js +2 -1
  44. package/dist/modules/datasource/endoflife-date/index.js.map +1 -1
  45. package/dist/modules/datasource/galaxy-collection/index.js +3 -2
  46. package/dist/modules/datasource/galaxy-collection/index.js.map +1 -1
  47. package/dist/modules/datasource/git-host-tags.js +6 -5
  48. package/dist/modules/datasource/git-host-tags.js.map +1 -1
  49. package/dist/modules/datasource/gitea-tags/base.js +5 -4
  50. package/dist/modules/datasource/gitea-tags/base.js.map +1 -1
  51. package/dist/modules/datasource/gitea-tags/util.js +2 -5
  52. package/dist/modules/datasource/gitea-tags/util.js.map +1 -1
  53. package/dist/modules/datasource/github-digest/index.js +3 -5
  54. package/dist/modules/datasource/github-digest/index.js.map +1 -1
  55. package/dist/modules/datasource/github-release-attachments/index.js +3 -2
  56. package/dist/modules/datasource/github-release-attachments/index.js.map +1 -1
  57. package/dist/modules/datasource/gitlab-packages/index.js +2 -1
  58. package/dist/modules/datasource/gitlab-packages/index.js.map +1 -1
  59. package/dist/modules/datasource/gitlab-releases/index.js +2 -1
  60. package/dist/modules/datasource/gitlab-releases/index.js.map +1 -1
  61. package/dist/modules/datasource/gitlab-tags/index.js +3 -2
  62. package/dist/modules/datasource/gitlab-tags/index.js.map +1 -1
  63. package/dist/modules/datasource/glasskube-packages/index.js +2 -1
  64. package/dist/modules/datasource/glasskube-packages/index.js.map +1 -1
  65. package/dist/modules/datasource/go/goproxy-parser.js +3 -2
  66. package/dist/modules/datasource/go/goproxy-parser.js.map +1 -1
  67. package/dist/modules/datasource/go/index.js +4 -3
  68. package/dist/modules/datasource/go/index.js.map +1 -1
  69. package/dist/modules/datasource/go/releases-goproxy.js +6 -3
  70. package/dist/modules/datasource/go/releases-goproxy.js.map +1 -1
  71. package/dist/modules/datasource/go/timestamp-cache.js +3 -1
  72. package/dist/modules/datasource/go/timestamp-cache.js.map +1 -1
  73. package/dist/modules/datasource/golang-version/index.js +1 -1
  74. package/dist/modules/datasource/golang-version/index.js.map +1 -1
  75. package/dist/modules/datasource/gradle-version/index.js +1 -1
  76. package/dist/modules/datasource/gradle-version/index.js.map +1 -1
  77. package/dist/modules/datasource/helm/index.js +2 -1
  78. package/dist/modules/datasource/helm/index.js.map +1 -1
  79. package/dist/modules/datasource/hermit/index.js +3 -2
  80. package/dist/modules/datasource/hermit/index.js.map +1 -1
  81. package/dist/modules/datasource/hex/index.js +3 -2
  82. package/dist/modules/datasource/hex/index.js.map +1 -1
  83. package/dist/modules/datasource/hexpm-bob/index.js +2 -1
  84. package/dist/modules/datasource/hexpm-bob/index.js.map +1 -1
  85. package/dist/modules/datasource/index.js +4 -3
  86. package/dist/modules/datasource/index.js.map +1 -1
  87. package/dist/modules/datasource/java-version/index.js +2 -1
  88. package/dist/modules/datasource/java-version/index.js.map +1 -1
  89. package/dist/modules/datasource/jsr/index.js +2 -1
  90. package/dist/modules/datasource/jsr/index.js.map +1 -1
  91. package/dist/modules/datasource/maven/index.js +2 -1
  92. package/dist/modules/datasource/maven/index.js.map +1 -1
  93. package/dist/modules/datasource/nextcloud/index.js +2 -1
  94. package/dist/modules/datasource/nextcloud/index.js.map +1 -1
  95. package/dist/modules/datasource/node-version/index.js +1 -1
  96. package/dist/modules/datasource/node-version/index.js.map +1 -1
  97. package/dist/modules/datasource/nuget/v3.js +3 -2
  98. package/dist/modules/datasource/nuget/v3.js.map +1 -1
  99. package/dist/modules/datasource/orb/index.js +2 -1
  100. package/dist/modules/datasource/orb/index.js.map +1 -1
  101. package/dist/modules/datasource/packagist/index.js +4 -3
  102. package/dist/modules/datasource/packagist/index.js.map +1 -1
  103. package/dist/modules/datasource/pod/index.js +2 -1
  104. package/dist/modules/datasource/pod/index.js.map +1 -1
  105. package/dist/modules/datasource/python-version/index.js +1 -1
  106. package/dist/modules/datasource/python-version/index.js.map +1 -1
  107. package/dist/modules/datasource/repology/index.js +2 -1
  108. package/dist/modules/datasource/repology/index.js.map +1 -1
  109. package/dist/modules/datasource/rpm/index.js +2 -1
  110. package/dist/modules/datasource/rpm/index.js.map +1 -1
  111. package/dist/modules/datasource/rubygems/index.js +2 -1
  112. package/dist/modules/datasource/rubygems/index.js.map +1 -1
  113. package/dist/modules/datasource/rubygems/metadata-cache.js +2 -1
  114. package/dist/modules/datasource/rubygems/metadata-cache.js.map +1 -1
  115. package/dist/modules/datasource/sbt-package/index.js +11 -10
  116. package/dist/modules/datasource/sbt-package/index.js.map +1 -1
  117. package/dist/modules/datasource/terraform-module/index.js +2 -1
  118. package/dist/modules/datasource/terraform-module/index.js.map +1 -1
  119. package/dist/modules/datasource/terraform-provider/index.js +6 -5
  120. package/dist/modules/datasource/terraform-provider/index.js.map +1 -1
  121. package/dist/modules/datasource/unity3d/index.js +2 -1
  122. package/dist/modules/datasource/unity3d/index.js.map +1 -1
  123. package/dist/modules/datasource/unity3d-packages/index.js +2 -1
  124. package/dist/modules/datasource/unity3d-packages/index.js.map +1 -1
  125. package/dist/modules/manager/bazel/parser.js +3 -1
  126. package/dist/modules/manager/bazel/parser.js.map +1 -1
  127. package/dist/modules/manager/github-actions/extract.js +2 -1
  128. package/dist/modules/manager/github-actions/extract.js.map +1 -1
  129. package/dist/modules/manager/terraform/lockfile/hash.js +2 -1
  130. package/dist/modules/manager/terraform/lockfile/hash.js.map +1 -1
  131. package/dist/modules/platform/bitbucket/pr-cache.js +3 -2
  132. package/dist/modules/platform/bitbucket/pr-cache.js.map +1 -1
  133. package/dist/modules/platform/bitbucket-server/pr-cache.js +3 -2
  134. package/dist/modules/platform/bitbucket-server/pr-cache.js.map +1 -1
  135. package/dist/modules/platform/gitea/pr-cache.js +7 -6
  136. package/dist/modules/platform/gitea/pr-cache.js.map +1 -1
  137. package/dist/modules/platform/gitlab/pr-cache.js +3 -2
  138. package/dist/modules/platform/gitlab/pr-cache.js.map +1 -1
  139. package/dist/util/cache/package/index.js +1 -1
  140. package/dist/util/cache/package/key.js +8 -1
  141. package/dist/util/cache/package/key.js.map +1 -1
  142. package/dist/util/cache/package/with-cache.js +2 -1
  143. package/dist/util/cache/package/with-cache.js.map +1 -1
  144. package/dist/util/exec/containerbase.js +2 -1
  145. package/dist/util/exec/containerbase.js.map +1 -1
  146. package/dist/util/github/graphql/cache-strategies/memory-cache-strategy.js +2 -1
  147. package/dist/util/github/graphql/cache-strategies/memory-cache-strategy.js.map +1 -1
  148. package/dist/util/github/graphql/datasource-fetcher.js +5 -8
  149. package/dist/util/github/graphql/datasource-fetcher.js.map +1 -1
  150. package/dist/util/http/cache/memory-http-cache-provider.js +2 -1
  151. package/dist/util/http/cache/memory-http-cache-provider.js.map +1 -1
  152. package/dist/util/http/cache/package-http-cache-provider.js +2 -1
  153. package/dist/util/http/cache/package-http-cache-provider.js.map +1 -1
  154. package/dist/util/jsonata.js +2 -1
  155. package/dist/util/jsonata.js.map +1 -1
  156. package/dist/util/merge-confidence/index.js +10 -7
  157. package/dist/util/merge-confidence/index.js.map +1 -1
  158. package/dist/workers/repository/update/pr/changelog/release-notes.js +4 -5
  159. package/dist/workers/repository/update/pr/changelog/release-notes.js.map +1 -1
  160. package/dist/workers/repository/update/pr/changelog/source.js +2 -1
  161. package/dist/workers/repository/update/pr/changelog/source.js.map +1 -1
  162. package/package.json +2 -2
  163. package/renovate-schema.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"pr-cache.js","names":["memCache.get"],"sources":["../../../../lib/modules/platform/bitbucket-server/pr-cache.ts"],"sourcesContent":["import { isNullOrUndefined, isPlainObject, isString } from '@sindresorhus/is';\nimport { dequal } from 'dequal';\nimport { DateTime } from 'luxon';\nimport { logger } from '../../../logger/index.ts';\nimport * as memCache from '../../../util/cache/memory/index.ts';\nimport { getCache } from '../../../util/cache/repository/index.ts';\nimport type { BitbucketServerHttp } from '../../../util/http/bitbucket-server.ts';\nimport { getQueryString } from '../../../util/url.ts';\nimport type { BbsPr, BbsPrCacheData, BbsRestPr } from './types.ts';\nimport { prInfo } from './utils.ts';\n\n/* v8 ignore next -- one-off cache-schema migration shim, only runs against real legacy repo caches */\nfunction migrateBitbucketServerCache(platform: unknown): void {\n if (!isPlainObject(platform)) {\n return;\n }\n\n if (!isPlainObject(platform.bitbucketServer)) {\n return;\n }\n\n platform['bitbucket-server'] = platform.bitbucketServer;\n delete platform.bitbucketServer;\n}\n\nexport class BbsPrCache {\n private cache: BbsPrCacheData;\n private items: BbsPr[] = [];\n private projectKey: string;\n private repo: string;\n private readonly ignorePrAuthor: boolean;\n private author: string | null;\n\n private constructor(\n projectKey: string,\n repo: string,\n ignorePrAuthor: boolean,\n author: string | null,\n ) {\n this.projectKey = projectKey;\n this.repo = repo;\n this.ignorePrAuthor = ignorePrAuthor;\n this.author = author;\n const repoCache = getCache();\n repoCache.platform ??= {};\n migrateBitbucketServerCache(repoCache.platform);\n repoCache.platform['bitbucket-server'] ??= {};\n let pullRequestCache = repoCache.platform['bitbucket-server']\n .pullRequestsCache as BbsPrCacheData;\n if (\n isNullOrUndefined(pullRequestCache) ||\n pullRequestCache.author !== author\n ) {\n pullRequestCache = {\n items: {},\n updatedDate: null,\n author,\n };\n }\n repoCache.platform['bitbucket-server'].pullRequestsCache = pullRequestCache;\n this.cache = pullRequestCache;\n this.updateItems();\n }\n\n private static async init(\n http: BitbucketServerHttp,\n projectKey: string,\n repo: string,\n ignorePrAuthor: boolean,\n author: string | null,\n ): Promise<BbsPrCache> {\n const res = new BbsPrCache(projectKey, repo, ignorePrAuthor, author);\n const isSynced = memCache.get<true | undefined>('bbs-pr-cache-synced');\n\n // v8 ignore next -- TODO: add test #40625\n if (!isSynced) {\n await res.sync(http);\n memCache.set('bbs-pr-cache-synced', true);\n }\n\n return res;\n }\n\n private getPrs(): BbsPr[] {\n return this.items;\n }\n\n static async getPrs(\n http: BitbucketServerHttp,\n projectKey: string,\n repo: string,\n ignorePrAuthor: boolean,\n author: string,\n ): Promise<BbsPr[]> {\n const prCache = await BbsPrCache.init(\n http,\n projectKey,\n repo,\n ignorePrAuthor,\n author,\n );\n return prCache.getPrs();\n }\n\n private setPr(item: BbsPr): void {\n this.cache.items[item.number] = item;\n this.updateItems();\n }\n\n static async setPr(\n http: BitbucketServerHttp,\n projectKey: string,\n repo: string,\n ignorePrAuthor: boolean,\n author: string,\n item: BbsPr,\n ): Promise<void> {\n const prCache = await BbsPrCache.init(\n http,\n projectKey,\n repo,\n ignorePrAuthor,\n author,\n );\n prCache.setPr(item);\n }\n\n private reconcile(rawItems: BbsRestPr[]): boolean {\n logger.debug('reconciled');\n const { items } = this.cache;\n let { updatedDate } = this.cache;\n const cacheTime = updatedDate ? DateTime.fromMillis(updatedDate) : null;\n\n let needNextPage = true;\n\n for (const rawItem of rawItems) {\n const id = rawItem.id;\n\n const newItem = prInfo(rawItem);\n\n const oldItem = items[id];\n if (dequal(oldItem, newItem)) {\n needNextPage = false;\n continue;\n }\n\n items[id] = newItem;\n\n const itemTime = DateTime.fromMillis(rawItem.updatedDate);\n if (!cacheTime || itemTime > cacheTime) {\n updatedDate = rawItem.updatedDate;\n }\n }\n\n this.cache.updatedDate = updatedDate;\n\n return needNextPage;\n }\n\n private async sync(http: BitbucketServerHttp): Promise<BbsPrCache> {\n const searchParams: Record<string, string> = {\n state: 'ALL',\n limit: this.items.length ? '20' : '100',\n };\n if (!this.ignorePrAuthor && isString(this.author)) {\n searchParams['role.1'] = 'AUTHOR';\n searchParams['username.1'] = this.author;\n }\n let query: string | null = getQueryString(searchParams);\n\n while (query) {\n const res = await http.getJsonUnchecked<{\n nextPageStart: string;\n values: BbsRestPr[];\n }>(\n `./rest/api/1.0/projects/${this.projectKey}/repos/${this.repo}/pull-requests?${query}`,\n {\n memCache: false,\n },\n );\n\n const needNextPage = this.reconcile(res.body.values);\n if (!needNextPage) {\n break;\n }\n\n if (res.body.nextPageStart) {\n searchParams.start = res.body.nextPageStart.toString();\n } else {\n query = null;\n }\n }\n\n this.updateItems();\n\n return this;\n }\n\n /**\n * Ensure the pr cache starts with the most recent PRs.\n * JavaScript ensures that the cache is sorted by PR number.\n */\n private updateItems(): void {\n this.items = Object.values(this.cache.items).reverse();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pr-cache.js","names":["memCache.get"],"sources":["../../../../lib/modules/platform/bitbucket-server/pr-cache.ts"],"sourcesContent":["import { isNullOrUndefined, isPlainObject, isString } from '@sindresorhus/is';\nimport { dequal } from 'dequal';\nimport { DateTime } from 'luxon';\nimport { logger } from '../../../logger/index.ts';\nimport * as memCache from '../../../util/cache/memory/index.ts';\nimport { getCache } from '../../../util/cache/repository/index.ts';\nimport type { BitbucketServerHttp } from '../../../util/http/bitbucket-server.ts';\nimport { getQueryString } from '../../../util/url.ts';\nimport type { BbsPr, BbsPrCacheData, BbsRestPr } from './types.ts';\nimport { prInfo } from './utils.ts';\n\nconst syncedCacheKey = 'bitbucket-server:pr-cache-synced';\n\n/* v8 ignore next -- one-off cache-schema migration shim, only runs against real legacy repo caches */\nfunction migrateBitbucketServerCache(platform: unknown): void {\n if (!isPlainObject(platform)) {\n return;\n }\n\n if (!isPlainObject(platform.bitbucketServer)) {\n return;\n }\n\n platform['bitbucket-server'] = platform.bitbucketServer;\n delete platform.bitbucketServer;\n}\n\nexport class BbsPrCache {\n private cache: BbsPrCacheData;\n private items: BbsPr[] = [];\n private projectKey: string;\n private repo: string;\n private readonly ignorePrAuthor: boolean;\n private author: string | null;\n\n private constructor(\n projectKey: string,\n repo: string,\n ignorePrAuthor: boolean,\n author: string | null,\n ) {\n this.projectKey = projectKey;\n this.repo = repo;\n this.ignorePrAuthor = ignorePrAuthor;\n this.author = author;\n const repoCache = getCache();\n repoCache.platform ??= {};\n migrateBitbucketServerCache(repoCache.platform);\n repoCache.platform['bitbucket-server'] ??= {};\n let pullRequestCache = repoCache.platform['bitbucket-server']\n .pullRequestsCache as BbsPrCacheData;\n if (\n isNullOrUndefined(pullRequestCache) ||\n pullRequestCache.author !== author\n ) {\n pullRequestCache = {\n items: {},\n updatedDate: null,\n author,\n };\n }\n repoCache.platform['bitbucket-server'].pullRequestsCache = pullRequestCache;\n this.cache = pullRequestCache;\n this.updateItems();\n }\n\n private static async init(\n http: BitbucketServerHttp,\n projectKey: string,\n repo: string,\n ignorePrAuthor: boolean,\n author: string | null,\n ): Promise<BbsPrCache> {\n const res = new BbsPrCache(projectKey, repo, ignorePrAuthor, author);\n const isSynced = memCache.get<true | undefined>(syncedCacheKey);\n\n // v8 ignore next -- TODO: add test #40625\n if (!isSynced) {\n await res.sync(http);\n memCache.set(syncedCacheKey, true);\n }\n\n return res;\n }\n\n private getPrs(): BbsPr[] {\n return this.items;\n }\n\n static async getPrs(\n http: BitbucketServerHttp,\n projectKey: string,\n repo: string,\n ignorePrAuthor: boolean,\n author: string,\n ): Promise<BbsPr[]> {\n const prCache = await BbsPrCache.init(\n http,\n projectKey,\n repo,\n ignorePrAuthor,\n author,\n );\n return prCache.getPrs();\n }\n\n private setPr(item: BbsPr): void {\n this.cache.items[item.number] = item;\n this.updateItems();\n }\n\n static async setPr(\n http: BitbucketServerHttp,\n projectKey: string,\n repo: string,\n ignorePrAuthor: boolean,\n author: string,\n item: BbsPr,\n ): Promise<void> {\n const prCache = await BbsPrCache.init(\n http,\n projectKey,\n repo,\n ignorePrAuthor,\n author,\n );\n prCache.setPr(item);\n }\n\n private reconcile(rawItems: BbsRestPr[]): boolean {\n logger.debug('reconciled');\n const { items } = this.cache;\n let { updatedDate } = this.cache;\n const cacheTime = updatedDate ? DateTime.fromMillis(updatedDate) : null;\n\n let needNextPage = true;\n\n for (const rawItem of rawItems) {\n const id = rawItem.id;\n\n const newItem = prInfo(rawItem);\n\n const oldItem = items[id];\n if (dequal(oldItem, newItem)) {\n needNextPage = false;\n continue;\n }\n\n items[id] = newItem;\n\n const itemTime = DateTime.fromMillis(rawItem.updatedDate);\n if (!cacheTime || itemTime > cacheTime) {\n updatedDate = rawItem.updatedDate;\n }\n }\n\n this.cache.updatedDate = updatedDate;\n\n return needNextPage;\n }\n\n private async sync(http: BitbucketServerHttp): Promise<BbsPrCache> {\n const searchParams: Record<string, string> = {\n state: 'ALL',\n limit: this.items.length ? '20' : '100',\n };\n if (!this.ignorePrAuthor && isString(this.author)) {\n searchParams['role.1'] = 'AUTHOR';\n searchParams['username.1'] = this.author;\n }\n let query: string | null = getQueryString(searchParams);\n\n while (query) {\n const res = await http.getJsonUnchecked<{\n nextPageStart: string;\n values: BbsRestPr[];\n }>(\n `./rest/api/1.0/projects/${this.projectKey}/repos/${this.repo}/pull-requests?${query}`,\n {\n memCache: false,\n },\n );\n\n const needNextPage = this.reconcile(res.body.values);\n if (!needNextPage) {\n break;\n }\n\n if (res.body.nextPageStart) {\n searchParams.start = res.body.nextPageStart.toString();\n } else {\n query = null;\n }\n }\n\n this.updateItems();\n\n return this;\n }\n\n /**\n * Ensure the pr cache starts with the most recent PRs.\n * JavaScript ensures that the cache is sorted by PR number.\n */\n private updateItems(): void {\n this.items = Object.values(this.cache.items).reverse();\n }\n}\n"],"mappings":"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"}
@@ -9,9 +9,10 @@ import { isNullOrUndefined } from "@sindresorhus/is";
9
9
  import { dequal } from "dequal";
10
10
  import { DateTime } from "luxon";
11
11
  //#region lib/modules/platform/gitea/pr-cache.ts
12
- function syncedCacheKey(platform) {
13
- return `${platform}-pr-cache-synced`;
14
- }
12
+ const syncedCacheKeys = {
13
+ gitea: "gitea:pr-cache-synced",
14
+ forgejo: "forgejo:pr-cache-synced"
15
+ };
15
16
  /**
16
17
  * The PRs of a single repository, backed by the repository cache.
17
18
  */
@@ -127,14 +128,14 @@ var GiteaPrCache = class {
127
128
  this.repoCache = null;
128
129
  }
129
130
  forceSync() {
130
- set(syncedCacheKey(this.platform), false);
131
+ set(syncedCacheKeys[this.platform], false);
131
132
  }
132
133
  async open() {
133
134
  if (!this.repoOptions) throw new Error("PR cache used before initRepo()");
134
135
  this.repoCache ??= new RepoPrCache(this.http, this.platform, this.repoOptions);
135
- if (!get(syncedCacheKey(this.platform))) {
136
+ if (!get(syncedCacheKeys[this.platform])) {
136
137
  await this.repoCache.sync();
137
- set(syncedCacheKey(this.platform), true);
138
+ set(syncedCacheKeys[this.platform], true);
138
139
  }
139
140
  return this.repoCache;
140
141
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pr-cache.js","names":["memCache.get"],"sources":["../../../../lib/modules/platform/gitea/pr-cache.ts"],"sourcesContent":["import { isNullOrUndefined } from '@sindresorhus/is';\nimport { dequal } from 'dequal';\nimport { DateTime } from 'luxon';\nimport { TEMPORARY_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport * as memCache from '../../../util/cache/memory/index.ts';\nimport { getCache } from '../../../util/cache/repository/index.ts';\nimport type { GiteaHttp } from '../../../util/http/gitea.ts';\nimport {\n getQueryString,\n parseLinkHeader,\n parseUrl,\n} from '../../../util/url.ts';\nimport type { Pr } from '../types.ts';\nimport type { PR } from './schema.ts';\nimport { PRList } from './schema.ts';\nimport type { GiteaPlatformKey, PrCacheData } from './types.ts';\nimport { API_PATH, toRenovatePR } from './utils.ts';\n\nfunction syncedCacheKey(platform: GiteaPlatformKey): string {\n return `${platform}-pr-cache-synced`;\n}\n\ninterface RepoPrCacheOptions {\n repo: string;\n ignorePrAuthor: boolean;\n author: string;\n}\n\n/**\n * The PRs of a single repository, backed by the repository cache.\n */\nclass RepoPrCache {\n private readonly http: GiteaHttp;\n private readonly platform: GiteaPlatformKey;\n private readonly cache: PrCacheData;\n private items: Pr[] = [];\n private readonly repo: string;\n private readonly ignorePrAuthor: boolean;\n private readonly author: string;\n\n constructor(\n http: GiteaHttp,\n platform: GiteaPlatformKey,\n { repo, ignorePrAuthor, author }: RepoPrCacheOptions,\n ) {\n this.http = http;\n this.platform = platform;\n this.repo = repo;\n this.ignorePrAuthor = ignorePrAuthor;\n this.author = author;\n const repoCache = getCache();\n repoCache.platform ??= {};\n const platformCache = (repoCache.platform[platform] ??= {});\n let pullRequestCache = platformCache.pullRequestsCache as\n PrCacheData | undefined;\n if (\n isNullOrUndefined(pullRequestCache) ||\n pullRequestCache.author !== author\n ) {\n pullRequestCache = {\n items: {},\n updated_at: null,\n author,\n };\n }\n platformCache.pullRequestsCache = pullRequestCache;\n this.cache = pullRequestCache;\n this.updateItems();\n }\n\n get prs(): Pr[] {\n return this.items;\n }\n\n setPr(item: Pr): void {\n this.cache.items[item.number] = item;\n this.updateItems();\n }\n\n private reconcile(rawItems: (PR | null)[]): boolean {\n const { items } = this.cache;\n let { updated_at } = this.cache;\n const cacheTime = updated_at ? DateTime.fromISO(updated_at) : null;\n\n let needNextPage = true;\n\n for (const rawItem of rawItems) {\n if (!rawItem) {\n logger.warn(\n { platform: this.platform },\n 'PR is empty, throwing temporary error',\n );\n // Gitea API sometimes returns empty PRs, so we throw a temporary error\n // https://github.com/go-gitea/gitea/blob/fcd096231ac2deaefbca10a7db1b9b01f1da93d7/services/convert/pull.go#L34-L52\n throw new Error(TEMPORARY_ERROR);\n }\n const id = rawItem.number;\n\n const newItem = toRenovatePR(rawItem, this.author);\n if (!newItem) {\n continue;\n }\n\n const oldItem = items[id];\n if (dequal(oldItem, newItem)) {\n needNextPage = false;\n continue;\n }\n\n items[id] = newItem;\n\n const itemTime = DateTime.fromISO(rawItem.updated_at);\n if (!cacheTime || itemTime > cacheTime) {\n updated_at = rawItem.updated_at;\n }\n }\n\n this.cache.updated_at = updated_at;\n\n return needNextPage;\n }\n\n async sync(): Promise<void> {\n let query: string | null = getQueryString({\n state: 'all',\n sort: 'recentupdate',\n // Fetch 100 PRs on the first run to ensure we have the most recent PRs.\n // Gitea / Forgejo will cap appropriate (50 by default, see `MAX_RESPONSE_ITEMS`).\n // https://docs.gitea.com/administration/config-cheat-sheet#api-api\n // https://forgejo.org/docs/latest/admin/config-cheat-sheet/#api-api\n limit: this.items.length ? 20 : 100,\n // Supported since Gitea 1.23.0 and Forgejo v10.0.0.\n // Will be ignored by older instances.\n ...(this.ignorePrAuthor ? {} : { poster: this.author }),\n });\n\n while (query) {\n const res = await this.http.getJson(\n `${API_PATH}/repos/${this.repo}/pulls?${query}`,\n {\n memCache: false,\n paginate: false,\n },\n PRList,\n );\n\n const needNextPage = this.reconcile(res.body);\n if (!needNextPage) {\n break;\n }\n\n const uri = parseUrl(parseLinkHeader(res.headers.link)?.next?.url);\n query = uri ? uri.search : null;\n }\n\n this.updateItems();\n }\n\n /**\n * Ensure the pr cache starts with the most recent PRs.\n * JavaScript ensures that the cache is sorted by PR number.\n */\n private updateItems(): void {\n this.items = Object.values(this.cache.items).reverse();\n }\n}\n\n/**\n * PR cache of one platform. `initRepo()` records the repository, the\n * repository cache itself is bound on first use because it is initialized\n * after `platform.initRepo()`.\n */\nexport class GiteaPrCache {\n private readonly http: GiteaHttp;\n private readonly platform: GiteaPlatformKey;\n private repoOptions: RepoPrCacheOptions | null = null;\n private repoCache: RepoPrCache | null = null;\n\n constructor(http: GiteaHttp, platform: GiteaPlatformKey) {\n this.http = http;\n this.platform = platform;\n }\n\n initRepo(repo: string, ignorePrAuthor: boolean, author: string): void {\n this.repoOptions = { repo, ignorePrAuthor, author };\n this.repoCache = null;\n }\n\n reset(): void {\n this.repoOptions = null;\n this.repoCache = null;\n }\n\n forceSync(): void {\n memCache.set(syncedCacheKey(this.platform), false);\n }\n\n private async open(): Promise<RepoPrCache> {\n if (!this.repoOptions) {\n throw new Error('PR cache used before initRepo()');\n }\n this.repoCache ??= new RepoPrCache(\n this.http,\n this.platform,\n this.repoOptions,\n );\n const isSynced = memCache.get<true | undefined>(\n syncedCacheKey(this.platform),\n );\n if (!isSynced) {\n await this.repoCache.sync();\n memCache.set(syncedCacheKey(this.platform), true);\n }\n return this.repoCache;\n }\n\n async getPrs(): Promise<Pr[]> {\n const repoCache = await this.open();\n return repoCache.prs;\n }\n\n async setPr(item: Pr): Promise<void> {\n const repoCache = await this.open();\n repoCache.setPr(item);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pr-cache.js","names":["memCache.get"],"sources":["../../../../lib/modules/platform/gitea/pr-cache.ts"],"sourcesContent":["import { isNullOrUndefined } from '@sindresorhus/is';\nimport { dequal } from 'dequal';\nimport { DateTime } from 'luxon';\nimport { TEMPORARY_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport * as memCache from '../../../util/cache/memory/index.ts';\nimport { getCache } from '../../../util/cache/repository/index.ts';\nimport type { GiteaHttp } from '../../../util/http/gitea.ts';\nimport {\n getQueryString,\n parseLinkHeader,\n parseUrl,\n} from '../../../util/url.ts';\nimport type { Pr } from '../types.ts';\nimport type { PR } from './schema.ts';\nimport { PRList } from './schema.ts';\nimport type { GiteaPlatformKey, PrCacheData } from './types.ts';\nimport { API_PATH, toRenovatePR } from './utils.ts';\n\nconst syncedCacheKeys: Record<GiteaPlatformKey, string> = {\n gitea: 'gitea:pr-cache-synced',\n forgejo: 'forgejo:pr-cache-synced',\n};\n\ninterface RepoPrCacheOptions {\n repo: string;\n ignorePrAuthor: boolean;\n author: string;\n}\n\n/**\n * The PRs of a single repository, backed by the repository cache.\n */\nclass RepoPrCache {\n private readonly http: GiteaHttp;\n private readonly platform: GiteaPlatformKey;\n private readonly cache: PrCacheData;\n private items: Pr[] = [];\n private readonly repo: string;\n private readonly ignorePrAuthor: boolean;\n private readonly author: string;\n\n constructor(\n http: GiteaHttp,\n platform: GiteaPlatformKey,\n { repo, ignorePrAuthor, author }: RepoPrCacheOptions,\n ) {\n this.http = http;\n this.platform = platform;\n this.repo = repo;\n this.ignorePrAuthor = ignorePrAuthor;\n this.author = author;\n const repoCache = getCache();\n repoCache.platform ??= {};\n const platformCache = (repoCache.platform[platform] ??= {});\n let pullRequestCache = platformCache.pullRequestsCache as\n PrCacheData | undefined;\n if (\n isNullOrUndefined(pullRequestCache) ||\n pullRequestCache.author !== author\n ) {\n pullRequestCache = {\n items: {},\n updated_at: null,\n author,\n };\n }\n platformCache.pullRequestsCache = pullRequestCache;\n this.cache = pullRequestCache;\n this.updateItems();\n }\n\n get prs(): Pr[] {\n return this.items;\n }\n\n setPr(item: Pr): void {\n this.cache.items[item.number] = item;\n this.updateItems();\n }\n\n private reconcile(rawItems: (PR | null)[]): boolean {\n const { items } = this.cache;\n let { updated_at } = this.cache;\n const cacheTime = updated_at ? DateTime.fromISO(updated_at) : null;\n\n let needNextPage = true;\n\n for (const rawItem of rawItems) {\n if (!rawItem) {\n logger.warn(\n { platform: this.platform },\n 'PR is empty, throwing temporary error',\n );\n // Gitea API sometimes returns empty PRs, so we throw a temporary error\n // https://github.com/go-gitea/gitea/blob/fcd096231ac2deaefbca10a7db1b9b01f1da93d7/services/convert/pull.go#L34-L52\n throw new Error(TEMPORARY_ERROR);\n }\n const id = rawItem.number;\n\n const newItem = toRenovatePR(rawItem, this.author);\n if (!newItem) {\n continue;\n }\n\n const oldItem = items[id];\n if (dequal(oldItem, newItem)) {\n needNextPage = false;\n continue;\n }\n\n items[id] = newItem;\n\n const itemTime = DateTime.fromISO(rawItem.updated_at);\n if (!cacheTime || itemTime > cacheTime) {\n updated_at = rawItem.updated_at;\n }\n }\n\n this.cache.updated_at = updated_at;\n\n return needNextPage;\n }\n\n async sync(): Promise<void> {\n let query: string | null = getQueryString({\n state: 'all',\n sort: 'recentupdate',\n // Fetch 100 PRs on the first run to ensure we have the most recent PRs.\n // Gitea / Forgejo will cap appropriate (50 by default, see `MAX_RESPONSE_ITEMS`).\n // https://docs.gitea.com/administration/config-cheat-sheet#api-api\n // https://forgejo.org/docs/latest/admin/config-cheat-sheet/#api-api\n limit: this.items.length ? 20 : 100,\n // Supported since Gitea 1.23.0 and Forgejo v10.0.0.\n // Will be ignored by older instances.\n ...(this.ignorePrAuthor ? {} : { poster: this.author }),\n });\n\n while (query) {\n const res = await this.http.getJson(\n `${API_PATH}/repos/${this.repo}/pulls?${query}`,\n {\n memCache: false,\n paginate: false,\n },\n PRList,\n );\n\n const needNextPage = this.reconcile(res.body);\n if (!needNextPage) {\n break;\n }\n\n const uri = parseUrl(parseLinkHeader(res.headers.link)?.next?.url);\n query = uri ? uri.search : null;\n }\n\n this.updateItems();\n }\n\n /**\n * Ensure the pr cache starts with the most recent PRs.\n * JavaScript ensures that the cache is sorted by PR number.\n */\n private updateItems(): void {\n this.items = Object.values(this.cache.items).reverse();\n }\n}\n\n/**\n * PR cache of one platform. `initRepo()` records the repository, the\n * repository cache itself is bound on first use because it is initialized\n * after `platform.initRepo()`.\n */\nexport class GiteaPrCache {\n private readonly http: GiteaHttp;\n private readonly platform: GiteaPlatformKey;\n private repoOptions: RepoPrCacheOptions | null = null;\n private repoCache: RepoPrCache | null = null;\n\n constructor(http: GiteaHttp, platform: GiteaPlatformKey) {\n this.http = http;\n this.platform = platform;\n }\n\n initRepo(repo: string, ignorePrAuthor: boolean, author: string): void {\n this.repoOptions = { repo, ignorePrAuthor, author };\n this.repoCache = null;\n }\n\n reset(): void {\n this.repoOptions = null;\n this.repoCache = null;\n }\n\n forceSync(): void {\n memCache.set(syncedCacheKeys[this.platform], false);\n }\n\n private async open(): Promise<RepoPrCache> {\n if (!this.repoOptions) {\n throw new Error('PR cache used before initRepo()');\n }\n this.repoCache ??= new RepoPrCache(\n this.http,\n this.platform,\n this.repoOptions,\n );\n const isSynced = memCache.get<true | undefined>(\n syncedCacheKeys[this.platform],\n );\n if (!isSynced) {\n await this.repoCache.sync();\n memCache.set(syncedCacheKeys[this.platform], true);\n }\n return this.repoCache;\n }\n\n async getPrs(): Promise<Pr[]> {\n const repoCache = await this.open();\n return repoCache.prs;\n }\n\n async setPr(item: Pr): Promise<void> {\n const repoCache = await this.open();\n repoCache.setPr(item);\n }\n}\n"],"mappings":"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"}
@@ -7,6 +7,7 @@ import { repoCacheProvider } from "../../../util/http/cache/repository-http-cach
7
7
  import { GitLabMergeRequests } from "./schema.js";
8
8
  import { prInfo } from "./utils.js";
9
9
  //#region lib/modules/platform/gitlab/pr-cache.ts
10
+ const syncedCacheKey = "gitlab:pr-cache-synced";
10
11
  var GitlabPrCache = class GitlabPrCache {
11
12
  items = [];
12
13
  cache;
@@ -47,9 +48,9 @@ var GitlabPrCache = class GitlabPrCache {
47
48
  }
48
49
  static async init(http, repo, author, ignorePrAuthor) {
49
50
  const res = new GitlabPrCache(repo, author, ignorePrAuthor);
50
- if (!get("gitlab-pr-cache-synced")) {
51
+ if (!get(syncedCacheKey)) {
51
52
  await res.sync(http);
52
- set("gitlab-pr-cache-synced", true);
53
+ set(syncedCacheKey, true);
53
54
  }
54
55
  return res;
55
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pr-cache.js","names":["memCache.get"],"sources":["../../../../lib/modules/platform/gitlab/pr-cache.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport * as memCache from '../../../util/cache/memory/index.ts';\nimport { getCache } from '../../../util/cache/repository/index.ts';\nimport { repoCacheProvider } from '../../../util/http/cache/repository-http-cache-provider.ts';\nimport type {\n GitlabHttp,\n GitlabHttpOptions,\n} from '../../../util/http/gitlab.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { getQueryString } from '../../../util/url.ts';\nimport { GitLabMergeRequests } from './schema.ts';\nimport type { GitlabPr, GitlabPrCacheData } from './types.ts';\nimport { prInfo } from './utils.ts';\n\nexport class GitlabPrCache {\n private items: GitlabPr[] = [];\n private cache: GitlabPrCacheData;\n private repo: string;\n private ignorePrAuthor: boolean;\n\n private constructor(\n repo: string,\n author: string | null,\n ignorePrAuthor: boolean,\n ) {\n this.repo = repo;\n this.ignorePrAuthor = ignorePrAuthor;\n const repoCache = getCache();\n repoCache.platform ??= {};\n repoCache.platform.gitlab ??= {};\n\n let pullRequestCache = repoCache.platform.gitlab\n .pullRequestsCache as GitlabPrCacheData;\n if (!pullRequestCache) {\n logger.debug('Initializing new PR cache at repository cache');\n pullRequestCache = {\n items: {},\n updated_at: null,\n author,\n };\n } else if (pullRequestCache.author !== author) {\n logger.debug('Resetting PR cache because authors do not match');\n pullRequestCache = {\n items: {},\n updated_at: null,\n author,\n };\n } else if (pullRequestCache.updated_at?.match(regEx(/\\.\\d\\d\\dZ$/))) {\n logger.debug('Resetting PR cache of older format');\n pullRequestCache = {\n items: {},\n updated_at: null,\n author,\n };\n }\n repoCache.platform.gitlab.pullRequestsCache = pullRequestCache;\n this.cache = pullRequestCache;\n this.updateItems();\n }\n\n private static async init(\n http: GitlabHttp,\n repo: string,\n author: string | null,\n ignorePrAuthor: boolean,\n ): Promise<GitlabPrCache> {\n const res = new GitlabPrCache(repo, author, ignorePrAuthor);\n const isSynced = memCache.get<true | undefined>('gitlab-pr-cache-synced');\n\n if (!isSynced) {\n await res.sync(http);\n memCache.set('gitlab-pr-cache-synced', true);\n }\n\n return res;\n }\n\n private getPrs(): GitlabPr[] {\n return this.items;\n }\n\n static async getPrs(\n http: GitlabHttp,\n repo: string,\n author: string | null,\n ignorePrAuthor: boolean,\n ): Promise<GitlabPr[]> {\n const prCache = await GitlabPrCache.init(\n http,\n repo,\n author,\n ignorePrAuthor,\n );\n return prCache.getPrs();\n }\n\n private setPr(pr: GitlabPr): void {\n logger.debug(`Adding PR #${pr.number} to the PR cache`);\n this.cache.items[pr.number] = pr;\n this.updateItems();\n }\n\n static async setPr(\n http: GitlabHttp,\n repo: string,\n author: string | null,\n item: GitlabPr,\n ignorePrAuthor: boolean,\n ): Promise<void> {\n const prCache = await GitlabPrCache.init(\n http,\n repo,\n author,\n ignorePrAuthor,\n );\n prCache.setPr(item);\n }\n\n private async sync(http: GitlabHttp): Promise<GitlabPrCache> {\n logger.debug('Syncing PR list');\n\n const searchParams: Record<string, string> = {\n per_page: '100',\n order_by: 'updated_at',\n sort: 'desc',\n };\n\n const opts: GitlabHttpOptions = { paginate: true };\n\n const updated_after = this.cache.updated_at;\n if (updated_after) {\n opts.cacheProvider = repoCacheProvider;\n searchParams.updated_after = updated_after;\n }\n\n if (!this.ignorePrAuthor) {\n searchParams.scope = 'created_by_me';\n }\n\n const query: string | null = getQueryString(searchParams);\n const { body: items } = await http.getJson(\n `/projects/${this.repo}/merge_requests?${query}`,\n opts,\n GitLabMergeRequests,\n );\n\n if (items.length) {\n for (const item of items) {\n const id = item.iid;\n this.cache.items[id] = prInfo(item);\n }\n\n const [{ updated_at }] = items;\n this.cache.updated_at = updated_at.replace(regEx(/\\.\\d\\d\\dZ$/), 'Z');\n }\n\n this.updateItems();\n\n return this;\n }\n\n /**\n * Ensure the pr cache starts with the most recent PRs.\n */\n private updateItems(): void {\n this.items = Object.values(this.cache.items).sort(\n (a, b) => b.number - a.number,\n );\n }\n}\n"],"mappings":";;;;;;;;;AAcA,IAAa,gBAAb,MAAa,cAAc;CACzB,QAA4B,CAAC;CAC7B;CACA;CACA;CAEA,YACE,MACA,QACA,gBACA;EACA,KAAK,OAAO;EACZ,KAAK,iBAAiB;EACtB,MAAM,YAAY,SAAS;EAC3B,UAAU,aAAa,CAAC;EACxB,UAAU,SAAS,WAAW,CAAC;EAE/B,IAAI,mBAAmB,UAAU,SAAS,OACvC;EACH,IAAI,CAAC,kBAAkB;GACrB,OAAO,MAAM,+CAA+C;GAC5D,mBAAmB;IACjB,OAAO,CAAC;IACR,YAAY;IACZ;GACF;EACF,OAAO,IAAI,iBAAiB,WAAW,QAAQ;GAC7C,OAAO,MAAM,iDAAiD;GAC9D,mBAAmB;IACjB,OAAO,CAAC;IACR,YAAY;IACZ;GACF;EACF,OAAO,IAAI,iBAAiB,YAAY,MAAM,MAAM,YAAY,CAAC,GAAG;GAClE,OAAO,MAAM,oCAAoC;GACjD,mBAAmB;IACjB,OAAO,CAAC;IACR,YAAY;IACZ;GACF;EACF;EACA,UAAU,SAAS,OAAO,oBAAoB;EAC9C,KAAK,QAAQ;EACb,KAAK,YAAY;CACnB;CAEA,aAAqB,KACnB,MACA,MACA,QACA,gBACwB;EACxB,MAAM,MAAM,IAAI,cAAc,MAAM,QAAQ,cAAc;EAG1D,IAAI,CAFaA,IAA+B,wBAEpC,GAAG;GACb,MAAM,IAAI,KAAK,IAAI;GACnB,IAAa,0BAA0B,IAAI;EAC7C;EAEA,OAAO;CACT;CAEA,SAA6B;EAC3B,OAAO,KAAK;CACd;CAEA,aAAa,OACX,MACA,MACA,QACA,gBACqB;EAOrB,QAAO,MANe,cAAc,KAClC,MACA,MACA,QACA,cACF,EAAA,CACe,OAAO;CACxB;CAEA,MAAc,IAAoB;EAChC,OAAO,MAAM,cAAc,GAAG,OAAO,iBAAiB;EACtD,KAAK,MAAM,MAAM,GAAG,UAAU;EAC9B,KAAK,YAAY;CACnB;CAEA,aAAa,MACX,MACA,MACA,QACA,MACA,gBACe;EAOf,CAAA,MANsB,cAAc,KAClC,MACA,MACA,QACA,cACF,EAAA,CACQ,MAAM,IAAI;CACpB;CAEA,MAAc,KAAK,MAA0C;EAC3D,OAAO,MAAM,iBAAiB;EAE9B,MAAM,eAAuC;GAC3C,UAAU;GACV,UAAU;GACV,MAAM;EACR;EAEA,MAAM,OAA0B,EAAE,UAAU,KAAK;EAEjD,MAAM,gBAAgB,KAAK,MAAM;EACjC,IAAI,eAAe;GACjB,KAAK,gBAAgB;GACrB,aAAa,gBAAgB;EAC/B;EAEA,IAAI,CAAC,KAAK,gBACR,aAAa,QAAQ;EAGvB,MAAM,QAAuB,eAAe,YAAY;EACxD,MAAM,EAAE,MAAM,UAAU,MAAM,KAAK,QACjC,aAAa,KAAK,KAAK,kBAAkB,SACzC,MACA,mBACF;EAEA,IAAI,MAAM,QAAQ;GAChB,KAAK,MAAM,QAAQ,OAAO;IACxB,MAAM,KAAK,KAAK;IAChB,KAAK,MAAM,MAAM,MAAM,OAAO,IAAI;GACpC;GAEA,MAAM,CAAC,EAAE,gBAAgB;GACzB,KAAK,MAAM,aAAa,WAAW,QAAQ,MAAM,YAAY,GAAG,GAAG;EACrE;EAEA,KAAK,YAAY;EAEjB,OAAO;CACT;;;;CAKA,cAA4B;EAC1B,KAAK,QAAQ,OAAO,OAAO,KAAK,MAAM,KAAK,CAAC,CAAC,MAC1C,GAAG,MAAM,EAAE,SAAS,EAAE,MACzB;CACF;AACF"}
1
+ {"version":3,"file":"pr-cache.js","names":["memCache.get"],"sources":["../../../../lib/modules/platform/gitlab/pr-cache.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport * as memCache from '../../../util/cache/memory/index.ts';\nimport { getCache } from '../../../util/cache/repository/index.ts';\nimport { repoCacheProvider } from '../../../util/http/cache/repository-http-cache-provider.ts';\nimport type {\n GitlabHttp,\n GitlabHttpOptions,\n} from '../../../util/http/gitlab.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { getQueryString } from '../../../util/url.ts';\nimport { GitLabMergeRequests } from './schema.ts';\nimport type { GitlabPr, GitlabPrCacheData } from './types.ts';\nimport { prInfo } from './utils.ts';\n\nconst syncedCacheKey = 'gitlab:pr-cache-synced';\n\nexport class GitlabPrCache {\n private items: GitlabPr[] = [];\n private cache: GitlabPrCacheData;\n private repo: string;\n private ignorePrAuthor: boolean;\n\n private constructor(\n repo: string,\n author: string | null,\n ignorePrAuthor: boolean,\n ) {\n this.repo = repo;\n this.ignorePrAuthor = ignorePrAuthor;\n const repoCache = getCache();\n repoCache.platform ??= {};\n repoCache.platform.gitlab ??= {};\n\n let pullRequestCache = repoCache.platform.gitlab\n .pullRequestsCache as GitlabPrCacheData;\n if (!pullRequestCache) {\n logger.debug('Initializing new PR cache at repository cache');\n pullRequestCache = {\n items: {},\n updated_at: null,\n author,\n };\n } else if (pullRequestCache.author !== author) {\n logger.debug('Resetting PR cache because authors do not match');\n pullRequestCache = {\n items: {},\n updated_at: null,\n author,\n };\n } else if (pullRequestCache.updated_at?.match(regEx(/\\.\\d\\d\\dZ$/))) {\n logger.debug('Resetting PR cache of older format');\n pullRequestCache = {\n items: {},\n updated_at: null,\n author,\n };\n }\n repoCache.platform.gitlab.pullRequestsCache = pullRequestCache;\n this.cache = pullRequestCache;\n this.updateItems();\n }\n\n private static async init(\n http: GitlabHttp,\n repo: string,\n author: string | null,\n ignorePrAuthor: boolean,\n ): Promise<GitlabPrCache> {\n const res = new GitlabPrCache(repo, author, ignorePrAuthor);\n const isSynced = memCache.get<true | undefined>(syncedCacheKey);\n\n if (!isSynced) {\n await res.sync(http);\n memCache.set(syncedCacheKey, true);\n }\n\n return res;\n }\n\n private getPrs(): GitlabPr[] {\n return this.items;\n }\n\n static async getPrs(\n http: GitlabHttp,\n repo: string,\n author: string | null,\n ignorePrAuthor: boolean,\n ): Promise<GitlabPr[]> {\n const prCache = await GitlabPrCache.init(\n http,\n repo,\n author,\n ignorePrAuthor,\n );\n return prCache.getPrs();\n }\n\n private setPr(pr: GitlabPr): void {\n logger.debug(`Adding PR #${pr.number} to the PR cache`);\n this.cache.items[pr.number] = pr;\n this.updateItems();\n }\n\n static async setPr(\n http: GitlabHttp,\n repo: string,\n author: string | null,\n item: GitlabPr,\n ignorePrAuthor: boolean,\n ): Promise<void> {\n const prCache = await GitlabPrCache.init(\n http,\n repo,\n author,\n ignorePrAuthor,\n );\n prCache.setPr(item);\n }\n\n private async sync(http: GitlabHttp): Promise<GitlabPrCache> {\n logger.debug('Syncing PR list');\n\n const searchParams: Record<string, string> = {\n per_page: '100',\n order_by: 'updated_at',\n sort: 'desc',\n };\n\n const opts: GitlabHttpOptions = { paginate: true };\n\n const updated_after = this.cache.updated_at;\n if (updated_after) {\n opts.cacheProvider = repoCacheProvider;\n searchParams.updated_after = updated_after;\n }\n\n if (!this.ignorePrAuthor) {\n searchParams.scope = 'created_by_me';\n }\n\n const query: string | null = getQueryString(searchParams);\n const { body: items } = await http.getJson(\n `/projects/${this.repo}/merge_requests?${query}`,\n opts,\n GitLabMergeRequests,\n );\n\n if (items.length) {\n for (const item of items) {\n const id = item.iid;\n this.cache.items[id] = prInfo(item);\n }\n\n const [{ updated_at }] = items;\n this.cache.updated_at = updated_at.replace(regEx(/\\.\\d\\d\\dZ$/), 'Z');\n }\n\n this.updateItems();\n\n return this;\n }\n\n /**\n * Ensure the pr cache starts with the most recent PRs.\n */\n private updateItems(): void {\n this.items = Object.values(this.cache.items).sort(\n (a, b) => b.number - a.number,\n );\n }\n}\n"],"mappings":";;;;;;;;;AAcA,MAAM,iBAAiB;AAEvB,IAAa,gBAAb,MAAa,cAAc;CACzB,QAA4B,CAAC;CAC7B;CACA;CACA;CAEA,YACE,MACA,QACA,gBACA;EACA,KAAK,OAAO;EACZ,KAAK,iBAAiB;EACtB,MAAM,YAAY,SAAS;EAC3B,UAAU,aAAa,CAAC;EACxB,UAAU,SAAS,WAAW,CAAC;EAE/B,IAAI,mBAAmB,UAAU,SAAS,OACvC;EACH,IAAI,CAAC,kBAAkB;GACrB,OAAO,MAAM,+CAA+C;GAC5D,mBAAmB;IACjB,OAAO,CAAC;IACR,YAAY;IACZ;GACF;EACF,OAAO,IAAI,iBAAiB,WAAW,QAAQ;GAC7C,OAAO,MAAM,iDAAiD;GAC9D,mBAAmB;IACjB,OAAO,CAAC;IACR,YAAY;IACZ;GACF;EACF,OAAO,IAAI,iBAAiB,YAAY,MAAM,MAAM,YAAY,CAAC,GAAG;GAClE,OAAO,MAAM,oCAAoC;GACjD,mBAAmB;IACjB,OAAO,CAAC;IACR,YAAY;IACZ;GACF;EACF;EACA,UAAU,SAAS,OAAO,oBAAoB;EAC9C,KAAK,QAAQ;EACb,KAAK,YAAY;CACnB;CAEA,aAAqB,KACnB,MACA,MACA,QACA,gBACwB;EACxB,MAAM,MAAM,IAAI,cAAc,MAAM,QAAQ,cAAc;EAG1D,IAAI,CAFaA,IAA+B,cAEpC,GAAG;GACb,MAAM,IAAI,KAAK,IAAI;GACnB,IAAa,gBAAgB,IAAI;EACnC;EAEA,OAAO;CACT;CAEA,SAA6B;EAC3B,OAAO,KAAK;CACd;CAEA,aAAa,OACX,MACA,MACA,QACA,gBACqB;EAOrB,QAAO,MANe,cAAc,KAClC,MACA,MACA,QACA,cACF,EAAA,CACe,OAAO;CACxB;CAEA,MAAc,IAAoB;EAChC,OAAO,MAAM,cAAc,GAAG,OAAO,iBAAiB;EACtD,KAAK,MAAM,MAAM,GAAG,UAAU;EAC9B,KAAK,YAAY;CACnB;CAEA,aAAa,MACX,MACA,MACA,QACA,MACA,gBACe;EAOf,CAAA,MANsB,cAAc,KAClC,MACA,MACA,QACA,cACF,EAAA,CACQ,MAAM,IAAI;CACpB;CAEA,MAAc,KAAK,MAA0C;EAC3D,OAAO,MAAM,iBAAiB;EAE9B,MAAM,eAAuC;GAC3C,UAAU;GACV,UAAU;GACV,MAAM;EACR;EAEA,MAAM,OAA0B,EAAE,UAAU,KAAK;EAEjD,MAAM,gBAAgB,KAAK,MAAM;EACjC,IAAI,eAAe;GACjB,KAAK,gBAAgB;GACrB,aAAa,gBAAgB;EAC/B;EAEA,IAAI,CAAC,KAAK,gBACR,aAAa,QAAQ;EAGvB,MAAM,QAAuB,eAAe,YAAY;EACxD,MAAM,EAAE,MAAM,UAAU,MAAM,KAAK,QACjC,aAAa,KAAK,KAAK,kBAAkB,SACzC,MACA,mBACF;EAEA,IAAI,MAAM,QAAQ;GAChB,KAAK,MAAM,QAAQ,OAAO;IACxB,MAAM,KAAK,KAAK;IAChB,KAAK,MAAM,MAAM,MAAM,OAAO,IAAI;GACpC;GAEA,MAAM,CAAC,EAAE,gBAAgB;GACzB,KAAK,MAAM,aAAa,WAAW,QAAQ,MAAM,YAAY,GAAG,GAAG;EACrE;EAEA,KAAK,YAAY;EAEjB,OAAO;CACT;;;;CAKA,cAA4B;EAC1B,KAAK,QAAQ,OAAO,OAAO,KAAK,MAAM,KAAK,CAAC,CAAC,MAC1C,GAAG,MAAM,EAAE,SAAS,EAAE,MACzB;CACF;AACF"}
@@ -1,7 +1,7 @@
1
1
  import { get as get$1, set as set$1 } from "../memory/index.js";
2
2
  import { PackageCacheStats } from "../../stats.js";
3
- import { destroy, get as get$2, getCacheType as getCacheType$1, init as init$1, set as set$2 } from "./backend.js";
4
3
  import { getCombinedKey } from "./key.js";
4
+ import { destroy, get as get$2, getCacheType as getCacheType$1, init as init$1, set as set$2 } from "./backend.js";
5
5
  import { getTtlOverride } from "./ttl.js";
6
6
  //#region lib/util/cache/package/index.ts
7
7
  function getCacheType() {
@@ -5,7 +5,14 @@
5
5
  function getCombinedKey(namespace, key) {
6
6
  return `datasource-mem:pkg-fetch:${namespace}:${key}`;
7
7
  }
8
+ /**
9
+ * Joins all given parts with `:`, using an empty string for `undefined` and `null` parts.
10
+ * Parts are joined as-is, without escaping `:` inside a part.
11
+ */
12
+ function buildCacheKey(...parts) {
13
+ return parts.map((part) => part ?? "").join(":");
14
+ }
8
15
  //#endregion
9
- export { getCombinedKey };
16
+ export { buildCacheKey, getCombinedKey };
10
17
 
11
18
  //# sourceMappingURL=key.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"key.js","names":[],"sources":["../../../../lib/util/cache/package/key.ts"],"sourcesContent":["import type { CombinedKey, PackageCacheNamespace } from './types.ts';\n\n/**\n * Returns the key used by underlying storage implementations\n */\nexport function getCombinedKey(\n namespace: PackageCacheNamespace,\n key: string,\n): CombinedKey {\n return `datasource-mem:pkg-fetch:${namespace}:${key}`;\n}\n"],"mappings":";;;;AAKA,SAAgB,eACd,WACA,KACa;CACb,OAAO,4BAA4B,UAAU,GAAG;AAClD"}
1
+ {"version":3,"file":"key.js","names":[],"sources":["../../../../lib/util/cache/package/key.ts"],"sourcesContent":["import type { CombinedKey, PackageCacheNamespace } from './types.ts';\n\n/**\n * Returns the key used by underlying storage implementations\n */\nexport function getCombinedKey(\n namespace: PackageCacheNamespace,\n key: string,\n): CombinedKey {\n return `datasource-mem:pkg-fetch:${namespace}:${key}`;\n}\n\n/**\n * Joins all given parts with `:`, using an empty string for `undefined` and `null` parts.\n * Parts are joined as-is, without escaping `:` inside a part.\n */\nexport function buildCacheKey(\n ...parts: (string | number | null | undefined)[]\n): string {\n return parts.map((part) => part ?? '').join(':');\n}\n"],"mappings":";;;;AAKA,SAAgB,eACd,WACA,KACa;CACb,OAAO,4BAA4B,UAAU,GAAG;AAClD;;;;;AAMA,SAAgB,cACd,GAAG,OACK;CACR,OAAO,MAAM,KAAK,SAAS,QAAQ,EAAE,CAAC,CAAC,KAAK,GAAG;AACjD"}
@@ -1,5 +1,6 @@
1
1
  import { GlobalConfig } from "../../../config/global.js";
2
2
  import { logger } from "../../../logger/index.js";
3
+ import { buildCacheKey } from "./key.js";
3
4
  import { acquireLock } from "../../mutex.js";
4
5
  import { resolveTtlValues } from "./ttl.js";
5
6
  import { get, setWithRawTtl } from "./index.js";
@@ -22,7 +23,7 @@ async function withCache(options, fn) {
22
23
  const shouldCacheResult = options.shouldCacheResult ?? defaultShouldCacheResult;
23
24
  // istanbul ignore if -- TODO: add test #40625
24
25
  if (!namespace || !key) return fn();
25
- const cacheKey = `cache-decorator:${key}`;
26
+ const cacheKey = buildCacheKey("cache-decorator", key);
26
27
  const releaseLock = await acquireLock(cacheKey, namespace);
27
28
  try {
28
29
  const cachedRecord = await get(namespace, cacheKey);
@@ -1 +1 @@
1
- {"version":3,"file":"with-cache.js","names":["packageCache.get","packageCache.setWithRawTtl"],"sources":["../../../../lib/util/cache/package/with-cache.ts"],"sourcesContent":["import { isUndefined } from '@sindresorhus/is';\nimport { DateTime } from 'luxon';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { acquireLock } from '../../mutex.ts';\nimport * as packageCache from './index.ts';\nimport { resolveTtlValues } from './ttl.ts';\nimport type { CachedRecord, PackageCacheNamespace } from './types.ts';\n\nexport interface CachedOptions {\n /**\n * The cache namespace.\n */\n namespace: PackageCacheNamespace;\n\n /**\n * The cache key.\n */\n key: string;\n\n /**\n * The TTL (or expiry) of the key in minutes.\n * @default 30\n */\n ttlMinutes?: number;\n\n /**\n * Whether caching is enabled for this call.\n * When false, the function is called directly without caching.\n * @default true\n */\n cacheable?: boolean;\n\n /**\n * Whether a cache result is safe to use and store for this call.\n * @default value !== undefined\n */\n shouldCacheResult?: (value: unknown) => boolean;\n\n /**\n * Enable extended hard TTL for graceful degradation.\n * When true and upstream errors occur, stale cached data is returned.\n * @default false\n */\n fallback?: boolean;\n}\n\n/**\n * Caches the result of an async function.\n *\n * @param options - Cache options\n * @param fn - The async function to cache\n * @returns The cached or fresh result\n */\nexport async function withCache<T>(\n options: CachedOptions,\n fn: () => T | Promise<T>,\n): Promise<T> {\n const {\n namespace,\n key,\n ttlMinutes = 30,\n cacheable = true,\n fallback = false,\n } = options;\n\n const cachePrivatePackages = GlobalConfig.get('cachePrivatePackages');\n const isCacheable = cachePrivatePackages || cacheable;\n if (!isCacheable) {\n return fn();\n }\n\n function defaultShouldCacheResult(_value: unknown): boolean {\n return true;\n }\n const shouldCacheResult =\n options.shouldCacheResult ?? defaultShouldCacheResult;\n\n // istanbul ignore if -- TODO: add test #40625\n if (!namespace || !key) {\n return fn();\n }\n\n const cacheKey = `cache-decorator:${key}`;\n\n // prevent concurrent processing and cache writes\n const releaseLock = await acquireLock(cacheKey, namespace);\n\n try {\n const cachedRecord = await packageCache.get<CachedRecord>(\n namespace,\n cacheKey,\n );\n\n const { softTtlMinutes, hardTtlMinutes: resolvedHardTtl } =\n resolveTtlValues(namespace, ttlMinutes);\n\n // The separation between \"soft\" and \"hard\" TTL allows us to treat\n // data as obsolete according to the \"soft\" TTL while physically storing it\n // according to the \"hard\" TTL.\n //\n // This helps us return obsolete data in case of upstream server errors,\n // which is more useful than throwing exceptions ourselves.\n //\n // The `fallback` option controls whether this extended TTL behavior is used.\n // When false, the \"soft\" just equals the \"hard\" ttl.\n const hardTtlMinutes = fallback ? resolvedHardTtl : softTtlMinutes;\n\n let fallbackValue: unknown;\n if (cachedRecord && shouldCacheResult(cachedRecord.value)) {\n const now = DateTime.local();\n const cachedAt = DateTime.fromISO(cachedRecord.cachedAt);\n\n const softDeadline = cachedAt.plus({ minutes: softTtlMinutes });\n if (now < softDeadline) {\n return cachedRecord.value as T;\n }\n\n const hardDeadline = cachedAt.plus({ minutes: hardTtlMinutes });\n if (now < hardDeadline) {\n fallbackValue = cachedRecord.value;\n }\n }\n\n let newValue: T;\n try {\n newValue = await fn();\n } catch (err) {\n if (!isUndefined(fallbackValue)) {\n logger.debug(\n { err },\n 'Package cache: callback error, returning stale data',\n );\n return fallbackValue as T;\n }\n throw err;\n }\n\n if (!isUndefined(newValue) && shouldCacheResult(newValue)) {\n const newRecord: CachedRecord = {\n cachedAt: DateTime.local().toISO(),\n value: newValue,\n };\n await packageCache.setWithRawTtl(\n namespace,\n cacheKey,\n newRecord,\n hardTtlMinutes,\n );\n }\n\n return newValue;\n } finally {\n releaseLock();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAsDA,eAAsB,UACpB,SACA,IACY;CACZ,MAAM,EACJ,WACA,KACA,aAAa,IACb,YAAY,MACZ,WAAW,UACT;CAIJ,IAAI,EAFyB,aAAa,IAAI,sBACP,KAAK,YAE1C,OAAO,GAAG;CAGZ,SAAS,yBAAyB,QAA0B;EAC1D,OAAO;CACT;CACA,MAAM,oBACJ,QAAQ,qBAAqB;;CAG/B,IAAI,CAAC,aAAa,CAAC,KACjB,OAAO,GAAG;CAGZ,MAAM,WAAW,mBAAmB;CAGpC,MAAM,cAAc,MAAM,YAAY,UAAU,SAAS;CAEzD,IAAI;EACF,MAAM,eAAe,MAAMA,IACzB,WACA,QACF;EAEA,MAAM,EAAE,gBAAgB,gBAAgB,oBACtC,iBAAiB,WAAW,UAAU;EAWxC,MAAM,iBAAiB,WAAW,kBAAkB;EAEpD,IAAI;EACJ,IAAI,gBAAgB,kBAAkB,aAAa,KAAK,GAAG;GACzD,MAAM,MAAM,SAAS,MAAM;GAC3B,MAAM,WAAW,SAAS,QAAQ,aAAa,QAAQ;GAGvD,IAAI,MADiB,SAAS,KAAK,EAAE,SAAS,eAAe,CACxC,GACnB,OAAO,aAAa;GAItB,IAAI,MADiB,SAAS,KAAK,EAAE,SAAS,eAAe,CACxC,GACnB,gBAAgB,aAAa;EAEjC;EAEA,IAAI;EACJ,IAAI;GACF,WAAW,MAAM,GAAG;EACtB,SAAS,KAAK;GACZ,IAAI,CAAC,YAAY,aAAa,GAAG;IAC/B,OAAO,MACL,EAAE,IAAI,GACN,qDACF;IACA,OAAO;GACT;GACA,MAAM;EACR;EAEA,IAAI,CAAC,YAAY,QAAQ,KAAK,kBAAkB,QAAQ,GAAG;GACzD,MAAM,YAA0B;IAC9B,UAAU,SAAS,MAAM,CAAC,CAAC,MAAM;IACjC,OAAO;GACT;GACA,MAAMC,cACJ,WACA,UACA,WACA,cACF;EACF;EAEA,OAAO;CACT,UAAU;EACR,YAAY;CACd;AACF"}
1
+ {"version":3,"file":"with-cache.js","names":["packageCache.get","packageCache.setWithRawTtl"],"sources":["../../../../lib/util/cache/package/with-cache.ts"],"sourcesContent":["import { isUndefined } from '@sindresorhus/is';\nimport { DateTime } from 'luxon';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { acquireLock } from '../../mutex.ts';\nimport * as packageCache from './index.ts';\nimport { buildCacheKey } from './key.ts';\nimport { resolveTtlValues } from './ttl.ts';\nimport type { CachedRecord, PackageCacheNamespace } from './types.ts';\n\nexport interface CachedOptions {\n /**\n * The cache namespace.\n */\n namespace: PackageCacheNamespace;\n\n /**\n * The cache key.\n */\n key: string;\n\n /**\n * The TTL (or expiry) of the key in minutes.\n * @default 30\n */\n ttlMinutes?: number;\n\n /**\n * Whether caching is enabled for this call.\n * When false, the function is called directly without caching.\n * @default true\n */\n cacheable?: boolean;\n\n /**\n * Whether a cache result is safe to use and store for this call.\n * @default value !== undefined\n */\n shouldCacheResult?: (value: unknown) => boolean;\n\n /**\n * Enable extended hard TTL for graceful degradation.\n * When true and upstream errors occur, stale cached data is returned.\n * @default false\n */\n fallback?: boolean;\n}\n\n/**\n * Caches the result of an async function.\n *\n * @param options - Cache options\n * @param fn - The async function to cache\n * @returns The cached or fresh result\n */\nexport async function withCache<T>(\n options: CachedOptions,\n fn: () => T | Promise<T>,\n): Promise<T> {\n const {\n namespace,\n key,\n ttlMinutes = 30,\n cacheable = true,\n fallback = false,\n } = options;\n\n const cachePrivatePackages = GlobalConfig.get('cachePrivatePackages');\n const isCacheable = cachePrivatePackages || cacheable;\n if (!isCacheable) {\n return fn();\n }\n\n function defaultShouldCacheResult(_value: unknown): boolean {\n return true;\n }\n const shouldCacheResult =\n options.shouldCacheResult ?? defaultShouldCacheResult;\n\n // istanbul ignore if -- TODO: add test #40625\n if (!namespace || !key) {\n return fn();\n }\n\n const cacheKey = buildCacheKey('cache-decorator', key);\n\n // prevent concurrent processing and cache writes\n const releaseLock = await acquireLock(cacheKey, namespace);\n\n try {\n const cachedRecord = await packageCache.get<CachedRecord>(\n namespace,\n cacheKey,\n );\n\n const { softTtlMinutes, hardTtlMinutes: resolvedHardTtl } =\n resolveTtlValues(namespace, ttlMinutes);\n\n // The separation between \"soft\" and \"hard\" TTL allows us to treat\n // data as obsolete according to the \"soft\" TTL while physically storing it\n // according to the \"hard\" TTL.\n //\n // This helps us return obsolete data in case of upstream server errors,\n // which is more useful than throwing exceptions ourselves.\n //\n // The `fallback` option controls whether this extended TTL behavior is used.\n // When false, the \"soft\" just equals the \"hard\" ttl.\n const hardTtlMinutes = fallback ? resolvedHardTtl : softTtlMinutes;\n\n let fallbackValue: unknown;\n if (cachedRecord && shouldCacheResult(cachedRecord.value)) {\n const now = DateTime.local();\n const cachedAt = DateTime.fromISO(cachedRecord.cachedAt);\n\n const softDeadline = cachedAt.plus({ minutes: softTtlMinutes });\n if (now < softDeadline) {\n return cachedRecord.value as T;\n }\n\n const hardDeadline = cachedAt.plus({ minutes: hardTtlMinutes });\n if (now < hardDeadline) {\n fallbackValue = cachedRecord.value;\n }\n }\n\n let newValue: T;\n try {\n newValue = await fn();\n } catch (err) {\n if (!isUndefined(fallbackValue)) {\n logger.debug(\n { err },\n 'Package cache: callback error, returning stale data',\n );\n return fallbackValue as T;\n }\n throw err;\n }\n\n if (!isUndefined(newValue) && shouldCacheResult(newValue)) {\n const newRecord: CachedRecord = {\n cachedAt: DateTime.local().toISO(),\n value: newValue,\n };\n await packageCache.setWithRawTtl(\n namespace,\n cacheKey,\n newRecord,\n hardTtlMinutes,\n );\n }\n\n return newValue;\n } finally {\n releaseLock();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAuDA,eAAsB,UACpB,SACA,IACY;CACZ,MAAM,EACJ,WACA,KACA,aAAa,IACb,YAAY,MACZ,WAAW,UACT;CAIJ,IAAI,EAFyB,aAAa,IAAI,sBACP,KAAK,YAE1C,OAAO,GAAG;CAGZ,SAAS,yBAAyB,QAA0B;EAC1D,OAAO;CACT;CACA,MAAM,oBACJ,QAAQ,qBAAqB;;CAG/B,IAAI,CAAC,aAAa,CAAC,KACjB,OAAO,GAAG;CAGZ,MAAM,WAAW,cAAc,mBAAmB,GAAG;CAGrD,MAAM,cAAc,MAAM,YAAY,UAAU,SAAS;CAEzD,IAAI;EACF,MAAM,eAAe,MAAMA,IACzB,WACA,QACF;EAEA,MAAM,EAAE,gBAAgB,gBAAgB,oBACtC,iBAAiB,WAAW,UAAU;EAWxC,MAAM,iBAAiB,WAAW,kBAAkB;EAEpD,IAAI;EACJ,IAAI,gBAAgB,kBAAkB,aAAa,KAAK,GAAG;GACzD,MAAM,MAAM,SAAS,MAAM;GAC3B,MAAM,WAAW,SAAS,QAAQ,aAAa,QAAQ;GAGvD,IAAI,MADiB,SAAS,KAAK,EAAE,SAAS,eAAe,CACxC,GACnB,OAAO,aAAa;GAItB,IAAI,MADiB,SAAS,KAAK,EAAE,SAAS,eAAe,CACxC,GACnB,gBAAgB,aAAa;EAEjC;EAEA,IAAI;EACJ,IAAI;GACF,WAAW,MAAM,GAAG;EACtB,SAAS,KAAK;GACZ,IAAI,CAAC,YAAY,aAAa,GAAG;IAC/B,OAAO,MACL,EAAE,IAAI,GACN,qDACF;IACA,OAAO;GACT;GACA,MAAM;EACR;EAEA,IAAI,CAAC,YAAY,QAAQ,KAAK,kBAAkB,QAAQ,GAAG;GACzD,MAAM,YAA0B;IAC9B,UAAU,SAAS,MAAM,CAAC,CAAC,MAAM;IACjC,OAAO;GACT;GACA,MAAMC,cACJ,WACA,UACA,WACA,cACF;EACF;EAEA,OAAO;CACT,UAAU;EACR,YAAY;CACd;AACF"}
@@ -4,6 +4,7 @@ import { regEx } from "../regex.js";
4
4
  import { GlobalConfig } from "../../config/global.js";
5
5
  import { coerceArray } from "../array.js";
6
6
  import { logger } from "../../logger/index.js";
7
+ import { buildCacheKey } from "../cache/package/key.js";
7
8
  import { isString } from "@sindresorhus/is";
8
9
  import { quote } from "shlex";
9
10
  //#region lib/util/exec/containerbase.ts
@@ -338,7 +339,7 @@ async function generateInstallCommands(toolConstraints, memoize = false) {
338
339
  const toolVersion = await resolveConstraint(toolConstraint);
339
340
  const { toolName } = toolConstraint;
340
341
  if (memoize) {
341
- const cacheKey = `containerbase-active:${toolName}`;
342
+ const cacheKey = buildCacheKey("containerbase-active", toolName);
342
343
  if (get(cacheKey) === toolVersion) continue;
343
344
  set(cacheKey, toolVersion);
344
345
  }
@@ -1 +1 @@
1
- {"version":3,"file":"containerbase.js","names":["memCache.get"],"sources":["../../../lib/util/exec/containerbase.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { quote } from 'shlex';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { logger } from '../../logger/index.ts';\nimport type { ReleaseResult } from '../../modules/datasource/index.ts';\nimport type { VersioningApi } from '../../modules/versioning/types.ts';\nimport { coerceArray } from '../array.ts';\nimport * as memCache from '../cache/memory/index.ts';\nimport { getEnv } from '../env.ts';\nimport { regEx } from '../regex.ts';\nimport type { Opt, ToolConfig, ToolConstraint, ToolName } from './types.ts';\n\n/**\n * A subset of Containerbase tools that are supported by Renovate to look up version numbers for.\n */\nexport const allToolConfig: Partial<Record<ToolName, ToolConfig>> = {\n apm: {\n datasource: 'github-releases',\n packageName: 'microsoft/apm',\n versioning: 'semver',\n extractVersion: '^v(?<version>.*)$',\n },\n bazelisk: {\n datasource: 'github-releases',\n packageName: 'bazelbuild/bazelisk',\n versioning: 'semver',\n },\n bun: {\n datasource: 'github-releases',\n packageName: 'oven-sh/bun',\n extractVersion: '^bun-v(?<version>.*)$',\n versioning: 'npm',\n },\n bundler: {\n datasource: 'rubygems',\n packageName: 'bundler',\n versioning: 'ruby',\n },\n cocoapods: {\n datasource: 'rubygems',\n packageName: 'cocoapods',\n versioning: 'ruby',\n },\n composer: {\n datasource: 'github-releases',\n packageName: 'containerbase/composer-prebuild',\n versioning: 'composer',\n },\n conan: {\n datasource: 'pypi',\n packageName: 'conan',\n versioning: 'pep440',\n },\n copier: {\n datasource: 'pypi',\n packageName: 'copier',\n versioning: 'pep440',\n },\n corepack: {\n datasource: 'npm',\n packageName: 'corepack',\n versioning: 'npm',\n },\n deno: {\n datasource: 'github-releases',\n packageName: 'denoland/deno',\n versioning: 'deno',\n },\n devbox: {\n datasource: 'github-releases',\n packageName: 'jetify-com/devbox',\n versioning: 'semver',\n },\n dotnet: {\n datasource: 'dotnet-version',\n packageName: 'dotnet-sdk',\n versioning: 'semver',\n },\n erlang: {\n datasource: 'github-releases',\n packageName: 'containerbase/erlang-prebuild',\n versioning: 'semver-coerced',\n },\n elixir: {\n datasource: 'github-releases',\n packageName: 'elixir-lang/elixir',\n versioning: 'semver',\n },\n flux: {\n datasource: 'github-releases',\n packageName: 'fluxcd/flux2',\n versioning: 'semver',\n },\n gh: {\n datasource: 'github-releases',\n packageName: 'cli/cli',\n versioning: 'semver',\n },\n gleam: {\n datasource: 'github-releases',\n packageName: 'gleam-lang/gleam',\n versioning: 'semver',\n },\n golang: {\n datasource: 'github-releases',\n packageName: 'containerbase/golang-prebuild',\n versioning: 'npm',\n },\n gradle: {\n datasource: 'gradle-version',\n packageName: 'gradle',\n versioning: 'gradle',\n },\n hashin: {\n datasource: 'pypi',\n packageName: 'hashin',\n versioning: 'pep440',\n },\n helm: {\n datasource: 'github-releases',\n packageName: 'helm/helm',\n versioning: 'semver',\n },\n helmfile: {\n datasource: 'github-releases',\n packageName: 'helmfile/helmfile',\n versioning: 'semver',\n },\n java: {\n datasource: 'java-version',\n packageName: 'java?system=true',\n versioning: 'npm',\n },\n jb: {\n datasource: 'github-releases',\n packageName: 'jsonnet-bundler/jsonnet-bundler',\n versioning: 'semver',\n },\n kustomize: {\n datasource: 'github-releases',\n packageName: 'kubernetes-sigs/kustomize',\n extractVersion: '^kustomize/v(?<version>.*)$',\n versioning: 'semver',\n },\n maven: {\n datasource: 'github-releases',\n packageName: 'containerbase/maven-prebuild',\n versioning: 'maven',\n },\n mise: {\n datasource: 'github-releases',\n packageName: 'jdx/mise',\n versioning: 'npm',\n },\n nix: {\n datasource: 'github-releases',\n packageName: 'containerbase/nix-prebuild',\n versioning: 'semver',\n },\n node: {\n datasource: 'github-releases',\n packageName: 'containerbase/node-prebuild',\n versioning: 'node',\n },\n npm: {\n datasource: 'npm',\n packageName: 'npm',\n versioning: 'npm',\n },\n pdm: {\n datasource: 'github-releases',\n packageName: 'pdm-project/pdm',\n versioning: 'semver',\n },\n php: {\n datasource: 'github-releases',\n packageName: 'containerbase/php-prebuild',\n versioning: 'composer',\n },\n 'pip-tools': {\n datasource: 'pypi',\n packageName: 'pip-tools',\n versioning: 'pep440',\n },\n pipenv: {\n datasource: 'pypi',\n packageName: 'pipenv',\n versioning: 'pep440',\n },\n pnpm: {\n datasource: 'npm',\n packageName: 'pnpm',\n versioning: 'npm',\n },\n pixi: {\n datasource: 'github-releases',\n packageName: 'prefix-dev/pixi',\n versioning: 'conda',\n extractVersion: '^v(?<version>.*)$',\n },\n poetry: {\n datasource: 'pypi',\n packageName: 'poetry',\n versioning: 'pep440',\n },\n python: {\n datasource: 'github-releases',\n packageName: 'containerbase/python-prebuild',\n versioning: 'python',\n },\n ruby: {\n datasource: 'github-releases',\n packageName: 'containerbase/ruby-prebuild',\n versioning: 'ruby',\n },\n rust: {\n datasource: 'rust-version',\n packageName: 'rust',\n versioning: 'rust-release-channel',\n },\n uv: {\n datasource: 'pypi',\n packageName: 'uv',\n versioning: 'pep440',\n },\n yarn: {\n datasource: 'npm',\n packageName: 'yarn',\n versioning: 'npm',\n },\n 'yarn-slim': {\n datasource: 'npm',\n packageName: 'yarn',\n versioning: 'npm',\n },\n dart: {\n datasource: 'dart-version',\n packageName: 'dart',\n versioning: 'npm',\n },\n flutter: {\n datasource: 'github-releases',\n packageName: 'containerbase/flutter-prebuild',\n versioning: 'npm',\n },\n vendir: {\n datasource: 'github-releases',\n packageName: 'carvel-dev/vendir',\n versioning: 'semver',\n },\n} as const;\n\n/**\n * A Containerbase `tool` that Renovate supports configuring the version of.\n */\nexport type SupportedToolNames = keyof typeof allToolConfig;\n\n/**\n * All Containerbase `tool`s that Renovate supports configuring the version of.\n */\nexport function getSupportedToolNames(): readonly ToolName[] {\n return Object.keys(allToolConfig) as readonly ToolName[];\n}\n\nlet _getPkgReleases: Promise<\n typeof import('../../modules/datasource/index.ts')\n> | null = null;\n\nasync function getPkgReleases(\n toolConfig: ToolConfig,\n): Promise<ReleaseResult | null> {\n _getPkgReleases ??= import('../../modules/datasource/index.ts');\n const { getPkgReleases } = await _getPkgReleases;\n return getPkgReleases(toolConfig);\n}\n\nexport function getToolConfig(toolName: ToolName): ToolConfig | undefined {\n return allToolConfig[toolName];\n}\n\nexport function supportsDynamicInstall(toolName: ToolName): boolean {\n return !!allToolConfig[toolName];\n}\n\nexport function isContainerbase(): boolean {\n return !!getEnv().CONTAINERBASE;\n}\n\nexport function isDynamicInstall(\n toolConstraints?: Opt<ToolConstraint[]>,\n): boolean {\n if (GlobalConfig.get('binarySource') !== 'install') {\n return false;\n }\n if (!isContainerbase()) {\n logger.debug('Falling back to binarySource=global');\n return false;\n }\n return (\n !toolConstraints ||\n toolConstraints.every((toolConstraint) =>\n supportsDynamicInstall(toolConstraint.toolName),\n )\n );\n}\n\nfunction isStable(\n version: string,\n versioningApi: VersioningApi,\n latest?: string,\n): boolean {\n if (!versioningApi.isStable(version)) {\n return false;\n }\n if (isString(latest) && versioningApi.isGreaterThan(version, latest)) {\n return false;\n }\n return true;\n}\n\nexport async function resolveConstraint(\n toolConstraint: ToolConstraint,\n): Promise<string> {\n const { toolName } = toolConstraint;\n const toolConfig = allToolConfig[toolName];\n if (!toolConfig) {\n throw new Error(`Invalid tool to install: ${toolName}`);\n }\n\n const { get: getVersioning } =\n await import('../../modules/versioning/index.ts');\n const versioning = getVersioning(toolConfig.versioning);\n let constraint = toolConstraint.constraint;\n if (constraint) {\n if (versioning.isValid(constraint)) {\n if (versioning.isSingleVersion(constraint)) {\n return constraint.replace(regEx(/^=+/), '').trim();\n }\n } else {\n logger.warn(\n { toolName, constraint, versioning: toolConfig.versioning },\n 'Invalid tool constraint',\n );\n constraint = undefined;\n }\n }\n\n const pkgReleases = await getPkgReleases(toolConfig);\n const releases = coerceArray(pkgReleases?.releases);\n\n if (!releases?.length) {\n logger.warn({ toolConfig }, 'No tool releases found.');\n throw new Error('No tool releases found.');\n }\n\n const matchingReleases = releases.filter(\n (r) => !constraint || versioning.matches(r.version, constraint),\n );\n\n const stableMatchingVersion = matchingReleases\n .filter((r) => isStable(r.version, versioning, pkgReleases?.tags?.latest))\n .pop()?.version;\n if (stableMatchingVersion) {\n logger.debug(\n { toolName, constraint, resolvedVersion: stableMatchingVersion },\n 'Resolved stable matching version',\n );\n return stableMatchingVersion;\n }\n\n const unstableMatchingVersion = matchingReleases.pop()?.version;\n if (unstableMatchingVersion) {\n logger.debug(\n { toolName, constraint, resolvedVersion: unstableMatchingVersion },\n 'Resolved unstable matching version',\n );\n return unstableMatchingVersion;\n }\n\n const stableVersion = releases\n .filter((r) => isStable(r.version, versioning, pkgReleases?.tags?.latest))\n .pop()?.version;\n if (stableVersion) {\n logger.warn(\n { toolName, constraint, stableVersion },\n 'No matching tool versions found for constraint - using latest stable version',\n );\n }\n\n const highestVersion = releases.pop()!.version;\n logger.warn(\n { toolName, constraint, highestVersion },\n 'No matching or stable tool versions found - using an unstable version',\n );\n return highestVersion;\n}\n\n// Docker execs run in a fresh `--rm` container each time, so `memoize` must\n// stay false there - only the persistent-host (binarySource=install) path\n// can safely skip a tool whose requested version is already active.\n// `install-tool` also activates the version it installs, so the memo tracks\n// the active version per tool, not every installed version.\nexport async function generateInstallCommands(\n toolConstraints: Opt<ToolConstraint[]>,\n memoize = false,\n): Promise<string[]> {\n const installCommands: string[] = [];\n if (toolConstraints?.length) {\n for (const toolConstraint of toolConstraints) {\n const toolVersion = await resolveConstraint(toolConstraint);\n const { toolName } = toolConstraint;\n if (memoize) {\n const cacheKey = `containerbase-active:${toolName}`;\n if (memCache.get<string | undefined>(cacheKey) === toolVersion) {\n continue;\n }\n memCache.set(cacheKey, toolVersion);\n }\n const installCommand = `install-tool ${toolName} ${quote(toolVersion)}`;\n installCommands.push(installCommand);\n }\n }\n return installCommands;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"containerbase.js","names":["memCache.get"],"sources":["../../../lib/util/exec/containerbase.ts"],"sourcesContent":["import { isString } from '@sindresorhus/is';\nimport { quote } from 'shlex';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { logger } from '../../logger/index.ts';\nimport type { ReleaseResult } from '../../modules/datasource/index.ts';\nimport type { VersioningApi } from '../../modules/versioning/types.ts';\nimport { coerceArray } from '../array.ts';\nimport * as memCache from '../cache/memory/index.ts';\nimport { buildCacheKey } from '../cache/package/key.ts';\nimport { getEnv } from '../env.ts';\nimport { regEx } from '../regex.ts';\nimport type { Opt, ToolConfig, ToolConstraint, ToolName } from './types.ts';\n\n/**\n * A subset of Containerbase tools that are supported by Renovate to look up version numbers for.\n */\nexport const allToolConfig: Partial<Record<ToolName, ToolConfig>> = {\n apm: {\n datasource: 'github-releases',\n packageName: 'microsoft/apm',\n versioning: 'semver',\n extractVersion: '^v(?<version>.*)$',\n },\n bazelisk: {\n datasource: 'github-releases',\n packageName: 'bazelbuild/bazelisk',\n versioning: 'semver',\n },\n bun: {\n datasource: 'github-releases',\n packageName: 'oven-sh/bun',\n extractVersion: '^bun-v(?<version>.*)$',\n versioning: 'npm',\n },\n bundler: {\n datasource: 'rubygems',\n packageName: 'bundler',\n versioning: 'ruby',\n },\n cocoapods: {\n datasource: 'rubygems',\n packageName: 'cocoapods',\n versioning: 'ruby',\n },\n composer: {\n datasource: 'github-releases',\n packageName: 'containerbase/composer-prebuild',\n versioning: 'composer',\n },\n conan: {\n datasource: 'pypi',\n packageName: 'conan',\n versioning: 'pep440',\n },\n copier: {\n datasource: 'pypi',\n packageName: 'copier',\n versioning: 'pep440',\n },\n corepack: {\n datasource: 'npm',\n packageName: 'corepack',\n versioning: 'npm',\n },\n deno: {\n datasource: 'github-releases',\n packageName: 'denoland/deno',\n versioning: 'deno',\n },\n devbox: {\n datasource: 'github-releases',\n packageName: 'jetify-com/devbox',\n versioning: 'semver',\n },\n dotnet: {\n datasource: 'dotnet-version',\n packageName: 'dotnet-sdk',\n versioning: 'semver',\n },\n erlang: {\n datasource: 'github-releases',\n packageName: 'containerbase/erlang-prebuild',\n versioning: 'semver-coerced',\n },\n elixir: {\n datasource: 'github-releases',\n packageName: 'elixir-lang/elixir',\n versioning: 'semver',\n },\n flux: {\n datasource: 'github-releases',\n packageName: 'fluxcd/flux2',\n versioning: 'semver',\n },\n gh: {\n datasource: 'github-releases',\n packageName: 'cli/cli',\n versioning: 'semver',\n },\n gleam: {\n datasource: 'github-releases',\n packageName: 'gleam-lang/gleam',\n versioning: 'semver',\n },\n golang: {\n datasource: 'github-releases',\n packageName: 'containerbase/golang-prebuild',\n versioning: 'npm',\n },\n gradle: {\n datasource: 'gradle-version',\n packageName: 'gradle',\n versioning: 'gradle',\n },\n hashin: {\n datasource: 'pypi',\n packageName: 'hashin',\n versioning: 'pep440',\n },\n helm: {\n datasource: 'github-releases',\n packageName: 'helm/helm',\n versioning: 'semver',\n },\n helmfile: {\n datasource: 'github-releases',\n packageName: 'helmfile/helmfile',\n versioning: 'semver',\n },\n java: {\n datasource: 'java-version',\n packageName: 'java?system=true',\n versioning: 'npm',\n },\n jb: {\n datasource: 'github-releases',\n packageName: 'jsonnet-bundler/jsonnet-bundler',\n versioning: 'semver',\n },\n kustomize: {\n datasource: 'github-releases',\n packageName: 'kubernetes-sigs/kustomize',\n extractVersion: '^kustomize/v(?<version>.*)$',\n versioning: 'semver',\n },\n maven: {\n datasource: 'github-releases',\n packageName: 'containerbase/maven-prebuild',\n versioning: 'maven',\n },\n mise: {\n datasource: 'github-releases',\n packageName: 'jdx/mise',\n versioning: 'npm',\n },\n nix: {\n datasource: 'github-releases',\n packageName: 'containerbase/nix-prebuild',\n versioning: 'semver',\n },\n node: {\n datasource: 'github-releases',\n packageName: 'containerbase/node-prebuild',\n versioning: 'node',\n },\n npm: {\n datasource: 'npm',\n packageName: 'npm',\n versioning: 'npm',\n },\n pdm: {\n datasource: 'github-releases',\n packageName: 'pdm-project/pdm',\n versioning: 'semver',\n },\n php: {\n datasource: 'github-releases',\n packageName: 'containerbase/php-prebuild',\n versioning: 'composer',\n },\n 'pip-tools': {\n datasource: 'pypi',\n packageName: 'pip-tools',\n versioning: 'pep440',\n },\n pipenv: {\n datasource: 'pypi',\n packageName: 'pipenv',\n versioning: 'pep440',\n },\n pnpm: {\n datasource: 'npm',\n packageName: 'pnpm',\n versioning: 'npm',\n },\n pixi: {\n datasource: 'github-releases',\n packageName: 'prefix-dev/pixi',\n versioning: 'conda',\n extractVersion: '^v(?<version>.*)$',\n },\n poetry: {\n datasource: 'pypi',\n packageName: 'poetry',\n versioning: 'pep440',\n },\n python: {\n datasource: 'github-releases',\n packageName: 'containerbase/python-prebuild',\n versioning: 'python',\n },\n ruby: {\n datasource: 'github-releases',\n packageName: 'containerbase/ruby-prebuild',\n versioning: 'ruby',\n },\n rust: {\n datasource: 'rust-version',\n packageName: 'rust',\n versioning: 'rust-release-channel',\n },\n uv: {\n datasource: 'pypi',\n packageName: 'uv',\n versioning: 'pep440',\n },\n yarn: {\n datasource: 'npm',\n packageName: 'yarn',\n versioning: 'npm',\n },\n 'yarn-slim': {\n datasource: 'npm',\n packageName: 'yarn',\n versioning: 'npm',\n },\n dart: {\n datasource: 'dart-version',\n packageName: 'dart',\n versioning: 'npm',\n },\n flutter: {\n datasource: 'github-releases',\n packageName: 'containerbase/flutter-prebuild',\n versioning: 'npm',\n },\n vendir: {\n datasource: 'github-releases',\n packageName: 'carvel-dev/vendir',\n versioning: 'semver',\n },\n} as const;\n\n/**\n * A Containerbase `tool` that Renovate supports configuring the version of.\n */\nexport type SupportedToolNames = keyof typeof allToolConfig;\n\n/**\n * All Containerbase `tool`s that Renovate supports configuring the version of.\n */\nexport function getSupportedToolNames(): readonly ToolName[] {\n return Object.keys(allToolConfig) as readonly ToolName[];\n}\n\nlet _getPkgReleases: Promise<\n typeof import('../../modules/datasource/index.ts')\n> | null = null;\n\nasync function getPkgReleases(\n toolConfig: ToolConfig,\n): Promise<ReleaseResult | null> {\n _getPkgReleases ??= import('../../modules/datasource/index.ts');\n const { getPkgReleases } = await _getPkgReleases;\n return getPkgReleases(toolConfig);\n}\n\nexport function getToolConfig(toolName: ToolName): ToolConfig | undefined {\n return allToolConfig[toolName];\n}\n\nexport function supportsDynamicInstall(toolName: ToolName): boolean {\n return !!allToolConfig[toolName];\n}\n\nexport function isContainerbase(): boolean {\n return !!getEnv().CONTAINERBASE;\n}\n\nexport function isDynamicInstall(\n toolConstraints?: Opt<ToolConstraint[]>,\n): boolean {\n if (GlobalConfig.get('binarySource') !== 'install') {\n return false;\n }\n if (!isContainerbase()) {\n logger.debug('Falling back to binarySource=global');\n return false;\n }\n return (\n !toolConstraints ||\n toolConstraints.every((toolConstraint) =>\n supportsDynamicInstall(toolConstraint.toolName),\n )\n );\n}\n\nfunction isStable(\n version: string,\n versioningApi: VersioningApi,\n latest?: string,\n): boolean {\n if (!versioningApi.isStable(version)) {\n return false;\n }\n if (isString(latest) && versioningApi.isGreaterThan(version, latest)) {\n return false;\n }\n return true;\n}\n\nexport async function resolveConstraint(\n toolConstraint: ToolConstraint,\n): Promise<string> {\n const { toolName } = toolConstraint;\n const toolConfig = allToolConfig[toolName];\n if (!toolConfig) {\n throw new Error(`Invalid tool to install: ${toolName}`);\n }\n\n const { get: getVersioning } =\n await import('../../modules/versioning/index.ts');\n const versioning = getVersioning(toolConfig.versioning);\n let constraint = toolConstraint.constraint;\n if (constraint) {\n if (versioning.isValid(constraint)) {\n if (versioning.isSingleVersion(constraint)) {\n return constraint.replace(regEx(/^=+/), '').trim();\n }\n } else {\n logger.warn(\n { toolName, constraint, versioning: toolConfig.versioning },\n 'Invalid tool constraint',\n );\n constraint = undefined;\n }\n }\n\n const pkgReleases = await getPkgReleases(toolConfig);\n const releases = coerceArray(pkgReleases?.releases);\n\n if (!releases?.length) {\n logger.warn({ toolConfig }, 'No tool releases found.');\n throw new Error('No tool releases found.');\n }\n\n const matchingReleases = releases.filter(\n (r) => !constraint || versioning.matches(r.version, constraint),\n );\n\n const stableMatchingVersion = matchingReleases\n .filter((r) => isStable(r.version, versioning, pkgReleases?.tags?.latest))\n .pop()?.version;\n if (stableMatchingVersion) {\n logger.debug(\n { toolName, constraint, resolvedVersion: stableMatchingVersion },\n 'Resolved stable matching version',\n );\n return stableMatchingVersion;\n }\n\n const unstableMatchingVersion = matchingReleases.pop()?.version;\n if (unstableMatchingVersion) {\n logger.debug(\n { toolName, constraint, resolvedVersion: unstableMatchingVersion },\n 'Resolved unstable matching version',\n );\n return unstableMatchingVersion;\n }\n\n const stableVersion = releases\n .filter((r) => isStable(r.version, versioning, pkgReleases?.tags?.latest))\n .pop()?.version;\n if (stableVersion) {\n logger.warn(\n { toolName, constraint, stableVersion },\n 'No matching tool versions found for constraint - using latest stable version',\n );\n }\n\n const highestVersion = releases.pop()!.version;\n logger.warn(\n { toolName, constraint, highestVersion },\n 'No matching or stable tool versions found - using an unstable version',\n );\n return highestVersion;\n}\n\n// Docker execs run in a fresh `--rm` container each time, so `memoize` must\n// stay false there - only the persistent-host (binarySource=install) path\n// can safely skip a tool whose requested version is already active.\n// `install-tool` also activates the version it installs, so the memo tracks\n// the active version per tool, not every installed version.\nexport async function generateInstallCommands(\n toolConstraints: Opt<ToolConstraint[]>,\n memoize = false,\n): Promise<string[]> {\n const installCommands: string[] = [];\n if (toolConstraints?.length) {\n for (const toolConstraint of toolConstraints) {\n const toolVersion = await resolveConstraint(toolConstraint);\n const { toolName } = toolConstraint;\n if (memoize) {\n const cacheKey = buildCacheKey('containerbase-active', toolName);\n if (memCache.get<string | undefined>(cacheKey) === toolVersion) {\n continue;\n }\n memCache.set(cacheKey, toolVersion);\n }\n const installCommand = `install-tool ${toolName} ${quote(toolVersion)}`;\n installCommands.push(installCommand);\n }\n }\n return installCommands;\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { get, set } from "../../../cache/memory/index.js";
2
+ import { buildCacheKey } from "../../../cache/package/key.js";
2
3
  import { AbstractGithubGraphqlCacheStrategy } from "./abstract-cache-strategy.js";
3
4
  //#region lib/util/github/graphql/cache-strategies/memory-cache-strategy.ts
4
5
  /**
@@ -7,7 +8,7 @@ import { AbstractGithubGraphqlCacheStrategy } from "./abstract-cache-strategy.js
7
8
  */
8
9
  var GithubGraphqlMemoryCacheStrategy = class extends AbstractGithubGraphqlCacheStrategy {
9
10
  fullKey() {
10
- return `github-graphql-cache:${this.cacheNs}:${this.cacheKey}`;
11
+ return buildCacheKey("github-graphql-cache", this.cacheNs, this.cacheKey);
11
12
  }
12
13
  load() {
13
14
  const key = this.fullKey();
@@ -1 +1 @@
1
- {"version":3,"file":"memory-cache-strategy.js","names":["memCache.get"],"sources":["../../../../../lib/util/github/graphql/cache-strategies/memory-cache-strategy.ts"],"sourcesContent":["import * as memCache from '../../../cache/memory/index.ts';\nimport type {\n GithubDatasourceItem,\n GithubGraphqlCacheRecord,\n} from '../types.ts';\nimport { AbstractGithubGraphqlCacheStrategy } from './abstract-cache-strategy.ts';\n\n/**\n * In-memory strategy meant to be used for private packages\n * and for testing purposes.\n */\nexport class GithubGraphqlMemoryCacheStrategy<\n GithubItem extends GithubDatasourceItem,\n> extends AbstractGithubGraphqlCacheStrategy<GithubItem> {\n private fullKey(): string {\n return `github-graphql-cache:${this.cacheNs}:${this.cacheKey}`;\n }\n\n load(): Promise<GithubGraphqlCacheRecord<GithubItem> | undefined> {\n const key = this.fullKey();\n const res = memCache.get(key);\n return Promise.resolve(res);\n }\n\n persist(cacheRecord: GithubGraphqlCacheRecord<GithubItem>): Promise<void> {\n const key = this.fullKey();\n memCache.set(key, cacheRecord);\n return Promise.resolve();\n }\n}\n"],"mappings":";;;;;;;AAWA,IAAa,mCAAb,cAEU,mCAA+C;CACvD,UAA0B;EACxB,OAAO,wBAAwB,KAAK,QAAQ,GAAG,KAAK;CACtD;CAEA,OAAkE;EAChE,MAAM,MAAM,KAAK,QAAQ;EACzB,MAAM,MAAMA,IAAa,GAAG;EAC5B,OAAO,QAAQ,QAAQ,GAAG;CAC5B;CAEA,QAAQ,aAAkE;EACxE,MAAM,MAAM,KAAK,QAAQ;EACzB,IAAa,KAAK,WAAW;EAC7B,OAAO,QAAQ,QAAQ;CACzB;AACF"}
1
+ {"version":3,"file":"memory-cache-strategy.js","names":["memCache.get"],"sources":["../../../../../lib/util/github/graphql/cache-strategies/memory-cache-strategy.ts"],"sourcesContent":["import * as memCache from '../../../cache/memory/index.ts';\nimport { buildCacheKey } from '../../../cache/package/key.ts';\nimport type {\n GithubDatasourceItem,\n GithubGraphqlCacheRecord,\n} from '../types.ts';\nimport { AbstractGithubGraphqlCacheStrategy } from './abstract-cache-strategy.ts';\n\n/**\n * In-memory strategy meant to be used for private packages\n * and for testing purposes.\n */\nexport class GithubGraphqlMemoryCacheStrategy<\n GithubItem extends GithubDatasourceItem,\n> extends AbstractGithubGraphqlCacheStrategy<GithubItem> {\n private fullKey(): string {\n return buildCacheKey('github-graphql-cache', this.cacheNs, this.cacheKey);\n }\n\n load(): Promise<GithubGraphqlCacheRecord<GithubItem> | undefined> {\n const key = this.fullKey();\n const res = memCache.get(key);\n return Promise.resolve(res);\n }\n\n persist(cacheRecord: GithubGraphqlCacheRecord<GithubItem>): Promise<void> {\n const key = this.fullKey();\n memCache.set(key, cacheRecord);\n return Promise.resolve();\n }\n}\n"],"mappings":";;;;;;;;AAYA,IAAa,mCAAb,cAEU,mCAA+C;CACvD,UAA0B;EACxB,OAAO,cAAc,wBAAwB,KAAK,SAAS,KAAK,QAAQ;CAC1E;CAEA,OAAkE;EAChE,MAAM,MAAM,KAAK,QAAQ;EACzB,MAAM,MAAMA,IAAa,GAAG;EAC5B,OAAO,QAAQ,QAAQ,GAAG;CAC5B;CAEA,QAAQ,aAAkE;EACxE,MAAM,MAAM,KAAK,QAAQ;EACzB,IAAa,KAAK,WAAW;EAC7B,OAAO,QAAQ,QAAQ;CACzB;AACF"}
@@ -2,6 +2,7 @@ import { get, set } from "../../cache/memory/index.js";
2
2
  import { regEx } from "../../regex.js";
3
3
  import { GlobalConfig } from "../../../config/global.js";
4
4
  import { logger } from "../../../logger/index.js";
5
+ import { buildCacheKey } from "../../cache/package/key.js";
5
6
  import { ExternalHostError } from "../../../types/errors/external-host-error.js";
6
7
  import { get as get$1, set as set$1 } from "../../cache/package/index.js";
7
8
  import { getApiBaseUrl } from "../url.js";
@@ -61,11 +62,7 @@ var GithubGraphqlDatasourceFetcher = class GithubGraphqlDatasourceFetcher {
61
62
  return this.datasourceAdapter.key;
62
63
  }
63
64
  getCacheKey() {
64
- return [
65
- this.baseUrl,
66
- this.repoOwner,
67
- this.repoName
68
- ].join(":");
65
+ return buildCacheKey(this.baseUrl, this.repoOwner, this.repoName);
69
66
  }
70
67
  getRawQueryOptions() {
71
68
  return {
@@ -188,12 +185,12 @@ var GithubGraphqlDatasourceFetcher = class GithubGraphqlDatasourceFetcher {
188
185
  }
189
186
  async loadPersistenceFlag() {
190
187
  const ns = this.getCacheNs();
191
- const key = `${this.getCacheKey()}:is-persistent`;
188
+ const key = buildCacheKey(this.getCacheKey(), "is-persistent");
192
189
  this.isPersistent = await get$1(ns, key);
193
190
  }
194
191
  async storePersistenceFlag(minutes) {
195
192
  const ns = this.getCacheNs();
196
- const key = `${this.getCacheKey()}:is-persistent`;
193
+ const key = buildCacheKey(this.getCacheKey(), "is-persistent");
197
194
  await set$1(ns, key, true, minutes);
198
195
  }
199
196
  /**
@@ -201,7 +198,7 @@ var GithubGraphqlDatasourceFetcher = class GithubGraphqlDatasourceFetcher {
201
198
  * to a particular package during single run.
202
199
  */
203
200
  doUniqueQuery() {
204
- const cacheKey = `github-pending:${this.getCacheNs()}:${this.getCacheKey()}`;
201
+ const cacheKey = buildCacheKey("github-pending", this.getCacheNs(), this.getCacheKey());
205
202
  let resultPromise = get(cacheKey);
206
203
  resultPromise ??= this.doCachedQuery();
207
204
  set(cacheKey, resultPromise);
@@ -1 +1 @@
1
- {"version":3,"file":"datasource-fetcher.js","names":["packageCache.get","packageCache.set","memCache.get"],"sources":["../../../../lib/util/github/graphql/datasource-fetcher.ts"],"sourcesContent":["import is from '@sindresorhus/is';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport * as memCache from '../../cache/memory/index.ts';\nimport * as packageCache from '../../cache/package/index.ts';\nimport type { PackageCacheNamespace } from '../../cache/package/types.ts';\nimport type {\n GithubGraphqlResponse,\n GithubHttp,\n GithubHttpOptions,\n} from '../../http/github.ts';\nimport type { HttpResponse } from '../../http/types.ts';\nimport { regEx } from '../../regex.ts';\nimport { getApiBaseUrl } from '../url.ts';\nimport { GithubGraphqlMemoryCacheStrategy } from './cache-strategies/memory-cache-strategy.ts';\nimport { GithubGraphqlPackageCacheStrategy } from './cache-strategies/package-cache-strategy.ts';\nimport type {\n GithubDatasourceItem,\n GithubGraphqlCacheStrategy,\n GithubGraphqlDatasourceAdapter,\n GithubGraphqlPayload,\n GithubGraphqlRepoParams,\n GithubGraphqlRepoResponse,\n GithubPackageConfig,\n RawQueryResponse,\n} from './types.ts';\n\n/**\n * Page sizes to try, from the largest to the smallest.\n *\n * Repositories with many tags can exceed the GitHub GraphQL execution\n * timeout even for small page sizes, hence the low floor.\n *\n * @see https://github.com/renovatebot/renovate/discussions/45248\n */\nconst pageSizes = [100, 50, 25, 10, 5] as const;\n\ntype PageSize = (typeof pageSizes)[number];\n\n/**\n * We know empirically that certain type of GraphQL errors\n * can be fixed by shrinking page size.\n *\n * @see https://github.com/renovatebot/renovate/issues/16343\n */\nfunction isUnknownGraphqlError(err: Error): boolean {\n const { message } = err;\n return message.startsWith('Something went wrong while executing your query.');\n}\n\nfunction canBeSolvedByShrinking(err: Error): boolean {\n const errors: Error[] = err instanceof AggregateError ? err.errors : [err];\n return errors.some(\n (e) => err instanceof ExternalHostError || isUnknownGraphqlError(e),\n );\n}\n\nexport class GithubGraphqlDatasourceFetcher<\n GraphqlItem,\n ResultItem extends GithubDatasourceItem,\n> {\n static async query<T, U extends GithubDatasourceItem>(\n config: GithubPackageConfig,\n http: GithubHttp,\n adapter: GithubGraphqlDatasourceAdapter<T, U>,\n ): Promise<U[]> {\n const instance = new GithubGraphqlDatasourceFetcher<T, U>(\n config,\n http,\n adapter,\n );\n const items = await instance.getItems();\n return items;\n }\n\n private readonly baseUrl: string;\n private readonly repoOwner: string;\n private readonly repoName: string;\n\n private itemsPerQuery: PageSize = pageSizes[0];\n\n private queryCount = 0;\n\n private cursor: string | null = null;\n\n private isPersistent: boolean | undefined;\n private http: GithubHttp;\n private datasourceAdapter: GithubGraphqlDatasourceAdapter<\n GraphqlItem,\n ResultItem\n >;\n\n constructor(\n packageConfig: GithubPackageConfig,\n http: GithubHttp,\n datasourceAdapter: GithubGraphqlDatasourceAdapter<GraphqlItem, ResultItem>,\n ) {\n this.http = http;\n this.datasourceAdapter = datasourceAdapter;\n const { packageName, registryUrl } = packageConfig;\n [this.repoOwner, this.repoName] = packageName.split('/');\n this.baseUrl = getApiBaseUrl(registryUrl).replace(regEx(/\\/v3\\/$/), '/'); // Replace for GHE\n }\n\n private getCacheNs(): PackageCacheNamespace {\n return this.datasourceAdapter.key;\n }\n\n private getCacheKey(): string {\n return [this.baseUrl, this.repoOwner, this.repoName].join(':');\n }\n\n private getRawQueryOptions(): GithubHttpOptions {\n const baseUrl = this.baseUrl;\n const repository = `${this.repoOwner}/${this.repoName}`;\n const query = this.datasourceAdapter.query;\n const variables: GithubGraphqlRepoParams = {\n owner: this.repoOwner,\n name: this.repoName,\n count: this.itemsPerQuery,\n cursor: this.cursor,\n };\n\n return {\n baseUrl,\n repository,\n readOnly: true,\n body: { query, variables },\n };\n }\n\n private async doRawQuery(): Promise<\n RawQueryResponse<GithubGraphqlPayload<GraphqlItem>>\n > {\n const requestOptions = this.getRawQueryOptions();\n\n type GraphqlData = GithubGraphqlRepoResponse<GraphqlItem>;\n type HttpBody = GithubGraphqlResponse<GraphqlData>;\n let httpRes: HttpResponse<HttpBody>;\n try {\n httpRes = await this.http.postJson<HttpBody>('/graphql', requestOptions);\n } catch (err) {\n return [null, err];\n }\n\n const { body } = httpRes;\n const { data, errors } = body;\n\n if (errors?.length) {\n if (errors.length === 1) {\n const { message } = errors[0];\n const err = new Error(message);\n return [null, err];\n }\n const errorInstances = errors.map(({ message }) => new Error(message));\n const err = new AggregateError(errorInstances);\n return [null, err];\n }\n\n if (!data) {\n const msg = 'GitHub GraphQL datasource: failed to obtain data';\n const err = new Error(msg);\n return [null, err];\n }\n\n if (!data.repository) {\n const msg = 'GitHub GraphQL datasource: failed to obtain repository data';\n const err = new Error(msg);\n return [null, err];\n }\n\n if (!data.repository.payload) {\n const msg =\n 'GitHub GraphQL datasource: failed to obtain repository payload data';\n const err = new Error(msg);\n return [null, err];\n }\n\n this.queryCount += 1;\n\n // For values other than explicit `false`,\n // we assume that items can not be cached.\n this.isPersistent ??= data.repository.isRepoPrivate === false;\n\n const res = data.repository.payload;\n return [res, null];\n }\n\n private shrinkPageSize(): boolean {\n const nextIdx = pageSizes.indexOf(this.itemsPerQuery) + 1;\n if (nextIdx >= pageSizes.length) {\n return false;\n }\n\n this.itemsPerQuery = pageSizes[nextIdx];\n return true;\n }\n\n private hasReachedQueryLimit(): boolean {\n return this.queryCount >= 100;\n }\n\n private async doShrinkableQuery(): Promise<\n GithubGraphqlPayload<GraphqlItem>\n > {\n let res: GithubGraphqlPayload<GraphqlItem> | null = null;\n let err: Error | null = null;\n\n while (!res) {\n [res, err] = await this.doRawQuery();\n if (err) {\n if (!canBeSolvedByShrinking(err)) {\n throw err;\n }\n\n const shrinkResult = this.shrinkPageSize();\n if (!shrinkResult) {\n throw err;\n }\n const { body: _, ...options } = this.getRawQueryOptions();\n logger.debug(\n { options, newSize: this.itemsPerQuery },\n 'Shrinking GitHub GraphQL page size after error',\n );\n }\n }\n\n return res;\n }\n\n private _cacheStrategy: GithubGraphqlCacheStrategy<ResultItem> | undefined;\n\n private cacheStrategy(): GithubGraphqlCacheStrategy<ResultItem> {\n if (this._cacheStrategy) {\n return this._cacheStrategy;\n }\n const cacheNs = this.getCacheNs();\n const cacheKey = this.getCacheKey();\n const cachePrivatePackages = GlobalConfig.get('cachePrivatePackages');\n const skipStabilization = !is.undefined(this.datasourceAdapter.maxItems);\n this._cacheStrategy =\n cachePrivatePackages || this.isPersistent\n ? new GithubGraphqlPackageCacheStrategy<ResultItem>(\n cacheNs,\n cacheKey,\n skipStabilization,\n )\n : new GithubGraphqlMemoryCacheStrategy<ResultItem>(\n cacheNs,\n cacheKey,\n skipStabilization,\n );\n return this._cacheStrategy;\n }\n\n /**\n * This method is responsible for data synchronization.\n * It also detects persistence of the package, based on the first page result.\n */\n private async doPaginatedFetch(): Promise<void> {\n let hasNextPage = true;\n let isPaginationDone = false;\n let nextCursor: string | undefined;\n let itemCount = 0;\n const maxItems = this.datasourceAdapter.maxItems;\n while (hasNextPage && !isPaginationDone && !this.hasReachedQueryLimit()) {\n if (!is.undefined(maxItems) && itemCount >= maxItems) {\n break;\n }\n const queryResult = await this.doShrinkableQuery();\n\n const resultItems: ResultItem[] = [];\n for (const node of queryResult.nodes) {\n const item = this.datasourceAdapter.transform(node);\n if (!item) {\n logger.once.info(\n {\n packageName: `${this.repoOwner}/${this.repoName}`,\n baseUrl: this.baseUrl,\n },\n `GitHub GraphQL datasource: skipping empty item`,\n );\n continue;\n }\n resultItems.push(item);\n }\n itemCount += resultItems.length;\n\n // It's important to call `getCacheStrategy()` after `doShrinkableQuery()`\n // because `doShrinkableQuery()` may change `this.isCacheable`.\n //\n // Otherwise, cache items for public packages will never be persisted\n // in long-term cache.\n isPaginationDone = await this.cacheStrategy().reconcile(resultItems);\n\n hasNextPage = !!queryResult?.pageInfo?.hasNextPage;\n nextCursor = queryResult?.pageInfo?.endCursor;\n if (hasNextPage && nextCursor) {\n this.cursor = nextCursor;\n }\n }\n\n if (this.isPersistent) {\n await this.storePersistenceFlag(30);\n }\n }\n\n private async doCachedQuery(): Promise<ResultItem[]> {\n await this.loadPersistenceFlag();\n if (!this.isPersistent) {\n await this.doPaginatedFetch();\n }\n\n const res = await this.cacheStrategy().finalizeAndReturn();\n if (res.length) {\n return res;\n }\n\n delete this.isPersistent;\n await this.doPaginatedFetch();\n return this.cacheStrategy().finalizeAndReturn();\n }\n\n async loadPersistenceFlag(): Promise<void> {\n const ns = this.getCacheNs();\n const key = `${this.getCacheKey()}:is-persistent`;\n this.isPersistent = await packageCache.get<true>(ns, key);\n }\n\n async storePersistenceFlag(minutes: number): Promise<void> {\n const ns = this.getCacheNs();\n const key = `${this.getCacheKey()}:is-persistent`;\n await packageCache.set(ns, key, true, minutes);\n }\n\n /**\n * This method ensures the only one query is executed\n * to a particular package during single run.\n */\n private doUniqueQuery(): Promise<ResultItem[]> {\n const cacheKey = `github-pending:${this.getCacheNs()}:${this.getCacheKey()}`;\n let resultPromise = memCache.get<Promise<ResultItem[]>>(cacheKey);\n resultPromise ??= this.doCachedQuery();\n memCache.set(cacheKey, resultPromise);\n return resultPromise;\n }\n\n async getItems(): Promise<ResultItem[]> {\n const res = await this.doUniqueQuery();\n return res;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"datasource-fetcher.js","names":["packageCache.get","packageCache.set","memCache.get"],"sources":["../../../../lib/util/github/graphql/datasource-fetcher.ts"],"sourcesContent":["import is from '@sindresorhus/is';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport * as memCache from '../../cache/memory/index.ts';\nimport * as packageCache from '../../cache/package/index.ts';\nimport { buildCacheKey } from '../../cache/package/key.ts';\nimport type { PackageCacheNamespace } from '../../cache/package/types.ts';\nimport type {\n GithubGraphqlResponse,\n GithubHttp,\n GithubHttpOptions,\n} from '../../http/github.ts';\nimport type { HttpResponse } from '../../http/types.ts';\nimport { regEx } from '../../regex.ts';\nimport { getApiBaseUrl } from '../url.ts';\nimport { GithubGraphqlMemoryCacheStrategy } from './cache-strategies/memory-cache-strategy.ts';\nimport { GithubGraphqlPackageCacheStrategy } from './cache-strategies/package-cache-strategy.ts';\nimport type {\n GithubDatasourceItem,\n GithubGraphqlCacheStrategy,\n GithubGraphqlDatasourceAdapter,\n GithubGraphqlPayload,\n GithubGraphqlRepoParams,\n GithubGraphqlRepoResponse,\n GithubPackageConfig,\n RawQueryResponse,\n} from './types.ts';\n\n/**\n * Page sizes to try, from the largest to the smallest.\n *\n * Repositories with many tags can exceed the GitHub GraphQL execution\n * timeout even for small page sizes, hence the low floor.\n *\n * @see https://github.com/renovatebot/renovate/discussions/45248\n */\nconst pageSizes = [100, 50, 25, 10, 5] as const;\n\ntype PageSize = (typeof pageSizes)[number];\n\n/**\n * We know empirically that certain type of GraphQL errors\n * can be fixed by shrinking page size.\n *\n * @see https://github.com/renovatebot/renovate/issues/16343\n */\nfunction isUnknownGraphqlError(err: Error): boolean {\n const { message } = err;\n return message.startsWith('Something went wrong while executing your query.');\n}\n\nfunction canBeSolvedByShrinking(err: Error): boolean {\n const errors: Error[] = err instanceof AggregateError ? err.errors : [err];\n return errors.some(\n (e) => err instanceof ExternalHostError || isUnknownGraphqlError(e),\n );\n}\n\nexport class GithubGraphqlDatasourceFetcher<\n GraphqlItem,\n ResultItem extends GithubDatasourceItem,\n> {\n static async query<T, U extends GithubDatasourceItem>(\n config: GithubPackageConfig,\n http: GithubHttp,\n adapter: GithubGraphqlDatasourceAdapter<T, U>,\n ): Promise<U[]> {\n const instance = new GithubGraphqlDatasourceFetcher<T, U>(\n config,\n http,\n adapter,\n );\n const items = await instance.getItems();\n return items;\n }\n\n private readonly baseUrl: string;\n private readonly repoOwner: string;\n private readonly repoName: string;\n\n private itemsPerQuery: PageSize = pageSizes[0];\n\n private queryCount = 0;\n\n private cursor: string | null = null;\n\n private isPersistent: boolean | undefined;\n private http: GithubHttp;\n private datasourceAdapter: GithubGraphqlDatasourceAdapter<\n GraphqlItem,\n ResultItem\n >;\n\n constructor(\n packageConfig: GithubPackageConfig,\n http: GithubHttp,\n datasourceAdapter: GithubGraphqlDatasourceAdapter<GraphqlItem, ResultItem>,\n ) {\n this.http = http;\n this.datasourceAdapter = datasourceAdapter;\n const { packageName, registryUrl } = packageConfig;\n [this.repoOwner, this.repoName] = packageName.split('/');\n this.baseUrl = getApiBaseUrl(registryUrl).replace(regEx(/\\/v3\\/$/), '/'); // Replace for GHE\n }\n\n private getCacheNs(): PackageCacheNamespace {\n return this.datasourceAdapter.key;\n }\n\n private getCacheKey(): string {\n return buildCacheKey(this.baseUrl, this.repoOwner, this.repoName);\n }\n\n private getRawQueryOptions(): GithubHttpOptions {\n const baseUrl = this.baseUrl;\n const repository = `${this.repoOwner}/${this.repoName}`;\n const query = this.datasourceAdapter.query;\n const variables: GithubGraphqlRepoParams = {\n owner: this.repoOwner,\n name: this.repoName,\n count: this.itemsPerQuery,\n cursor: this.cursor,\n };\n\n return {\n baseUrl,\n repository,\n readOnly: true,\n body: { query, variables },\n };\n }\n\n private async doRawQuery(): Promise<\n RawQueryResponse<GithubGraphqlPayload<GraphqlItem>>\n > {\n const requestOptions = this.getRawQueryOptions();\n\n type GraphqlData = GithubGraphqlRepoResponse<GraphqlItem>;\n type HttpBody = GithubGraphqlResponse<GraphqlData>;\n let httpRes: HttpResponse<HttpBody>;\n try {\n httpRes = await this.http.postJson<HttpBody>('/graphql', requestOptions);\n } catch (err) {\n return [null, err];\n }\n\n const { body } = httpRes;\n const { data, errors } = body;\n\n if (errors?.length) {\n if (errors.length === 1) {\n const { message } = errors[0];\n const err = new Error(message);\n return [null, err];\n }\n const errorInstances = errors.map(({ message }) => new Error(message));\n const err = new AggregateError(errorInstances);\n return [null, err];\n }\n\n if (!data) {\n const msg = 'GitHub GraphQL datasource: failed to obtain data';\n const err = new Error(msg);\n return [null, err];\n }\n\n if (!data.repository) {\n const msg = 'GitHub GraphQL datasource: failed to obtain repository data';\n const err = new Error(msg);\n return [null, err];\n }\n\n if (!data.repository.payload) {\n const msg =\n 'GitHub GraphQL datasource: failed to obtain repository payload data';\n const err = new Error(msg);\n return [null, err];\n }\n\n this.queryCount += 1;\n\n // For values other than explicit `false`,\n // we assume that items can not be cached.\n this.isPersistent ??= data.repository.isRepoPrivate === false;\n\n const res = data.repository.payload;\n return [res, null];\n }\n\n private shrinkPageSize(): boolean {\n const nextIdx = pageSizes.indexOf(this.itemsPerQuery) + 1;\n if (nextIdx >= pageSizes.length) {\n return false;\n }\n\n this.itemsPerQuery = pageSizes[nextIdx];\n return true;\n }\n\n private hasReachedQueryLimit(): boolean {\n return this.queryCount >= 100;\n }\n\n private async doShrinkableQuery(): Promise<\n GithubGraphqlPayload<GraphqlItem>\n > {\n let res: GithubGraphqlPayload<GraphqlItem> | null = null;\n let err: Error | null = null;\n\n while (!res) {\n [res, err] = await this.doRawQuery();\n if (err) {\n if (!canBeSolvedByShrinking(err)) {\n throw err;\n }\n\n const shrinkResult = this.shrinkPageSize();\n if (!shrinkResult) {\n throw err;\n }\n const { body: _, ...options } = this.getRawQueryOptions();\n logger.debug(\n { options, newSize: this.itemsPerQuery },\n 'Shrinking GitHub GraphQL page size after error',\n );\n }\n }\n\n return res;\n }\n\n private _cacheStrategy: GithubGraphqlCacheStrategy<ResultItem> | undefined;\n\n private cacheStrategy(): GithubGraphqlCacheStrategy<ResultItem> {\n if (this._cacheStrategy) {\n return this._cacheStrategy;\n }\n const cacheNs = this.getCacheNs();\n const cacheKey = this.getCacheKey();\n const cachePrivatePackages = GlobalConfig.get('cachePrivatePackages');\n const skipStabilization = !is.undefined(this.datasourceAdapter.maxItems);\n this._cacheStrategy =\n cachePrivatePackages || this.isPersistent\n ? new GithubGraphqlPackageCacheStrategy<ResultItem>(\n cacheNs,\n cacheKey,\n skipStabilization,\n )\n : new GithubGraphqlMemoryCacheStrategy<ResultItem>(\n cacheNs,\n cacheKey,\n skipStabilization,\n );\n return this._cacheStrategy;\n }\n\n /**\n * This method is responsible for data synchronization.\n * It also detects persistence of the package, based on the first page result.\n */\n private async doPaginatedFetch(): Promise<void> {\n let hasNextPage = true;\n let isPaginationDone = false;\n let nextCursor: string | undefined;\n let itemCount = 0;\n const maxItems = this.datasourceAdapter.maxItems;\n while (hasNextPage && !isPaginationDone && !this.hasReachedQueryLimit()) {\n if (!is.undefined(maxItems) && itemCount >= maxItems) {\n break;\n }\n const queryResult = await this.doShrinkableQuery();\n\n const resultItems: ResultItem[] = [];\n for (const node of queryResult.nodes) {\n const item = this.datasourceAdapter.transform(node);\n if (!item) {\n logger.once.info(\n {\n packageName: `${this.repoOwner}/${this.repoName}`,\n baseUrl: this.baseUrl,\n },\n `GitHub GraphQL datasource: skipping empty item`,\n );\n continue;\n }\n resultItems.push(item);\n }\n itemCount += resultItems.length;\n\n // It's important to call `getCacheStrategy()` after `doShrinkableQuery()`\n // because `doShrinkableQuery()` may change `this.isCacheable`.\n //\n // Otherwise, cache items for public packages will never be persisted\n // in long-term cache.\n isPaginationDone = await this.cacheStrategy().reconcile(resultItems);\n\n hasNextPage = !!queryResult?.pageInfo?.hasNextPage;\n nextCursor = queryResult?.pageInfo?.endCursor;\n if (hasNextPage && nextCursor) {\n this.cursor = nextCursor;\n }\n }\n\n if (this.isPersistent) {\n await this.storePersistenceFlag(30);\n }\n }\n\n private async doCachedQuery(): Promise<ResultItem[]> {\n await this.loadPersistenceFlag();\n if (!this.isPersistent) {\n await this.doPaginatedFetch();\n }\n\n const res = await this.cacheStrategy().finalizeAndReturn();\n if (res.length) {\n return res;\n }\n\n delete this.isPersistent;\n await this.doPaginatedFetch();\n return this.cacheStrategy().finalizeAndReturn();\n }\n\n async loadPersistenceFlag(): Promise<void> {\n const ns = this.getCacheNs();\n const key = buildCacheKey(this.getCacheKey(), 'is-persistent');\n this.isPersistent = await packageCache.get<true>(ns, key);\n }\n\n async storePersistenceFlag(minutes: number): Promise<void> {\n const ns = this.getCacheNs();\n const key = buildCacheKey(this.getCacheKey(), 'is-persistent');\n await packageCache.set(ns, key, true, minutes);\n }\n\n /**\n * This method ensures the only one query is executed\n * to a particular package during single run.\n */\n private doUniqueQuery(): Promise<ResultItem[]> {\n const cacheKey = buildCacheKey(\n 'github-pending',\n this.getCacheNs(),\n this.getCacheKey(),\n );\n let resultPromise = memCache.get<Promise<ResultItem[]>>(cacheKey);\n resultPromise ??= this.doCachedQuery();\n memCache.set(cacheKey, resultPromise);\n return resultPromise;\n }\n\n async getItems(): Promise<ResultItem[]> {\n const res = await this.doUniqueQuery();\n return res;\n }\n}\n"],"mappings":"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"}
@@ -1,10 +1,11 @@
1
1
  import { get, set } from "../../cache/memory/index.js";
2
2
  import { clone } from "../../clone.js";
3
+ import { buildCacheKey } from "../../cache/package/key.js";
3
4
  import { AbstractHttpCacheProvider } from "./abstract-http-cache-provider.js";
4
5
  //#region lib/util/http/cache/memory-http-cache-provider.ts
5
6
  var MemoryHttpCacheProvider = class extends AbstractHttpCacheProvider {
6
7
  cacheKey(method, url) {
7
- return `memory-cache-http-provider:${method}:${url}`;
8
+ return buildCacheKey("memory-cache-http-provider", method, url);
8
9
  }
9
10
  load(method, url) {
10
11
  const data = get(this.cacheKey(method, url));
@@ -1 +1 @@
1
- {"version":3,"file":"memory-http-cache-provider.js","names":["memCache.get"],"sources":["../../../../lib/util/http/cache/memory-http-cache-provider.ts"],"sourcesContent":["import * as memCache from '../../cache/memory/index.ts';\nimport { clone } from '../../clone.ts';\nimport type { HttpResponse } from '../types.ts';\nimport { AbstractHttpCacheProvider } from './abstract-http-cache-provider.ts';\nimport type { HttpCache } from './schema.ts';\n\nexport class MemoryHttpCacheProvider extends AbstractHttpCacheProvider {\n private cacheKey(method: string, url: string): string {\n return `memory-cache-http-provider:${method}:${url}`;\n }\n\n protected override load(method: string, url: string): Promise<unknown> {\n const data = memCache.get<HttpCache>(this.cacheKey(method, url));\n const cloned = clone(data); // Ensures cached responses cannot be mutated\n return Promise.resolve(cloned);\n }\n\n protected override persist(\n method: string,\n url: string,\n data: HttpCache,\n ): Promise<void> {\n memCache.set(this.cacheKey(method, url), data);\n return Promise.resolve();\n }\n\n override async bypassServer<T>(\n method: string,\n url: string,\n ): Promise<HttpResponse<T> | null> {\n const cached = await this.get(method, url);\n if (!cached) {\n return null;\n }\n\n return cached.httpResponse as HttpResponse<T>;\n }\n}\n\nexport const memCacheProvider = new MemoryHttpCacheProvider();\n"],"mappings":";;;;AAMA,IAAa,0BAAb,cAA6C,0BAA0B;CACrE,SAAiB,QAAgB,KAAqB;EACpD,OAAO,8BAA8B,OAAO,GAAG;CACjD;CAEA,KAAwB,QAAgB,KAA+B;EACrE,MAAM,OAAOA,IAAwB,KAAK,SAAS,QAAQ,GAAG,CAAC;EAC/D,MAAM,SAAS,MAAM,IAAI;EACzB,OAAO,QAAQ,QAAQ,MAAM;CAC/B;CAEA,QACE,QACA,KACA,MACe;EACf,IAAa,KAAK,SAAS,QAAQ,GAAG,GAAG,IAAI;EAC7C,OAAO,QAAQ,QAAQ;CACzB;CAEA,MAAe,aACb,QACA,KACiC;EACjC,MAAM,SAAS,MAAM,KAAK,IAAI,QAAQ,GAAG;EACzC,IAAI,CAAC,QACH,OAAO;EAGT,OAAO,OAAO;CAChB;AACF;AAEA,MAAa,mBAAmB,IAAI,wBAAwB"}
1
+ {"version":3,"file":"memory-http-cache-provider.js","names":["memCache.get"],"sources":["../../../../lib/util/http/cache/memory-http-cache-provider.ts"],"sourcesContent":["import * as memCache from '../../cache/memory/index.ts';\nimport { buildCacheKey } from '../../cache/package/key.ts';\nimport { clone } from '../../clone.ts';\nimport type { HttpResponse } from '../types.ts';\nimport { AbstractHttpCacheProvider } from './abstract-http-cache-provider.ts';\nimport type { HttpCache } from './schema.ts';\n\nexport class MemoryHttpCacheProvider extends AbstractHttpCacheProvider {\n private cacheKey(method: string, url: string): string {\n return buildCacheKey('memory-cache-http-provider', method, url);\n }\n\n protected override load(method: string, url: string): Promise<unknown> {\n const data = memCache.get<HttpCache>(this.cacheKey(method, url));\n const cloned = clone(data); // Ensures cached responses cannot be mutated\n return Promise.resolve(cloned);\n }\n\n protected override persist(\n method: string,\n url: string,\n data: HttpCache,\n ): Promise<void> {\n memCache.set(this.cacheKey(method, url), data);\n return Promise.resolve();\n }\n\n override async bypassServer<T>(\n method: string,\n url: string,\n ): Promise<HttpResponse<T> | null> {\n const cached = await this.get(method, url);\n if (!cached) {\n return null;\n }\n\n return cached.httpResponse as HttpResponse<T>;\n }\n}\n\nexport const memCacheProvider = new MemoryHttpCacheProvider();\n"],"mappings":";;;;;AAOA,IAAa,0BAAb,cAA6C,0BAA0B;CACrE,SAAiB,QAAgB,KAAqB;EACpD,OAAO,cAAc,8BAA8B,QAAQ,GAAG;CAChE;CAEA,KAAwB,QAAgB,KAA+B;EACrE,MAAM,OAAOA,IAAwB,KAAK,SAAS,QAAQ,GAAG,CAAC;EAC/D,MAAM,SAAS,MAAM,IAAI;EACzB,OAAO,QAAQ,QAAQ,MAAM;CAC/B;CAEA,QACE,QACA,KACA,MACe;EACf,IAAa,KAAK,SAAS,QAAQ,GAAG,GAAG,IAAI;EAC7C,OAAO,QAAQ,QAAQ;CACzB;CAEA,MAAe,aACb,QACA,KACiC;EACjC,MAAM,SAAS,MAAM,KAAK,IAAI,QAAQ,GAAG;EACzC,IAAI,CAAC,QACH,OAAO;EAGT,OAAO,OAAO;CAChB;AACF;AAEA,MAAa,mBAAmB,IAAI,wBAAwB"}
@@ -2,6 +2,7 @@ import { regEx } from "../../regex.js";
2
2
  import { GlobalConfig } from "../../../config/global.js";
3
3
  import { logger } from "../../../logger/index.js";
4
4
  import { HttpCacheStats } from "../../stats.js";
5
+ import { buildCacheKey } from "../../cache/package/key.js";
5
6
  import { resolveTtlValues } from "../../cache/package/ttl.js";
6
7
  import { get, setWithRawTtl } from "../../cache/package/index.js";
7
8
  import { copyResponse } from "../util.js";
@@ -32,7 +33,7 @@ var PackageHttpCacheProvider = class extends AbstractHttpCacheProvider {
32
33
  return hardTtlMinutes;
33
34
  }
34
35
  cacheKey(method, url) {
35
- if (method !== "get") return `${method}:${url}`;
36
+ if (method !== "get") return buildCacheKey(method, url);
36
37
  return url;
37
38
  }
38
39
  async load(method, url) {