renovate 44.210.2 → 44.211.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) 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/utils.js +2 -1
  4. package/dist/config/utils.js.map +1 -1
  5. package/dist/config/validation-helpers/regex-glob-matchers.js.map +1 -1
  6. package/dist/config/validation-helpers/utils.js +5 -1
  7. package/dist/config/validation-helpers/utils.js.map +1 -1
  8. package/dist/config/validation.js +8 -2
  9. package/dist/config/validation.js.map +1 -1
  10. package/dist/config-validator.js +1 -1
  11. package/dist/config-validator.js.map +1 -1
  12. package/dist/global-config-option-defaults.generated.js +1 -1
  13. package/dist/global-config-option-defaults.generated.js.map +1 -1
  14. package/dist/instrumentation/index.js +3 -2
  15. package/dist/instrumentation/index.js.map +1 -1
  16. package/dist/logger/bunyan.js +3 -2
  17. package/dist/logger/bunyan.js.map +1 -1
  18. package/dist/logger/pretty-stdout.js +2 -1
  19. package/dist/logger/pretty-stdout.js.map +1 -1
  20. package/dist/modules/datasource/apk/index.js +2 -2
  21. package/dist/modules/datasource/apk/index.js.map +1 -1
  22. package/dist/modules/datasource/artifactory/index.js +2 -3
  23. package/dist/modules/datasource/artifactory/index.js.map +1 -1
  24. package/dist/modules/datasource/bazel/index.js +2 -1
  25. package/dist/modules/datasource/bazel/index.js.map +1 -1
  26. package/dist/modules/datasource/cdnjs/index.js +2 -1
  27. package/dist/modules/datasource/cdnjs/index.js.map +1 -1
  28. package/dist/modules/datasource/conda/index.js +2 -1
  29. package/dist/modules/datasource/conda/index.js.map +1 -1
  30. package/dist/modules/datasource/crate/index.js +2 -1
  31. package/dist/modules/datasource/crate/index.js.map +1 -1
  32. package/dist/modules/datasource/dart-version/index.js +2 -1
  33. package/dist/modules/datasource/dart-version/index.js.map +1 -1
  34. package/dist/modules/datasource/datasource.js +2 -2
  35. package/dist/modules/datasource/datasource.js.map +1 -1
  36. package/dist/modules/datasource/deb/url.js +3 -1
  37. package/dist/modules/datasource/deb/url.js.map +1 -1
  38. package/dist/modules/datasource/devbox/index.js +2 -1
  39. package/dist/modules/datasource/devbox/index.js.map +1 -1
  40. package/dist/modules/datasource/docker/common.js +10 -8
  41. package/dist/modules/datasource/docker/common.js.map +1 -1
  42. package/dist/modules/datasource/docker/ecr.js +2 -1
  43. package/dist/modules/datasource/docker/ecr.js.map +1 -1
  44. package/dist/modules/datasource/docker/index.js +20 -17
  45. package/dist/modules/datasource/docker/index.js.map +1 -1
  46. package/dist/modules/datasource/gitea-tags/base.js +2 -3
  47. package/dist/modules/datasource/gitea-tags/base.js.map +1 -1
  48. package/dist/modules/datasource/github-tags/index.js +2 -1
  49. package/dist/modules/datasource/github-tags/index.js.map +1 -1
  50. package/dist/modules/datasource/gitlab-tags/index.js +2 -3
  51. package/dist/modules/datasource/gitlab-tags/index.js.map +1 -1
  52. package/dist/modules/datasource/go/base.js +1 -1
  53. package/dist/modules/datasource/go/base.js.map +1 -1
  54. package/dist/modules/datasource/go/common.js +8 -2
  55. package/dist/modules/datasource/go/common.js.map +1 -1
  56. package/dist/modules/datasource/go/env.js +2 -1
  57. package/dist/modules/datasource/go/env.js.map +1 -1
  58. package/dist/modules/datasource/go/releases-goproxy.js +7 -5
  59. package/dist/modules/datasource/go/releases-goproxy.js.map +1 -1
  60. package/dist/modules/datasource/helm/index.js +2 -1
  61. package/dist/modules/datasource/helm/index.js.map +1 -1
  62. package/dist/modules/datasource/hexpm-bob/index.js +2 -1
  63. package/dist/modules/datasource/hexpm-bob/index.js.map +1 -1
  64. package/dist/modules/datasource/index.js +4 -3
  65. package/dist/modules/datasource/index.js.map +1 -1
  66. package/dist/modules/datasource/java-version/adoptium.js +3 -2
  67. package/dist/modules/datasource/java-version/adoptium.js.map +1 -1
  68. package/dist/modules/datasource/java-version/graalvm.js +2 -1
  69. package/dist/modules/datasource/java-version/graalvm.js.map +1 -1
  70. package/dist/modules/datasource/maven/index.js.map +1 -1
  71. package/dist/modules/datasource/maven/util.js +7 -10
  72. package/dist/modules/datasource/maven/util.js.map +1 -1
  73. package/dist/modules/datasource/npm/npmrc.js +2 -2
  74. package/dist/modules/datasource/npm/npmrc.js.map +1 -1
  75. package/dist/modules/datasource/nuget/v3.js +3 -5
  76. package/dist/modules/datasource/nuget/v3.js.map +1 -1
  77. package/dist/modules/datasource/packagist/index.js +4 -5
  78. package/dist/modules/datasource/packagist/index.js.map +1 -1
  79. package/dist/modules/datasource/pod/index.js +4 -4
  80. package/dist/modules/datasource/pod/index.js.map +1 -1
  81. package/dist/modules/datasource/pypi/index.js +19 -11
  82. package/dist/modules/datasource/pypi/index.js.map +1 -1
  83. package/dist/modules/datasource/python-version/index.js +2 -3
  84. package/dist/modules/datasource/python-version/index.js.map +1 -1
  85. package/dist/modules/datasource/repology/index.js +4 -3
  86. package/dist/modules/datasource/repology/index.js.map +1 -1
  87. package/dist/modules/datasource/rpm/providers/common.js +3 -1
  88. package/dist/modules/datasource/rpm/providers/common.js.map +1 -1
  89. package/dist/modules/datasource/rubygems/index.js +2 -5
  90. package/dist/modules/datasource/rubygems/index.js.map +1 -1
  91. package/dist/modules/datasource/rubygems/versions-endpoint-cache.js +13 -18
  92. package/dist/modules/datasource/rubygems/versions-endpoint-cache.js.map +1 -1
  93. package/dist/modules/datasource/terraform-module/base.js +2 -1
  94. package/dist/modules/datasource/terraform-module/base.js.map +1 -1
  95. package/dist/modules/datasource/terraform-provider/index.js +2 -3
  96. package/dist/modules/datasource/terraform-provider/index.js.map +1 -1
  97. package/dist/modules/manager/bazel-module/parser/context.js +0 -1
  98. package/dist/modules/manager/bazel-module/parser/context.js.map +1 -1
  99. package/dist/modules/manager/bundler/host-rules.js +4 -1
  100. package/dist/modules/manager/bundler/host-rules.js.map +1 -1
  101. package/dist/modules/manager/composer/range.js +1 -1
  102. package/dist/modules/manager/composer/range.js.map +1 -1
  103. package/dist/modules/manager/custom/utils.js +3 -1
  104. package/dist/modules/manager/custom/utils.js.map +1 -1
  105. package/dist/modules/manager/devbox/schema.js +2 -1
  106. package/dist/modules/manager/devbox/schema.js.map +1 -1
  107. package/dist/modules/manager/dockerfile/extract.js +10 -2
  108. package/dist/modules/manager/dockerfile/extract.js.map +1 -1
  109. package/dist/modules/manager/fingerprint.generated.js +1 -1
  110. package/dist/modules/manager/fingerprint.generated.js.map +1 -1
  111. package/dist/modules/manager/github-actions/parse.js +2 -1
  112. package/dist/modules/manager/github-actions/parse.js.map +1 -1
  113. package/dist/modules/manager/gomod/artifacts.js +5 -2
  114. package/dist/modules/manager/gomod/artifacts.js.map +1 -1
  115. package/dist/modules/manager/gradle/artifacts.js +5 -2
  116. package/dist/modules/manager/gradle/artifacts.js.map +1 -1
  117. package/dist/modules/manager/gradle/utils.js +2 -1
  118. package/dist/modules/manager/gradle/utils.js.map +1 -1
  119. package/dist/modules/manager/gradle-wrapper/utils.js +9 -5
  120. package/dist/modules/manager/gradle-wrapper/utils.js.map +1 -1
  121. package/dist/modules/manager/helm-values/util.js +1 -1
  122. package/dist/modules/manager/helm-values/util.js.map +1 -1
  123. package/dist/modules/manager/helmfile/artifacts.js +1 -1
  124. package/dist/modules/manager/helmfile/artifacts.js.map +1 -1
  125. package/dist/modules/manager/helmv3/artifacts.js +1 -1
  126. package/dist/modules/manager/helmv3/artifacts.js.map +1 -1
  127. package/dist/modules/manager/maven/extract.js +5 -2
  128. package/dist/modules/manager/maven/extract.js.map +1 -1
  129. package/dist/modules/manager/maven-wrapper/artifacts.js +3 -2
  130. package/dist/modules/manager/maven-wrapper/artifacts.js.map +1 -1
  131. package/dist/modules/manager/mise/artifacts.js +2 -1
  132. package/dist/modules/manager/mise/artifacts.js.map +1 -1
  133. package/dist/modules/manager/mise/extract.js.map +1 -1
  134. package/dist/modules/manager/npm/artifacts.js +3 -1
  135. package/dist/modules/manager/npm/artifacts.js.map +1 -1
  136. package/dist/modules/manager/npm/extract/common/dependency.js +4 -1
  137. package/dist/modules/manager/npm/extract/common/dependency.js.map +1 -1
  138. package/dist/modules/manager/npm/extract/common/package-file.js +2 -1
  139. package/dist/modules/manager/npm/extract/common/package-file.js.map +1 -1
  140. package/dist/modules/manager/npm/extract/index.js.map +1 -1
  141. package/dist/modules/manager/npm/extract/post/locked-versions.js.map +1 -1
  142. package/dist/modules/manager/npm/npmrc.js +2 -1
  143. package/dist/modules/manager/npm/npmrc.js.map +1 -1
  144. package/dist/modules/manager/npm/post-update/index.js +2 -1
  145. package/dist/modules/manager/npm/post-update/index.js.map +1 -1
  146. package/dist/modules/manager/npm/post-update/npm.js +2 -3
  147. package/dist/modules/manager/npm/post-update/npm.js.map +1 -1
  148. package/dist/modules/manager/npm/post-update/yarn.js.map +1 -1
  149. package/dist/modules/manager/npm/schema.js +6 -2
  150. package/dist/modules/manager/npm/schema.js.map +1 -1
  151. package/dist/modules/manager/npm/update/dependency/index.js +3 -2
  152. package/dist/modules/manager/npm/update/dependency/index.js.map +1 -1
  153. package/dist/modules/manager/npm/update/locked-dependency/common/parent-version.js +6 -2
  154. package/dist/modules/manager/npm/update/locked-dependency/common/parent-version.js.map +1 -1
  155. package/dist/modules/manager/npm/update/locked-dependency/package-lock/get-locked.js +2 -1
  156. package/dist/modules/manager/npm/update/locked-dependency/package-lock/get-locked.js.map +1 -1
  157. package/dist/modules/manager/nuget/package-tree.js +2 -1
  158. package/dist/modules/manager/nuget/package-tree.js.map +1 -1
  159. package/dist/modules/manager/paket/update-locked.js +4 -1
  160. package/dist/modules/manager/paket/update-locked.js.map +1 -1
  161. package/dist/modules/manager/pipenv/extract.js +4 -1
  162. package/dist/modules/manager/pipenv/extract.js.map +1 -1
  163. package/dist/modules/platform/azure/azure-helper.js +2 -1
  164. package/dist/modules/platform/azure/azure-helper.js.map +1 -1
  165. package/dist/modules/platform/azure/index.js +7 -3
  166. package/dist/modules/platform/azure/index.js.map +1 -1
  167. package/dist/modules/platform/bitbucket/index.js +13 -6
  168. package/dist/modules/platform/bitbucket/index.js.map +1 -1
  169. package/dist/modules/platform/bitbucket-server/index.js +13 -9
  170. package/dist/modules/platform/bitbucket-server/index.js.map +1 -1
  171. package/dist/modules/platform/codecommit/index.js +2 -2
  172. package/dist/modules/platform/codecommit/index.js.map +1 -1
  173. package/dist/modules/platform/gerrit/client.js +4 -1
  174. package/dist/modules/platform/gerrit/client.js.map +1 -1
  175. package/dist/modules/platform/gerrit/index.js +3 -2
  176. package/dist/modules/platform/gerrit/index.js.map +1 -1
  177. package/dist/modules/platform/gitea/gitea-helper.js +5 -4
  178. package/dist/modules/platform/gitea/gitea-helper.js.map +1 -1
  179. package/dist/modules/platform/gitea/index.js +11 -4
  180. package/dist/modules/platform/gitea/index.js.map +1 -1
  181. package/dist/modules/platform/github/index.js +36 -23
  182. package/dist/modules/platform/github/index.js.map +1 -1
  183. package/dist/modules/platform/gitlab/index.js +16 -9
  184. package/dist/modules/platform/gitlab/index.js.map +1 -1
  185. package/dist/modules/platform/scm-manager/index.js +4 -1
  186. package/dist/modules/platform/scm-manager/index.js.map +1 -1
  187. package/dist/modules/platform/scm-manager/utils.js +2 -1
  188. package/dist/modules/platform/scm-manager/utils.js.map +1 -1
  189. package/dist/modules/versioning/cargo/index.js.map +1 -1
  190. package/dist/modules/versioning/composer/index.js +2 -1
  191. package/dist/modules/versioning/composer/index.js.map +1 -1
  192. package/dist/modules/versioning/conan/common.js +4 -1
  193. package/dist/modules/versioning/conan/common.js.map +1 -1
  194. package/dist/modules/versioning/debian/index.js +2 -1
  195. package/dist/modules/versioning/debian/index.js.map +1 -1
  196. package/dist/modules/versioning/gradle/compare.js +2 -1
  197. package/dist/modules/versioning/gradle/compare.js.map +1 -1
  198. package/dist/modules/versioning/hex/index.js +2 -1
  199. package/dist/modules/versioning/hex/index.js.map +1 -1
  200. package/dist/modules/versioning/julia/index.js.map +1 -1
  201. package/dist/modules/versioning/maven/compare.js +17 -7
  202. package/dist/modules/versioning/maven/compare.js.map +1 -1
  203. package/dist/modules/versioning/npm/index.js +2 -1
  204. package/dist/modules/versioning/npm/index.js.map +1 -1
  205. package/dist/modules/versioning/npm/range.js.map +1 -1
  206. package/dist/modules/versioning/paket/index.js +2 -1
  207. package/dist/modules/versioning/paket/index.js.map +1 -1
  208. package/dist/modules/versioning/paket/range.js +7 -3
  209. package/dist/modules/versioning/paket/range.js.map +1 -1
  210. package/dist/modules/versioning/pep440/index.js +2 -1
  211. package/dist/modules/versioning/pep440/index.js.map +1 -1
  212. package/dist/modules/versioning/poetry/index.js +2 -1
  213. package/dist/modules/versioning/poetry/index.js.map +1 -1
  214. package/dist/modules/versioning/regex/index.js +1 -1
  215. package/dist/modules/versioning/regex/index.js.map +1 -1
  216. package/dist/modules/versioning/rez/index.js +2 -1
  217. package/dist/modules/versioning/rez/index.js.map +1 -1
  218. package/dist/modules/versioning/vcpkg/index.js +2 -1
  219. package/dist/modules/versioning/vcpkg/index.js.map +1 -1
  220. package/dist/util/cache/package/impl/base.js +2 -1
  221. package/dist/util/cache/package/impl/base.js.map +1 -1
  222. package/dist/util/cache/package/with-cache.js +2 -1
  223. package/dist/util/cache/package/with-cache.js.map +1 -1
  224. package/dist/util/check-token.js +7 -4
  225. package/dist/util/check-token.js.map +1 -1
  226. package/dist/util/exec/utils.js +4 -1
  227. package/dist/util/exec/utils.js.map +1 -1
  228. package/dist/util/git/auth.js +5 -1
  229. package/dist/util/git/auth.js.map +1 -1
  230. package/dist/util/git/error.js.map +1 -1
  231. package/dist/util/host-rules.js +5 -3
  232. package/dist/util/host-rules.js.map +1 -1
  233. package/dist/util/http/cache/abstract-http-cache-provider.js +3 -2
  234. package/dist/util/http/cache/abstract-http-cache-provider.js.map +1 -1
  235. package/dist/util/http/cache/package-http-cache-provider.js +2 -1
  236. package/dist/util/http/cache/package-http-cache-provider.js.map +1 -1
  237. package/dist/util/http/github.js +15 -11
  238. package/dist/util/http/github.js.map +1 -1
  239. package/dist/util/http/gitlab.js +5 -4
  240. package/dist/util/http/gitlab.js.map +1 -1
  241. package/dist/util/http/http.js +2 -1
  242. package/dist/util/http/http.js.map +1 -1
  243. package/dist/util/http/jwt.js +2 -1
  244. package/dist/util/http/jwt.js.map +1 -1
  245. package/dist/util/http/retry-after.js +2 -1
  246. package/dist/util/http/retry-after.js.map +1 -1
  247. package/dist/util/http/status.js +95 -0
  248. package/dist/util/http/status.js.map +1 -0
  249. package/dist/util/merge-confidence/index.js +3 -2
  250. package/dist/util/merge-confidence/index.js.map +1 -1
  251. package/dist/util/package-rules/current-version.js +4 -1
  252. package/dist/util/package-rules/current-version.js.map +1 -1
  253. package/dist/util/package-rules/index.js +7 -3
  254. package/dist/util/package-rules/index.js.map +1 -1
  255. package/dist/util/schema-utils/index.js +5 -0
  256. package/dist/util/schema-utils/index.js.map +1 -1
  257. package/dist/workers/global/config/parse/host-rules-from-env.js +2 -1
  258. package/dist/workers/global/config/parse/host-rules-from-env.js.map +1 -1
  259. package/dist/workers/repository/common.js +4 -1
  260. package/dist/workers/repository/common.js.map +1 -1
  261. package/dist/workers/repository/config-migration/branch/index.js +2 -1
  262. package/dist/workers/repository/config-migration/branch/index.js.map +1 -1
  263. package/dist/workers/repository/dependency-dashboard.js +6 -2
  264. package/dist/workers/repository/dependency-dashboard.js.map +1 -1
  265. package/dist/workers/repository/finalize/repository-statistics.js +4 -1
  266. package/dist/workers/repository/finalize/repository-statistics.js.map +1 -1
  267. package/dist/workers/repository/init/merge.js +13 -3
  268. package/dist/workers/repository/init/merge.js.map +1 -1
  269. package/dist/workers/repository/onboarding/branch/check.js +2 -1
  270. package/dist/workers/repository/onboarding/branch/check.js.map +1 -1
  271. package/dist/workers/repository/onboarding/pr/pr-list.js +4 -2
  272. package/dist/workers/repository/onboarding/pr/pr-list.js.map +1 -1
  273. package/dist/workers/repository/process/extract-update.js +4 -1
  274. package/dist/workers/repository/process/extract-update.js.map +1 -1
  275. package/dist/workers/repository/process/lookup/digest.js +2 -1
  276. package/dist/workers/repository/process/lookup/digest.js.map +1 -1
  277. package/dist/workers/repository/process/lookup/generate.js +1 -1
  278. package/dist/workers/repository/process/lookup/generate.js.map +1 -1
  279. package/dist/workers/repository/process/lookup/index.js +4 -1
  280. package/dist/workers/repository/process/lookup/index.js.map +1 -1
  281. package/dist/workers/repository/process/lookup/utils.js +7 -1
  282. package/dist/workers/repository/process/lookup/utils.js.map +1 -1
  283. package/dist/workers/repository/process/vulnerabilities.js +10 -3
  284. package/dist/workers/repository/process/vulnerabilities.js.map +1 -1
  285. package/dist/workers/repository/reconfigure/index.js +2 -1
  286. package/dist/workers/repository/reconfigure/index.js.map +1 -1
  287. package/dist/workers/repository/update/branch/auto-replace.js +6 -2
  288. package/dist/workers/repository/update/branch/auto-replace.js.map +1 -1
  289. package/dist/workers/repository/update/branch/errors.js +2 -1
  290. package/dist/workers/repository/update/branch/errors.js.map +1 -1
  291. package/dist/workers/repository/update/branch/execute-post-upgrade-commands.js +2 -2
  292. package/dist/workers/repository/update/branch/execute-post-upgrade-commands.js.map +1 -1
  293. package/dist/workers/repository/update/branch/get-updated.js +1 -2
  294. package/dist/workers/repository/update/branch/get-updated.js.map +1 -1
  295. package/dist/workers/repository/update/branch/index.js +2 -1
  296. package/dist/workers/repository/update/branch/index.js.map +1 -1
  297. package/dist/workers/repository/update/branch/status-checks.js +2 -1
  298. package/dist/workers/repository/update/branch/status-checks.js.map +1 -1
  299. package/dist/workers/repository/update/pr/body/index.js.map +1 -1
  300. package/dist/workers/repository/update/pr/changelog/release-notes.js +3 -2
  301. package/dist/workers/repository/update/pr/changelog/release-notes.js.map +1 -1
  302. package/dist/workers/repository/update/pr/index.js +7 -3
  303. package/dist/workers/repository/update/pr/index.js.map +1 -1
  304. package/dist/workers/repository/updates/generate.js +6 -3
  305. package/dist/workers/repository/updates/generate.js.map +1 -1
  306. package/package.json +2 -2
  307. package/renovate-schema.json +2 -2
@@ -6,6 +6,7 @@ import { isDockerDigest } from "../../../util/string-match.js";
6
6
  import { logger } from "../../../logger/index.js";
7
7
  import { buildCacheKey } from "../../../util/cache/package/key.js";
8
8
  import { ensurePathPrefix, joinUrlParts, parseLinkHeader, parseUrl } from "../../../util/url.js";
9
+ import { isBadRequest, isNotFound, isRateLimited, isServerError, isUnauthorized } from "../../../util/http/status.js";
9
10
  import { ExternalHostError } from "../../../types/errors/external-host-error.js";
10
11
  import { id } from "../../versioning/docker/index.js";
11
12
  import { withCache } from "../../../util/cache/package/with-cache.js";
@@ -79,7 +80,7 @@ var DockerDatasource = class DockerDatasource extends Datasource {
79
80
  });
80
81
  } catch (err) /* istanbul ignore next */ {
81
82
  if (err instanceof ExternalHostError) throw err;
82
- if (err.statusCode === 401) {
83
+ if (isUnauthorized(err)) {
83
84
  logger.debug({
84
85
  registryHost,
85
86
  dockerRepository
@@ -87,7 +88,7 @@ var DockerDatasource = class DockerDatasource extends Datasource {
87
88
  logger.debug({ err });
88
89
  return null;
89
90
  }
90
- if (err.statusCode === 404) {
91
+ if (isNotFound(err)) {
91
92
  logger.debug({
92
93
  err,
93
94
  registryHost,
@@ -96,8 +97,8 @@ var DockerDatasource = class DockerDatasource extends Datasource {
96
97
  }, "Docker Manifest is unknown");
97
98
  return null;
98
99
  }
99
- if (err.statusCode === 429 && isDockerHost(registryHost)) throw new ExternalHostError(err);
100
- if (err.statusCode >= 500 && err.statusCode < 600) throw new ExternalHostError(err);
100
+ if (isRateLimited(err) && isDockerHost(registryHost)) throw new ExternalHostError(err);
101
+ if (isServerError(err)) throw new ExternalHostError(err);
101
102
  if (err.code === "ETIMEDOUT") {
102
103
  logger.debug({ registryHost }, "Timeout when attempting to connect to docker registry");
103
104
  logger.debug({ err });
@@ -208,7 +209,7 @@ var DockerDatasource = class DockerDatasource extends Datasource {
208
209
  } catch (_err) {
209
210
  const err = _err instanceof ExternalHostError ? _err.err : /* istanbul ignore next: can never happen */ _err;
210
211
  // v8 ignore else -- needs a non-5xx failure from the manifest request
211
- if (typeof err.statusCode === "number" && err.statusCode >= 500 && err.statusCode < 600) return null;
212
+ if (isServerError(err)) return null;
212
213
  /* istanbul ignore next */
213
214
  throw _err;
214
215
  }
@@ -217,13 +218,13 @@ var DockerDatasource = class DockerDatasource extends Datasource {
217
218
  if (!configDigest) return null;
218
219
  const configResponse = await this.getImageConfig(registryHost, dockerRepository, configDigest);
219
220
  // v8 ignore else -- needs a config blob with neither key
220
- if (configResponse && ("config" in configResponse.body || "architecture" in configResponse.body)) {
221
+ if (configResponse && ["config", "architecture"].some((key) => key in configResponse.body)) {
221
222
  const architecture = configResponse.body.architecture ?? null;
222
223
  logger.debug(`Current digest ${currentDigest} relates to architecture ${architecture ?? "null"}`);
223
224
  return architecture;
224
225
  }
225
226
  } catch (err) /* istanbul ignore next */ {
226
- if (err.statusCode !== 404 || err.message === "page-not-found") throw err;
227
+ if (!isNotFound(err) || err.message === "page-not-found") throw err;
227
228
  logger.debug({
228
229
  registryHost,
229
230
  dockerRepository,
@@ -310,19 +311,19 @@ var DockerDatasource = class DockerDatasource extends Datasource {
310
311
  return labels;
311
312
  } catch (err) /* istanbul ignore next: should be tested in future */ {
312
313
  if (err instanceof ExternalHostError) throw err;
313
- if (err.statusCode === 400 || err.statusCode === 401) logger.debug({
314
+ if (isBadRequest(err) || isUnauthorized(err)) logger.debug({
314
315
  registryHost,
315
316
  dockerRepository,
316
317
  err
317
318
  }, "Unauthorized docker lookup");
318
- else if (err.statusCode === 404) logger.warn({
319
+ else if (isNotFound(err)) logger.warn({
319
320
  err,
320
321
  registryHost,
321
322
  dockerRepository,
322
323
  tag
323
324
  }, "Config Manifest is unknown");
324
- else if (err.statusCode === 429 && isDockerHost(registryHost)) logger.warn({ err }, "docker registry failure: too many requests");
325
- else if (err.statusCode >= 500 && err.statusCode < 600) logger.debug({
325
+ else if (isRateLimited(err) && isDockerHost(registryHost)) logger.warn({ err }, "docker registry failure: too many requests");
326
+ else if (isServerError(err)) logger.debug({
326
327
  err,
327
328
  registryHost,
328
329
  dockerRepository,
@@ -441,7 +442,7 @@ var DockerDatasource = class DockerDatasource extends Datasource {
441
442
  if (isQuay) try {
442
443
  tags = await this.getTagsQuayRegistry(registryHost, dockerRepository);
443
444
  } catch (err) {
444
- if (err.statusCode === 401) {
445
+ if (isUnauthorized(err)) {
445
446
  logger.debug({
446
447
  registryHost,
447
448
  dockerRepository
@@ -453,18 +454,19 @@ var DockerDatasource = class DockerDatasource extends Datasource {
453
454
  return tags;
454
455
  } catch (_err) /* istanbul ignore next */ {
455
456
  const err = _err instanceof ExternalHostError ? _err.err : _err;
456
- if ((err.statusCode === 404 || err.message === "page-not-found") && !dockerRepository.includes("/")) {
457
+ const notFound = isNotFound(err) || err.message === "page-not-found";
458
+ if (notFound && !dockerRepository.includes("/")) {
457
459
  logger.debug(`Retrying Tags for ${registryHost}/${dockerRepository} using library/ prefix`);
458
460
  return this.getTags(registryHost, `library/${dockerRepository}`);
459
461
  }
460
- if ((err.statusCode === 404 || err.message === "page-not-found") && isArtifactoryServer(err.response) && dockerRepository.split("/").length === 2) {
462
+ if (notFound && isArtifactoryServer(err.response) && dockerRepository.split("/").length === 2) {
461
463
  logger.debug(`JFrog Artifactory: Retrying Tags for ${registryHost}/${dockerRepository} using library/ path between JFrog virtual repository and image`);
462
464
  const dockerRepositoryParts = dockerRepository.split("/");
463
465
  const jfrogRepository = dockerRepositoryParts[0];
464
466
  const dockerImage = dockerRepositoryParts[1];
465
467
  return this.getTags(registryHost, `${jfrogRepository}/library/${dockerImage}`);
466
468
  }
467
- if (err.statusCode === 429 && isDockerHost(registryHost)) {
469
+ if (isRateLimited(err) && isDockerHost(registryHost)) {
468
470
  logger.warn({
469
471
  registryHost,
470
472
  dockerRepository,
@@ -472,7 +474,7 @@ var DockerDatasource = class DockerDatasource extends Datasource {
472
474
  }, "docker registry failure: too many requests");
473
475
  throw new ExternalHostError(err);
474
476
  }
475
- if (err.statusCode >= 500 && err.statusCode < 600) {
477
+ if (isServerError(err)) {
476
478
  logger.warn({
477
479
  registryHost,
478
480
  dockerRepository,
@@ -530,7 +532,8 @@ var DockerDatasource = class DockerDatasource extends Datasource {
530
532
  manifestResponse = await this.getManifestResponse(registryHost, dockerRepository, newTag, "head");
531
533
  if (manifestResponse && hasKey("docker-content-digest", manifestResponse.headers)) digest = manifestResponse.headers["docker-content-digest"] || null;
532
534
  }
533
- if (isNonEmptyString(architecture) || manifestResponse && !hasKey("docker-content-digest", manifestResponse.headers)) {
535
+ const lacksContentDigest = manifestResponse && !hasKey("docker-content-digest", manifestResponse.headers);
536
+ if (isNonEmptyString(architecture) || lacksContentDigest) {
534
537
  if (isNonEmptyString(architecture) && registryHost === "https://index.docker.io") {
535
538
  const cachedDigest = (await DockerHubCache.init(dockerRepository)).getArchDigestForTag(newTag, architecture);
536
539
  if (cachedDigest) return cachedDigest;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["dockerVersioningId","HttpError"],"sources":["../../../../lib/modules/datasource/docker/index.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { PAGE_NOT_FOUND_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { buildCacheKey } from '../../../util/cache/package/key.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { hasKey } from '../../../util/object.ts';\nimport { type AsyncResult, Result } from '../../../util/result.ts';\nimport { isDockerDigest } from '../../../util/string-match.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport {\n ensurePathPrefix,\n joinUrlParts,\n parseLinkHeader,\n parseUrl,\n} from '../../../util/url.ts';\nimport { id as dockerVersioningId } from '../../versioning/docker/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type {\n DigestConfig,\n GetReleasesConfig,\n Release,\n ReleaseResult,\n} from '../types.ts';\nimport {\n isArtifactoryServer,\n isCrossOriginPaginationAllowed,\n resolvePaginationUrl,\n} from '../util.ts';\nimport {\n DOCKER_HUB,\n dockerDatasourceId,\n extractDigestFromResponseBody,\n findHelmSourceUrl,\n findLatestStable,\n getAuthHeaders,\n getRegistryRepository,\n gitRefLabel,\n imageUrlLabel,\n isDockerHost,\n sourceLabel,\n sourceLabels,\n} from './common.ts';\nimport { DockerHubCache } from './dockerhub-cache.ts';\nimport { ecrPublicRegex, ecrRegex, isECRMaxResultsError } from './ecr.ts';\nimport type {\n DistributionManifest,\n Manifest,\n OciImageManifest,\n} from './schema.ts';\nimport {\n DockerHubTagsPage,\n ManifestJson,\n OciHelmConfig,\n OciImageConfig,\n QuayTagsResponse,\n RegistryTagsList,\n} from './schema.ts';\n\nconst defaultConfig = {\n commitMessageTopic: '{{{depName}}} Docker tag',\n commitMessageExtra:\n 'to {{#if isPinDigest}}{{{newDigestShort}}}{{else}}{{#if isMajor}}{{{prettyNewMajor}}}{{else}}{{{prettyNewVersion}}}{{/if}}{{/if}}',\n digest: {\n branchTopic: '{{{depNameSanitized}}}-{{{currentValue}}}',\n commitMessageExtra: 'to {{newDigestShort}}',\n commitMessageTopic:\n '{{{depName}}}{{#if currentValue}}:{{{currentValue}}}{{/if}} Docker digest',\n group: {\n commitMessageTopic: '{{{groupName}}}',\n commitMessageExtra: '',\n },\n },\n pin: {\n commitMessageExtra: '',\n groupName: 'Docker digests',\n group: {\n commitMessageTopic: '{{{groupName}}}',\n branchTopic: 'digests-pin',\n },\n },\n};\n\nexport class DockerDatasource extends Datasource {\n static readonly id = dockerDatasourceId;\n\n override readonly defaultVersioning = dockerVersioningId;\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return [DOCKER_HUB];\n }\n\n override readonly defaultConfig = defaultConfig;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'Only supported on Docker Hub: The release timestamp is determined from the `tag_last_pushed` field in the results. **NOTE**: Currently, digests will receive the same release timestamp as the `tag_last_pushed`, which means that digests may appear newer than they are - see https://github.com/renovatebot/renovate/issues/38659';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `org.opencontainers.image.source` and `org.label-schema.vcs-url` labels present in the metadata of the **latest stable** image found on the Docker registry.';\n\n constructor() {\n super(DockerDatasource.id);\n }\n\n // TODO: debug why quay throws errors (#9612)\n private async getManifestResponse(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n mode: 'head' | 'getText' = 'getText',\n ): Promise<HttpResponse | null> {\n logger.debug(\n `getManifestResponse(${registryHost}, ${dockerRepository}, ${tag}, ${mode})`,\n );\n try {\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return null;\n }\n headers.accept = [\n 'application/vnd.docker.distribution.manifest.list.v2+json',\n 'application/vnd.docker.distribution.manifest.v2+json',\n 'application/vnd.oci.image.manifest.v1+json',\n 'application/vnd.oci.image.index.v1+json',\n ].join(', ');\n const url = `${registryHost}/v2/${dockerRepository}/manifests/${tag}`;\n const manifestResponse = await this.http[mode](url, {\n headers,\n noAuth: true,\n cacheProvider: memCacheProvider,\n });\n return manifestResponse;\n } catch (err) /* istanbul ignore next */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Unauthorized docker lookup',\n );\n logger.debug({ err });\n return null;\n }\n if (err.statusCode === 404) {\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Docker Manifest is unknown',\n );\n return null;\n }\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n if (err.statusCode >= 500 && err.statusCode < 600) {\n throw new ExternalHostError(err);\n }\n if (err.code === 'ETIMEDOUT') {\n logger.debug(\n { registryHost },\n 'Timeout when attempting to connect to docker registry',\n );\n logger.debug({ err });\n return null;\n }\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Unknown Error looking up docker manifest',\n );\n return null;\n }\n }\n\n private async _getImageConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciImageConfig> | undefined> {\n logger.trace(\n `getImageConfig(${registryHost}, ${dockerRepository}, ${configDigest})`,\n );\n\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n /* v8 ignore next -- should never happen */\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return undefined;\n }\n const url = joinUrlParts(\n registryHost,\n 'v2',\n dockerRepository,\n 'blobs',\n configDigest,\n );\n return await this.http.getJson(\n url,\n {\n headers,\n noAuth: true,\n },\n OciImageConfig,\n );\n }\n\n getImageConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciImageConfig> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-imageconfig',\n key: buildCacheKey(registryHost, dockerRepository, configDigest),\n ttlMinutes: 1440 * 28,\n },\n () => this._getImageConfig(registryHost, dockerRepository, configDigest),\n );\n }\n\n private async _getHelmConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciHelmConfig> | undefined> {\n logger.trace(\n `getImageConfig(${registryHost}, ${dockerRepository}, ${configDigest})`,\n );\n\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n /* v8 ignore next -- should never happen */\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return undefined;\n }\n const url = joinUrlParts(\n registryHost,\n 'v2',\n dockerRepository,\n 'blobs',\n configDigest,\n );\n return await this.http.getJson(\n url,\n {\n headers,\n noAuth: true,\n },\n OciHelmConfig,\n );\n }\n\n getHelmConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciHelmConfig> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-imageconfig',\n key: buildCacheKey(registryHost, dockerRepository, configDigest),\n ttlMinutes: 1440 * 28,\n },\n () => this._getHelmConfig(registryHost, dockerRepository, configDigest),\n );\n }\n\n private async getConfigDigest(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<string | null> {\n return (\n (await this.getManifest(registry, dockerRepository, tag))?.config\n ?.digest ?? null\n );\n }\n\n private async getManifestDocument(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Manifest | null> {\n const manifestResponse = await this.getManifestResponse(\n registry,\n dockerRepository,\n tag,\n );\n\n // If getting the manifest fails here, then abort\n // This means that the latest tag doesn't have a manifest, which shouldn't\n // be possible\n /* v8 ignore next -- should never happen */\n if (!manifestResponse) {\n return null;\n }\n\n // Softfail on invalid manifests\n const parsed = ManifestJson.safeParse(manifestResponse.body);\n if (!parsed.success) {\n logger.debug(\n {\n registry,\n dockerRepository,\n tag,\n body: manifestResponse.body,\n headers: manifestResponse.headers,\n err: parsed.error,\n },\n 'Invalid manifest response',\n );\n return null;\n }\n\n return parsed.data;\n }\n\n private async resolveImageManifest(\n registry: string,\n dockerRepository: string,\n tag: string,\n manifest: Manifest,\n ): Promise<OciImageManifest | DistributionManifest | null> {\n switch (manifest.mediaType) {\n case 'application/vnd.docker.distribution.manifest.v2+json':\n case 'application/vnd.oci.image.manifest.v1+json':\n return manifest;\n case 'application/vnd.docker.distribution.manifest.list.v2+json':\n case 'application/vnd.oci.image.index.v1+json':\n if (!manifest.manifests.length) {\n logger.debug(\n { manifest },\n 'Invalid manifest list with no manifests - returning',\n );\n return null;\n }\n logger.trace(\n { registry, dockerRepository, tag },\n 'Found manifest list, using first image',\n );\n return this.getManifest(\n registry,\n dockerRepository,\n manifest.manifests[0].digest,\n );\n // istanbul ignore next: can't happen\n default:\n return null;\n }\n }\n\n private async getManifest(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<OciImageManifest | DistributionManifest | null> {\n const manifest = await this.getManifestDocument(\n registry,\n dockerRepository,\n tag,\n );\n if (!manifest) {\n return null;\n }\n return this.resolveImageManifest(registry, dockerRepository, tag, manifest);\n }\n\n private async _getImageArchitecture(\n registryHost: string,\n dockerRepository: string,\n currentDigest: string,\n ): Promise<string | null | undefined> {\n try {\n let manifestResponse: HttpResponse | null;\n\n try {\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n currentDigest,\n 'head',\n );\n } catch (_err) {\n const err =\n _err instanceof ExternalHostError\n ? _err.err\n : /* istanbul ignore next: can never happen */ _err;\n\n // v8 ignore else -- needs a non-5xx failure from the manifest request\n if (\n typeof err.statusCode === 'number' &&\n err.statusCode >= 500 &&\n err.statusCode < 600\n ) {\n // querying the digest manifest for a non existent image leads to a 500 statusCode\n return null;\n }\n\n /* istanbul ignore next */\n throw _err;\n }\n\n if (\n manifestResponse?.headers['content-type'] !==\n 'application/vnd.docker.distribution.manifest.v2+json' &&\n manifestResponse?.headers['content-type'] !==\n 'application/vnd.oci.image.manifest.v1+json'\n ) {\n return null;\n }\n\n const configDigest = await this.getConfigDigest(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n if (!configDigest) {\n return null;\n }\n\n const configResponse = await this.getImageConfig(\n registryHost,\n dockerRepository,\n configDigest,\n );\n\n // TODO: fix me, architecture is required in spec\n // v8 ignore else -- needs a config blob with neither key\n if (\n configResponse &&\n ('config' in configResponse.body ||\n 'architecture' in configResponse.body)\n ) {\n const architecture = configResponse.body.architecture ?? null;\n logger.debug(\n `Current digest ${currentDigest} relates to architecture ${\n architecture ?? 'null'\n }`,\n );\n\n return architecture;\n }\n } catch (err) /* istanbul ignore next */ {\n if (err.statusCode !== 404 || err.message === PAGE_NOT_FOUND_ERROR) {\n throw err;\n }\n logger.debug(\n { registryHost, dockerRepository, currentDigest, err },\n 'Unknown error getting image architecture',\n );\n }\n\n return undefined;\n }\n\n getImageArchitecture(\n registryHost: string,\n dockerRepository: string,\n currentDigest: string,\n ): Promise<string | null | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-architecture',\n key: buildCacheKey(registryHost, dockerRepository, currentDigest),\n ttlMinutes: 1440 * 28,\n },\n async (ctx) => {\n const architecture = await this._getImageArchitecture(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n ctx.cacheable = isNonEmptyString(architecture);\n return architecture;\n },\n );\n }\n\n /*\n * docker.getLabels\n *\n * This function will:\n * - Return the labels for the requested image\n */\n private async _getLabels(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Record<string, string> | undefined> {\n logger.debug(`getLabels(${registryHost}, ${dockerRepository}, ${tag})`);\n // Skip Docker Hub image if RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP is set\n if (\n getEnv().RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP &&\n registryHost === DOCKER_HUB\n ) {\n logger.debug(\n 'Docker Hub image - skipping label lookup due to RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP',\n );\n return {};\n }\n try {\n let labels: Record<string, string> | undefined = {};\n const manifestDocument = await this.getManifestDocument(\n registryHost,\n dockerRepository,\n tag,\n );\n\n if (!manifestDocument) {\n logger.debug(\n { registryHost, dockerRepository, tag },\n 'No manifest found',\n );\n return undefined;\n }\n\n if ('annotations' in manifestDocument && manifestDocument.annotations) {\n labels = manifestDocument.annotations;\n }\n\n if ('manifests' in manifestDocument) {\n const descriptorAnnotations = manifestDocument.manifests\n .map((descriptor) => descriptor.annotations)\n .find(\n (annotations) =>\n isNonEmptyString(annotations?.[sourceLabel]) &&\n isNonEmptyString(annotations?.[gitRefLabel]),\n );\n if (descriptorAnnotations) {\n labels = { ...labels, ...descriptorAnnotations };\n }\n }\n\n if (\n 'manifests' in manifestDocument &&\n labels[sourceLabel] &&\n labels[gitRefLabel]\n ) {\n return labels;\n }\n\n const manifest = await this.resolveImageManifest(\n registryHost,\n dockerRepository,\n tag,\n manifestDocument,\n );\n if (!manifest) {\n return undefined;\n }\n\n if ('annotations' in manifest && manifest.annotations) {\n labels = { ...labels, ...manifest.annotations };\n }\n\n switch (manifest.config.mediaType) {\n case 'application/vnd.cncf.helm.config.v1+json': {\n if (labels[sourceLabel]) {\n // we already have the source url, so no need to pull the config\n return labels;\n }\n const configResponse = await this.getHelmConfig(\n registryHost,\n dockerRepository,\n manifest.config.digest,\n );\n\n // v8 ignore else -- needs the helm config blob request to come back empty\n if (configResponse) {\n // Helm chart\n const url = findHelmSourceUrl(configResponse.body);\n // v8 ignore else -- needs a helm chart with no source url\n if (url) {\n labels[sourceLabel] = url;\n }\n }\n break;\n }\n case 'application/vnd.oci.image.config.v1+json':\n case 'application/vnd.docker.container.image.v1+json': {\n if (labels[sourceLabel] && labels[gitRefLabel]) {\n // we already have the source url, so no need to pull the config\n return labels;\n }\n const configResponse = await this.getImageConfig(\n registryHost,\n dockerRepository,\n manifest.config.digest,\n );\n\n /* v8 ignore next -- should never happen */\n if (!configResponse) {\n return labels;\n }\n\n const body = configResponse.body;\n if (body.config) {\n labels = { ...labels, ...body.config.Labels };\n } else {\n logger.debug(\n { headers: configResponse.headers, body },\n `manifest blob response body missing the \"config\" property`,\n );\n }\n break;\n }\n }\n\n // v8 ignore else -- labels are always set by the branches above\n if (labels) {\n logger.debug(\n {\n labels,\n },\n 'found labels in manifest',\n );\n }\n return labels;\n } catch (err) /* istanbul ignore next: should be tested in future */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (err.statusCode === 400 || err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository, err },\n 'Unauthorized docker lookup',\n );\n } else if (err.statusCode === 404) {\n logger.warn(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Config Manifest is unknown',\n );\n } else if (err.statusCode === 429 && isDockerHost(registryHost)) {\n logger.warn({ err }, 'docker registry failure: too many requests');\n } else if (err.statusCode >= 500 && err.statusCode < 600) {\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'docker registry failure: internal error',\n );\n } else if (\n err.code === 'ERR_TLS_CERT_ALTNAME_INVALID' ||\n err.code === 'ETIMEDOUT'\n ) {\n logger.debug(\n { registryHost, err },\n 'Error connecting to docker registry',\n );\n } else if (registryHost === 'https://quay.io') {\n // istanbul ignore next\n logger.debug(\n 'Ignoring quay.io errors until they fully support v2 schema',\n );\n } else {\n logger.info(\n { registryHost, dockerRepository, tag, err },\n 'Unknown error getting Docker labels',\n );\n }\n return {};\n }\n }\n\n getLabels(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Record<string, string> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-labels',\n key: buildCacheKey(registryHost, dockerRepository, tag),\n ttlMinutes: 24 * 60,\n },\n () => this._getLabels(registryHost, dockerRepository, tag),\n );\n }\n\n private async getTagsQuayRegistry(\n registry: string,\n repository: string,\n ): Promise<string[]> {\n let tags: string[] = [];\n const limit = 100;\n\n function pageUrl(page: number): string {\n return `${registry}/api/v1/repository/${repository}/tag/?limit=${limit}&page=${page}&onlyActiveTags=true`;\n }\n\n let page = 1;\n let url: string | null = pageUrl(page);\n while (url && page <= 20) {\n const res: HttpResponse<QuayTagsResponse> = await this.http.getJson(\n url,\n QuayTagsResponse,\n );\n const pageTags = res.body.tags.map((tag) => tag.name);\n tags = tags.concat(pageTags);\n page += 1;\n url = res.body.has_additional ? pageUrl(page) : null;\n }\n return tags;\n }\n\n private async getDockerApiTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | undefined> {\n let tags: string[] = [];\n // AWS ECR limits the maximum number of results to 1000\n // See https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeRepositories.html#ECR-DescribeRepositories-request-maxResults\n // See https://docs.aws.amazon.com/AmazonECRPublic/latest/APIReference/API_DescribeRepositories.html#ecrpublic-DescribeRepositories-request-maxResults\n const limit =\n ecrRegex.test(registryHost) || ecrPublicRegex.test(registryHost)\n ? 1000\n : 10000;\n let url: string | null =\n `${registryHost}/${dockerRepository}/tags/list?n=${limit}`;\n url = ensurePathPrefix(url, '/v2');\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n url,\n );\n if (!headers) {\n logger.debug('Failed to get authHeaders for getTags lookup');\n return undefined;\n }\n let page = 0;\n const hostsNeedingAllPages = [\n 'https://ghcr.io', // GHCR sorts from oldest to newest, so we need to get all pages\n 'https://quay.io', // Quay sorts from oldest to newest, so we need to get all pages\n 'https://cgr.dev', // Chainguard sorts lexically and publishes a tag per build, so current versions sort past the page limit\n 'https://registry.access.redhat.com', // RH catalog; Quay-style lexicographic sort, high tag counts\n 'https://registry.redhat.io', // RH authenticated catalog; same backend\n ];\n const pages = hostsNeedingAllPages.includes(registryHost)\n ? 1000\n : GlobalConfig.get('dockerMaxPages');\n logger.trace({ registryHost, dockerRepository, pages }, 'docker.getTags');\n const allowCrossOrigin = isCrossOriginPaginationAllowed(dockerDatasourceId);\n let foundMaxResultsError = false;\n do {\n let res: HttpResponse<RegistryTagsList>;\n try {\n res = await this.http.getJson(\n url,\n { headers, noAuth: true },\n RegistryTagsList,\n );\n } catch (err) {\n if (\n !foundMaxResultsError &&\n err instanceof HttpError &&\n isECRMaxResultsError(err)\n ) {\n const maxResults = 1000;\n url = `${registryHost}/${dockerRepository}/tags/list?n=${maxResults}`;\n url = ensurePathPrefix(url, '/v2');\n foundMaxResultsError = true;\n continue;\n }\n throw err;\n }\n tags = tags.concat(res.body.tags);\n const linkHeader = parseLinkHeader(res.headers.link);\n if (isArtifactoryServer(res)) {\n // Artifactory bug: next link comes back without virtual-repo prefix (RTFACT-18971)\n if (linkHeader?.next?.last) {\n // parse the current URL, strip any old \"last\" param, then set the new one\n const parsed = parseUrl(url);\n // v8 ignore if: url is always a valid HTTP URL as `ensurePathPrefix`\n if (!parsed) {\n url = null;\n break;\n }\n parsed.searchParams.delete('last');\n parsed.searchParams.set('last', linkHeader.next.last);\n url = parsed.href;\n } else {\n url = null;\n }\n } else if (linkHeader?.next?.url) {\n // Resolve the relative-or-absolute next link, not following cross-origin requests unless explicitly opted in\n const nextUrl = resolvePaginationUrl(\n url,\n linkHeader.next.url,\n allowCrossOrigin,\n );\n if (!nextUrl) {\n // make sure that users are aware if there are any (potentially malicious, or misconfigured) pagination links being returned\n logger.once.warn(\n { registryHost, nextUrl: linkHeader.next.url },\n 'Ignoring cross-origin or invalid Docker registry tags pagination link',\n );\n }\n url = nextUrl;\n } else {\n url = null;\n }\n page += 1;\n } while (url && page < pages);\n return tags;\n }\n\n private async _getTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | undefined> {\n try {\n const isQuay = registryHost === 'https://quay.io';\n let tags: string[] | undefined;\n if (isQuay) {\n try {\n // Due to pagination and sorting limits on Quay Docker v2 API implementation we try the Quay v1 API first\n tags = await this.getTagsQuayRegistry(registryHost, dockerRepository);\n } catch (err) {\n // If we get a 401 Unauthorized error (v1 API requires separate auth for private images), fall back to Docker v2 API\n if (err.statusCode === 401) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Quay v1 API unauthorized, falling back to Docker v2 API',\n );\n tags = await this.getDockerApiTags(registryHost, dockerRepository);\n } else {\n throw err;\n }\n }\n } else {\n tags = await this.getDockerApiTags(registryHost, dockerRepository);\n }\n return tags;\n } catch (_err) /* istanbul ignore next */ {\n const err = _err instanceof ExternalHostError ? _err.err : _err;\n\n if (\n (err.statusCode === 404 || err.message === PAGE_NOT_FOUND_ERROR) &&\n !dockerRepository.includes('/')\n ) {\n logger.debug(\n `Retrying Tags for ${registryHost}/${dockerRepository} using library/ prefix`,\n );\n return this.getTags(registryHost, `library/${dockerRepository}`);\n }\n // JFrog Artifactory - Retry handling when resolving Docker Official Images\n // These follow the format of {{registryHost}}{{jFrogRepository}}/library/{{dockerRepository}}\n if (\n (err.statusCode === 404 || err.message === PAGE_NOT_FOUND_ERROR) &&\n isArtifactoryServer(err.response) &&\n dockerRepository.split('/').length === 2\n ) {\n logger.debug(\n `JFrog Artifactory: Retrying Tags for ${registryHost}/${dockerRepository} using library/ path between JFrog virtual repository and image`,\n );\n\n const dockerRepositoryParts = dockerRepository.split('/');\n const jfrogRepository = dockerRepositoryParts[0];\n const dockerImage = dockerRepositoryParts[1];\n\n return this.getTags(\n registryHost,\n `${jfrogRepository}/library/${dockerImage}`,\n );\n }\n if (err.statusCode === 429 && isDockerHost(registryHost)) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry failure: too many requests',\n );\n throw new ExternalHostError(err);\n }\n if (err.statusCode >= 500 && err.statusCode < 600) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry failure: internal error',\n );\n throw new ExternalHostError(err);\n }\n const errorCodes = ['ECONNRESET', 'ETIMEDOUT'];\n if (errorCodes.includes(err.code)) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry connection failure',\n );\n throw new ExternalHostError(err);\n }\n if (isDockerHost(registryHost)) {\n logger.info({ err }, 'Docker Hub lookup failure');\n }\n throw _err;\n }\n }\n\n getTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-tags',\n key: buildCacheKey(registryHost, dockerRepository),\n public: registryHost === DOCKER_HUB,\n },\n () => this._getTags(registryHost, dockerRepository),\n );\n }\n\n /**\n * docker.getDigest\n *\n * The `newValue` supplied here should be a valid tag for the docker image.\n *\n * This function will:\n * - Look up a sha256 digest for a tag on its registry\n * - Return the digest as a string\n */\n private async _getDigest(\n { registryUrl, lookupName, packageName, currentDigest }: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n let registryHost: string;\n let dockerRepository: string;\n if (registryUrl && lookupName) {\n // Reuse the resolved values from getReleases()\n registryHost = registryUrl;\n dockerRepository = lookupName;\n } else {\n // Resolve values independently\n ({ registryHost, dockerRepository } = getRegistryRepository(\n packageName,\n registryUrl!,\n ));\n }\n logger.debug(\n // TODO: types (#22198)\n `getDigest(${registryHost}, ${dockerRepository}, ${newValue})`,\n );\n const newTag = isNonEmptyString(newValue) ? newValue : 'latest';\n let digest: string | null = null;\n try {\n let architecture: string | null | undefined = null;\n if (currentDigest && isDockerDigest(currentDigest)) {\n architecture = await this.getImageArchitecture(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n }\n\n let manifestResponse: HttpResponse | null = null;\n if (!architecture) {\n // Reuse the digest cached from the Docker Hub tag API\n if (registryHost === DOCKER_HUB) {\n const cache = await DockerHubCache.init(dockerRepository);\n const cachedDigest = cache.getDigestForTag(newTag);\n if (cachedDigest) {\n return cachedDigest;\n }\n }\n\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n newTag,\n 'head',\n );\n\n if (\n manifestResponse &&\n hasKey('docker-content-digest', manifestResponse.headers)\n ) {\n digest =\n (manifestResponse.headers['docker-content-digest'] as string) ||\n null;\n }\n }\n\n if (\n isNonEmptyString(architecture) ||\n (manifestResponse &&\n !hasKey('docker-content-digest', manifestResponse.headers))\n ) {\n // Reuse the per-arch digest cached from the Docker Hub tag API\n if (isNonEmptyString(architecture) && registryHost === DOCKER_HUB) {\n const cache = await DockerHubCache.init(dockerRepository);\n const cachedDigest = cache.getArchDigestForTag(newTag, architecture);\n if (cachedDigest) {\n return cachedDigest;\n }\n }\n\n logger.debug(\n { registryHost, dockerRepository },\n 'Architecture-specific digest or missing docker-content-digest header - pulling full manifest',\n );\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n newTag,\n );\n\n if (architecture && manifestResponse) {\n const parsed = ManifestJson.safeParse(manifestResponse.body);\n /* istanbul ignore else: hard to test */\n if (parsed.success) {\n const manifestList = parsed.data;\n if (\n manifestList.mediaType ===\n 'application/vnd.docker.distribution.manifest.list.v2+json' ||\n manifestList.mediaType ===\n 'application/vnd.oci.image.index.v1+json'\n ) {\n for (const manifest of manifestList.manifests) {\n if (manifest.platform?.architecture === architecture) {\n digest = manifest.digest;\n break;\n }\n }\n // TODO: return null if no matching architecture digest found\n // https://github.com/renovatebot/renovate/discussions/22639\n // NOTE: reaching the implicit else needs a manifest list with no\n // digest header. A coverage-ignore hint cannot suppress it on an\n // `else if`.\n } else if (\n hasKey('docker-content-digest', manifestResponse.headers)\n ) {\n // TODO: return null if no matching architecture, requires to fetch the config manifest\n // https://github.com/renovatebot/renovate/discussions/22639\n digest = manifestResponse.headers[\n 'docker-content-digest'\n ] as string;\n }\n } else {\n logger.debug(\n {\n registryHost,\n dockerRepository,\n newTag,\n body: manifestResponse.body,\n headers: manifestResponse.headers,\n err: parsed.error,\n },\n 'Failed to parse manifest response',\n );\n }\n }\n\n if (!digest) {\n logger.debug(\n { registryHost, dockerRepository, newTag },\n 'Extraction digest from manifest response body is deprecated',\n );\n digest = extractDigestFromResponseBody(manifestResponse!);\n }\n }\n\n if (\n !manifestResponse &&\n !dockerRepository.includes('/') &&\n !packageName.includes('/')\n ) {\n logger.debug(\n `Retrying Digest for ${registryHost}/${dockerRepository} using library/ prefix`,\n );\n return this.getDigest(\n {\n registryUrl,\n packageName: `library/${packageName}`,\n currentDigest,\n },\n newValue,\n );\n }\n\n if (manifestResponse) {\n // TODO: fix types (#22198)\n logger.debug(`Got docker digest ${digest!}`);\n }\n } catch (err) /* istanbul ignore next */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n {\n err,\n packageName,\n newTag,\n },\n 'Unknown Error looking up docker image digest',\n );\n }\n return digest;\n }\n\n override getDigest(\n config: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n const newTag = newValue ?? 'latest';\n const { registryHost, dockerRepository } = getRegistryRepository(\n config.packageName,\n config.registryUrl!,\n );\n return withCache(\n {\n namespace: 'datasource-docker-digest',\n key: buildCacheKey(\n registryHost,\n dockerRepository,\n newTag,\n config.currentDigest,\n ),\n fallback: true,\n },\n async (ctx) => {\n const digest = await this._getDigest(config, newValue);\n ctx.cacheable = isNonEmptyString(digest);\n return digest;\n },\n );\n }\n\n private async _getDockerHubTags(\n dockerRepository: string,\n ): Promise<Release[] | null> {\n let url = `https://hub.docker.com/v2/repositories/${dockerRepository}/tags?page_size=1000&ordering=last_updated`;\n\n const cache = await DockerHubCache.init(dockerRepository);\n const maxPages = GlobalConfig.get('dockerMaxPages');\n const allowCrossOrigin = isCrossOriginPaginationAllowed(dockerDatasourceId);\n let page = 0,\n needNextPage = true;\n while (needNextPage && page < maxPages) {\n const { val, err } = await this.http\n .getJsonSafe(url, DockerHubTagsPage)\n .unwrap();\n\n if (err) {\n logger.debug({ err }, `Docker: error fetching data from DockerHub`);\n return null;\n }\n page++;\n const { results, next, count } = val;\n\n needNextPage = cache.reconcile(results, count);\n\n if (!next) {\n break;\n }\n\n // Only follow the `next` link when it's on the same origin, unless explicitly opted in\n const nextUrl = resolvePaginationUrl(url, next, allowCrossOrigin);\n if (!nextUrl) {\n logger.once.warn(\n { dockerRepository, nextUrl: next },\n 'Ignoring cross-origin or invalid Docker Hub tags pagination link',\n );\n break;\n }\n\n url = nextUrl;\n }\n\n await cache.save();\n\n const items = cache.getItems();\n return items.map(({ name: version, tag_last_pushed }) => {\n const release: Release = { version };\n\n const releaseTimestamp = asTimestamp(tag_last_pushed);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n\n // Digest is intentionally not propagated — the Docker Hub tag API\n // returns the manifest-list digest, which would bypass arch-aware\n // resolution in `getDigest()`. `getDigest()` consults the same cache\n // as a shortcut when no arch resolution is needed.\n return release;\n });\n }\n\n getDockerHubTags(dockerRepository: string): Promise<Release[] | null> {\n return withCache(\n {\n namespace: 'datasource-docker-hub-tags',\n key: dockerRepository,\n },\n () => this._getDockerHubTags(dockerRepository),\n );\n }\n\n /**\n * docker.getReleases\n *\n * A docker image usually looks something like this: somehost.io/owner/repo:8.1.0-alpine\n * In the above:\n * - 'somehost.io' is the registry\n * - 'owner/repo' is the package name\n * - '8.1.0-alpine' is the tag\n *\n * This function will filter only tags that contain a semver version\n */\n private async _getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n const { registryHost, dockerRepository } = getRegistryRepository(\n packageName,\n registryUrl!,\n );\n\n type TagsResultType = AsyncResult<\n Release[],\n NonNullable<Error | 'tags-error' | 'dockerhub-error'>\n >;\n\n const getTags = (): TagsResultType =>\n Result.wrapNullable(\n this.getTags(registryHost, dockerRepository),\n 'tags-error' as const,\n ).transform((tags) => tags.map((version) => ({ version })));\n\n const getDockerHubTags = (): TagsResultType =>\n Result.wrapNullable(\n this.getDockerHubTags(dockerRepository),\n 'dockerhub-error' as const,\n ).catch(getTags);\n\n const tagsResult =\n registryHost === DOCKER_HUB &&\n !getEnv().RENOVATE_X_DOCKER_HUB_TAGS_DISABLE\n ? getDockerHubTags()\n : getTags();\n\n const { val: releases, err } = await tagsResult.unwrap();\n if (err instanceof Error) {\n throw err;\n } else if (err) {\n return null;\n }\n\n const ret: ReleaseResult = {\n registryUrl: registryHost,\n releases,\n };\n if (dockerRepository !== packageName) {\n // This will be reused later if a getDigest() call is made\n ret.lookupName = dockerRepository;\n }\n\n const tags = releases.map((release) => release.version);\n const latestTag = tags.includes('latest')\n ? 'latest'\n : (findLatestStable(tags) ?? tags.at(-1));\n\n /* v8 ignore next -- TODO: add test */\n if (!latestTag) {\n return ret;\n }\n const labels = await this.getLabels(\n registryHost,\n dockerRepository,\n latestTag,\n );\n if (labels) {\n if (isNonEmptyString(labels[gitRefLabel])) {\n ret.gitRef = labels[gitRefLabel];\n }\n for (const label of sourceLabels) {\n if (isNonEmptyString(labels[label])) {\n ret.sourceUrl = labels[label];\n break;\n }\n }\n if (isNonEmptyString(labels[imageUrlLabel])) {\n ret.homepage = labels[imageUrlLabel];\n }\n }\n return ret;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n const { registryHost, dockerRepository } = getRegistryRepository(\n config.packageName,\n config.registryUrl!,\n );\n return withCache(\n {\n namespace: 'datasource-docker-releases-v2',\n key: buildCacheKey(registryHost, dockerRepository),\n public: registryHost === DOCKER_HUB,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAgEA,MAAM,gBAAgB;CACpB,oBAAoB;CACpB,oBACE;CACF,QAAQ;EACN,aAAa;EACb,oBAAoB;EACpB,oBACE;EACF,OAAO;GACL,oBAAoB;GACpB,oBAAoB;EACtB;CACF;CACA,KAAK;EACH,oBAAoB;EACpB,WAAW;EACX,OAAO;GACL,oBAAoB;GACpB,aAAa;EACf;CACF;AACF;AAEA,IAAa,mBAAb,MAAa,yBAAyB,WAAW;CAC/C,OAAgB,KAAK;CAErB,oBAAsCA;CAEtC,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,UAAU;CACpB;CAEA,gBAAkC;CAElC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,cAAc;EACZ,MAAM,iBAAiB,EAAE;CAC3B;CAGA,MAAc,oBACZ,cACA,kBACA,KACA,OAA2B,WACG;EAC9B,OAAO,MACL,uBAAuB,aAAa,IAAI,iBAAiB,IAAI,IAAI,IAAI,KAAK,EAC5E;EACA,IAAI;GACF,MAAM,UAAU,MAAM,eACpB,KAAK,MACL,cACA,gBACF;GACA,IAAI,CAAC,SAAS;IACZ,OAAO,KAAK,kCAAkC;IAC9C,OAAO;GACT;GACA,QAAQ,SAAS;IACf;IACA;IACA;IACA;GACF,CAAC,CAAC,KAAK,IAAI;GACX,MAAM,MAAM,GAAG,aAAa,MAAM,iBAAiB,aAAa;GAMhE,OAAO,MALwB,KAAK,KAAK,KAAK,CAAC,KAAK;IAClD;IACA,QAAQ;IACR,eAAe;GACjB,CAAC;EAEH,SAAS,gCAAgC;GACvC,IAAI,eAAe,mBACjB,MAAM;GAER,IAAI,IAAI,eAAe,KAAK;IAC1B,OAAO,MACL;KAAE;KAAc;IAAiB,GACjC,4BACF;IACA,OAAO,MAAM,EAAE,IAAI,CAAC;IACpB,OAAO;GACT;GACA,IAAI,IAAI,eAAe,KAAK;IAC1B,OAAO,MACL;KACE;KACA;KACA;KACA;IACF,GACA,4BACF;IACA,OAAO;GACT;GACA,IAAI,IAAI,eAAe,OAAO,aAAa,YAAY,GACrD,MAAM,IAAI,kBAAkB,GAAG;GAEjC,IAAI,IAAI,cAAc,OAAO,IAAI,aAAa,KAC5C,MAAM,IAAI,kBAAkB,GAAG;GAEjC,IAAI,IAAI,SAAS,aAAa;IAC5B,OAAO,MACL,EAAE,aAAa,GACf,uDACF;IACA,OAAO,MAAM,EAAE,IAAI,CAAC;IACpB,OAAO;GACT;GACA,OAAO,MACL;IACE;IACA;IACA;IACA;GACF,GACA,0CACF;GACA,OAAO;EACT;CACF;CAEA,MAAc,gBACZ,cACA,kBACA,cACmD;EACnD,OAAO,MACL,kBAAkB,aAAa,IAAI,iBAAiB,IAAI,aAAa,EACvE;EAEA,MAAM,UAAU,MAAM,eACpB,KAAK,MACL,cACA,gBACF;;EAEA,IAAI,CAAC,SAAS;GACZ,OAAO,KAAK,kCAAkC;GAC9C;EACF;EACA,MAAM,MAAM,aACV,cACA,MACA,kBACA,SACA,YACF;EACA,OAAO,MAAM,KAAK,KAAK,QACrB,KACA;GACE;GACA,QAAQ;EACV,GACA,cACF;CACF;CAEA,eACE,cACA,kBACA,cACmD;EACnD,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,kBAAkB,YAAY;GAC/D,YAAY;EACd,SACM,KAAK,gBAAgB,cAAc,kBAAkB,YAAY,CACzE;CACF;CAEA,MAAc,eACZ,cACA,kBACA,cACkD;EAClD,OAAO,MACL,kBAAkB,aAAa,IAAI,iBAAiB,IAAI,aAAa,EACvE;EAEA,MAAM,UAAU,MAAM,eACpB,KAAK,MACL,cACA,gBACF;;EAEA,IAAI,CAAC,SAAS;GACZ,OAAO,KAAK,kCAAkC;GAC9C;EACF;EACA,MAAM,MAAM,aACV,cACA,MACA,kBACA,SACA,YACF;EACA,OAAO,MAAM,KAAK,KAAK,QACrB,KACA;GACE;GACA,QAAQ;EACV,GACA,aACF;CACF;CAEA,cACE,cACA,kBACA,cACkD;EAClD,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,kBAAkB,YAAY;GAC/D,YAAY;EACd,SACM,KAAK,eAAe,cAAc,kBAAkB,YAAY,CACxE;CACF;CAEA,MAAc,gBACZ,UACA,kBACA,KACwB;EACxB,QACG,MAAM,KAAK,YAAY,UAAU,kBAAkB,GAAG,EAAA,EAAI,QACvD,UAAU;CAElB;CAEA,MAAc,oBACZ,UACA,kBACA,KAC0B;EAC1B,MAAM,mBAAmB,MAAM,KAAK,oBAClC,UACA,kBACA,GACF;;EAMA,IAAI,CAAC,kBACH,OAAO;EAIT,MAAM,SAAS,aAAa,UAAU,iBAAiB,IAAI;EAC3D,IAAI,CAAC,OAAO,SAAS;GACnB,OAAO,MACL;IACE;IACA;IACA;IACA,MAAM,iBAAiB;IACvB,SAAS,iBAAiB;IAC1B,KAAK,OAAO;GACd,GACA,2BACF;GACA,OAAO;EACT;EAEA,OAAO,OAAO;CAChB;CAEA,MAAc,qBACZ,UACA,kBACA,KACA,UACyD;EACzD,QAAQ,SAAS,WAAjB;GACE,KAAK;GACL,KAAK,8CACH,OAAO;GACT,KAAK;GACL,KAAK;IACH,IAAI,CAAC,SAAS,UAAU,QAAQ;KAC9B,OAAO,MACL,EAAE,SAAS,GACX,qDACF;KACA,OAAO;IACT;IACA,OAAO,MACL;KAAE;KAAU;KAAkB;IAAI,GAClC,wCACF;IACA,OAAO,KAAK,YACV,UACA,kBACA,SAAS,UAAU,EAAE,CAAC,MACxB;;GAEF,SACE,OAAO;EACX;CACF;CAEA,MAAc,YACZ,UACA,kBACA,KACyD;EACzD,MAAM,WAAW,MAAM,KAAK,oBAC1B,UACA,kBACA,GACF;EACA,IAAI,CAAC,UACH,OAAO;EAET,OAAO,KAAK,qBAAqB,UAAU,kBAAkB,KAAK,QAAQ;CAC5E;CAEA,MAAc,sBACZ,cACA,kBACA,eACoC;EACpC,IAAI;GACF,IAAI;GAEJ,IAAI;IACF,mBAAmB,MAAM,KAAK,oBAC5B,cACA,kBACA,eACA,MACF;GACF,SAAS,MAAM;IACb,MAAM,MACJ,gBAAgB,oBACZ,KAAK,mDACwC;;IAGnD,IACE,OAAO,IAAI,eAAe,YAC1B,IAAI,cAAc,OAClB,IAAI,aAAa,KAGjB,OAAO;;IAIT,MAAM;GACR;GAEA,IACE,kBAAkB,QAAQ,oBACxB,0DACF,kBAAkB,QAAQ,oBACxB,8CAEF,OAAO;GAGT,MAAM,eAAe,MAAM,KAAK,gBAC9B,cACA,kBACA,aACF;GACA,IAAI,CAAC,cACH,OAAO;GAGT,MAAM,iBAAiB,MAAM,KAAK,eAChC,cACA,kBACA,YACF;;GAIA,IACE,mBACC,YAAY,eAAe,QAC1B,kBAAkB,eAAe,OACnC;IACA,MAAM,eAAe,eAAe,KAAK,gBAAgB;IACzD,OAAO,MACL,kBAAkB,cAAc,2BAC9B,gBAAgB,QAEpB;IAEA,OAAO;GACT;EACF,SAAS,gCAAgC;GACvC,IAAI,IAAI,eAAe,OAAO,IAAI,YAAA,kBAChC,MAAM;GAER,OAAO,MACL;IAAE;IAAc;IAAkB;IAAe;GAAI,GACrD,0CACF;EACF;CAGF;CAEA,qBACE,cACA,kBACA,eACoC;EACpC,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,kBAAkB,aAAa;GAChE,YAAY;EACd,GACA,OAAO,QAAQ;GACb,MAAM,eAAe,MAAM,KAAK,sBAC9B,cACA,kBACA,aACF;GACA,IAAI,YAAY,iBAAiB,YAAY;GAC7C,OAAO;EACT,CACF;CACF;CAQA,MAAc,WACZ,cACA,kBACA,KAC6C;EAC7C,OAAO,MAAM,aAAa,aAAa,IAAI,iBAAiB,IAAI,IAAI,EAAE;EAEtE,IACE,OAAO,CAAC,CAAC,8CACT,iBAAA,2BACA;GACA,OAAO,MACL,4FACF;GACA,OAAO,CAAC;EACV;EACA,IAAI;GACF,IAAI,SAA6C,CAAC;GAClD,MAAM,mBAAmB,MAAM,KAAK,oBAClC,cACA,kBACA,GACF;GAEA,IAAI,CAAC,kBAAkB;IACrB,OAAO,MACL;KAAE;KAAc;KAAkB;IAAI,GACtC,mBACF;IACA;GACF;GAEA,IAAI,iBAAiB,oBAAoB,iBAAiB,aACxD,SAAS,iBAAiB;GAG5B,IAAI,eAAe,kBAAkB;IACnC,MAAM,wBAAwB,iBAAiB,UAC5C,KAAK,eAAe,WAAW,WAAW,CAAC,CAC3C,MACE,gBACC,iBAAiB,cAAA,kCAA0B,KAC3C,iBAAiB,cAAA,oCAA0B,CAC/C;IACF,IAAI,uBACF,SAAS;KAAE,GAAG;KAAQ,GAAG;IAAsB;GAEnD;GAEA,IACE,eAAe,oBACf,OAAA,sCACA,OAAA,sCAEA,OAAO;GAGT,MAAM,WAAW,MAAM,KAAK,qBAC1B,cACA,kBACA,KACA,gBACF;GACA,IAAI,CAAC,UACH;GAGF,IAAI,iBAAiB,YAAY,SAAS,aACxC,SAAS;IAAE,GAAG;IAAQ,GAAG,SAAS;GAAY;GAGhD,QAAQ,SAAS,OAAO,WAAxB;IACE,KAAK,4CAA4C;KAC/C,IAAI,OAAA,oCAEF,OAAO;KAET,MAAM,iBAAiB,MAAM,KAAK,cAChC,cACA,kBACA,SAAS,OAAO,MAClB;;KAGA,IAAI,gBAAgB;MAElB,MAAM,MAAM,kBAAkB,eAAe,IAAI;;MAEjD,IAAI,KACF,OAAO,eAAe;KAE1B;KACA;IACF;IACA,KAAK;IACL,KAAK,kDAAkD;KACrD,IAAI,OAAA,sCAAuB,OAAA,sCAEzB,OAAO;KAET,MAAM,iBAAiB,MAAM,KAAK,eAChC,cACA,kBACA,SAAS,OAAO,MAClB;;KAGA,IAAI,CAAC,gBACH,OAAO;KAGT,MAAM,OAAO,eAAe;KAC5B,IAAI,KAAK,QACP,SAAS;MAAE,GAAG;MAAQ,GAAG,KAAK,OAAO;KAAO;UAE5C,OAAO,MACL;MAAE,SAAS,eAAe;MAAS;KAAK,GACxC,2DACF;KAEF;IACF;GACF;;GAGA,IAAI,QACF,OAAO,MACL,EACE,OACF,GACA,0BACF;GAEF,OAAO;EACT,SAAS,4DAA4D;GACnE,IAAI,eAAe,mBACjB,MAAM;GAER,IAAI,IAAI,eAAe,OAAO,IAAI,eAAe,KAC/C,OAAO,MACL;IAAE;IAAc;IAAkB;GAAI,GACtC,4BACF;QACK,IAAI,IAAI,eAAe,KAC5B,OAAO,KACL;IACE;IACA;IACA;IACA;GACF,GACA,4BACF;QACK,IAAI,IAAI,eAAe,OAAO,aAAa,YAAY,GAC5D,OAAO,KAAK,EAAE,IAAI,GAAG,4CAA4C;QAC5D,IAAI,IAAI,cAAc,OAAO,IAAI,aAAa,KACnD,OAAO,MACL;IACE;IACA;IACA;IACA;GACF,GACA,yCACF;QACK,IACL,IAAI,SAAS,kCACb,IAAI,SAAS,aAEb,OAAO,MACL;IAAE;IAAc;GAAI,GACpB,qCACF;QACK,IAAI,iBAAiB;;GAE1B,OAAO,MACL,4DACF;QAEA,OAAO,KACL;IAAE;IAAc;IAAkB;IAAK;GAAI,GAC3C,qCACF;GAEF,OAAO,CAAC;EACV;CACF;CAEA,UACE,cACA,kBACA,KAC6C;EAC7C,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,kBAAkB,GAAG;GACtD,YAAY;EACd,SACM,KAAK,WAAW,cAAc,kBAAkB,GAAG,CAC3D;CACF;CAEA,MAAc,oBACZ,UACA,YACmB;EACnB,IAAI,OAAiB,CAAC;EACtB,MAAM,QAAQ;EAEd,SAAS,QAAQ,MAAsB;GACrC,OAAO,GAAG,SAAS,qBAAqB,WAAW,cAAc,MAAM,QAAQ,KAAK;EACtF;EAEA,IAAI,OAAO;EACX,IAAI,MAAqB,QAAQ,IAAI;EACrC,OAAO,OAAO,QAAQ,IAAI;GACxB,MAAM,MAAsC,MAAM,KAAK,KAAK,QAC1D,KACA,gBACF;GACA,MAAM,WAAW,IAAI,KAAK,KAAK,KAAK,QAAQ,IAAI,IAAI;GACpD,OAAO,KAAK,OAAO,QAAQ;GAC3B,QAAQ;GACR,MAAM,IAAI,KAAK,iBAAiB,QAAQ,IAAI,IAAI;EAClD;EACA,OAAO;CACT;CAEA,MAAc,iBACZ,cACA,kBAC+B;EAC/B,IAAI,OAAiB,CAAC;EAQtB,IAAI,MACF,GAAG,aAAa,GAAG,iBAAiB,eAJpC,SAAS,KAAK,YAAY,KAAK,eAAe,KAAK,YAAY,IAC3D,MACA;EAGN,MAAM,iBAAiB,KAAK,KAAK;EACjC,MAAM,UAAU,MAAM,eACpB,KAAK,MACL,cACA,kBACA,GACF;EACA,IAAI,CAAC,SAAS;GACZ,OAAO,MAAM,8CAA8C;GAC3D;EACF;EACA,IAAI,OAAO;EAQX,MAAM,QAAQ;GANZ;GACA;GACA;GACA;GACA;EAE+B,CAAC,CAAC,SAAS,YAAY,IACpD,MACA,aAAa,IAAI,gBAAgB;EACrC,OAAO,MAAM;GAAE;GAAc;GAAkB;EAAM,GAAG,gBAAgB;EACxE,MAAM,mBAAmB,+BAA+B,kBAAkB;EAC1E,IAAI,uBAAuB;EAC3B,GAAG;GACD,IAAI;GACJ,IAAI;IACF,MAAM,MAAM,KAAK,KAAK,QACpB,KACA;KAAE;KAAS,QAAQ;IAAK,GACxB,gBACF;GACF,SAAS,KAAK;IACZ,IACE,CAAC,wBACD,eAAeC,gBACf,qBAAqB,GAAG,GACxB;KAEA,MAAM,GAAG,aAAa,GAAG,iBAAiB;KAC1C,MAAM,iBAAiB,KAAK,KAAK;KACjC,uBAAuB;KACvB;IACF;IACA,MAAM;GACR;GACA,OAAO,KAAK,OAAO,IAAI,KAAK,IAAI;GAChC,MAAM,aAAa,gBAAgB,IAAI,QAAQ,IAAI;GACnD,IAAI,oBAAoB,GAAG,GAAG;IAE5B,IAAI,YAAY,MAAM,MAAM;KAE1B,MAAM,SAAS,SAAS,GAAG;;KAE3B,IAAI,CAAC,QAAQ;MACX,MAAM;MACN;KACF;KACA,OAAO,aAAa,OAAO,MAAM;KACjC,OAAO,aAAa,IAAI,QAAQ,WAAW,KAAK,IAAI;KACpD,MAAM,OAAO;IACf,OACE,MAAM;GAEV,OAAO,IAAI,YAAY,MAAM,KAAK;IAEhC,MAAM,UAAU,qBACd,KACA,WAAW,KAAK,KAChB,gBACF;IACA,IAAI,CAAC,SAEH,OAAO,KAAK,KACV;KAAE;KAAc,SAAS,WAAW,KAAK;IAAI,GAC7C,uEACF;IAEF,MAAM;GACR,OACE,MAAM;GAER,QAAQ;EACV,SAAS,OAAO,OAAO;EACvB,OAAO;CACT;CAEA,MAAc,SACZ,cACA,kBAC+B;EAC/B,IAAI;GACF,MAAM,SAAS,iBAAiB;GAChC,IAAI;GACJ,IAAI,QACF,IAAI;IAEF,OAAO,MAAM,KAAK,oBAAoB,cAAc,gBAAgB;GACtE,SAAS,KAAK;IAEZ,IAAI,IAAI,eAAe,KAAK;KAC1B,OAAO,MACL;MAAE;MAAc;KAAiB,GACjC,yDACF;KACA,OAAO,MAAM,KAAK,iBAAiB,cAAc,gBAAgB;IACnE,OACE,MAAM;GAEV;QAEA,OAAO,MAAM,KAAK,iBAAiB,cAAc,gBAAgB;GAEnE,OAAO;EACT,SAAS,iCAAiC;GACxC,MAAM,MAAM,gBAAgB,oBAAoB,KAAK,MAAM;GAE3D,KACG,IAAI,eAAe,OAAO,IAAI,YAAA,qBAC/B,CAAC,iBAAiB,SAAS,GAAG,GAC9B;IACA,OAAO,MACL,qBAAqB,aAAa,GAAG,iBAAiB,uBACxD;IACA,OAAO,KAAK,QAAQ,cAAc,WAAW,kBAAkB;GACjE;GAGA,KACG,IAAI,eAAe,OAAO,IAAI,YAAA,qBAC/B,oBAAoB,IAAI,QAAQ,KAChC,iBAAiB,MAAM,GAAG,CAAC,CAAC,WAAW,GACvC;IACA,OAAO,MACL,wCAAwC,aAAa,GAAG,iBAAiB,gEAC3E;IAEA,MAAM,wBAAwB,iBAAiB,MAAM,GAAG;IACxD,MAAM,kBAAkB,sBAAsB;IAC9C,MAAM,cAAc,sBAAsB;IAE1C,OAAO,KAAK,QACV,cACA,GAAG,gBAAgB,WAAW,aAChC;GACF;GACA,IAAI,IAAI,eAAe,OAAO,aAAa,YAAY,GAAG;IACxD,OAAO,KACL;KAAE;KAAc;KAAkB;IAAI,GACtC,4CACF;IACA,MAAM,IAAI,kBAAkB,GAAG;GACjC;GACA,IAAI,IAAI,cAAc,OAAO,IAAI,aAAa,KAAK;IACjD,OAAO,KACL;KAAE;KAAc;KAAkB;IAAI,GACtC,yCACF;IACA,MAAM,IAAI,kBAAkB,GAAG;GACjC;GAEA,IAAI,CADgB,cAAc,WACrB,CAAC,CAAC,SAAS,IAAI,IAAI,GAAG;IACjC,OAAO,KACL;KAAE;KAAc;KAAkB;IAAI,GACtC,oCACF;IACA,MAAM,IAAI,kBAAkB,GAAG;GACjC;GACA,IAAI,aAAa,YAAY,GAC3B,OAAO,KAAK,EAAE,IAAI,GAAG,2BAA2B;GAElD,MAAM;EACR;CACF;CAEA,QACE,cACA,kBAC+B;EAC/B,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,gBAAgB;GACjD,QAAQ,iBAAiB;EAC3B,SACM,KAAK,SAAS,cAAc,gBAAgB,CACpD;CACF;;;;;;;;;;CAWA,MAAc,WACZ,EAAE,aAAa,YAAY,aAAa,iBACxC,UACwB;EACxB,IAAI;EACJ,IAAI;EACJ,IAAI,eAAe,YAAY;GAE7B,eAAe;GACf,mBAAmB;EACrB,OAEE,CAAC,CAAE,cAAc,oBAAqB,sBACpC,aACA,WACF;EAEF,OAAO,MAEL,aAAa,aAAa,IAAI,iBAAiB,IAAI,SAAS,EAC9D;EACA,MAAM,SAAS,iBAAiB,QAAQ,IAAI,WAAW;EACvD,IAAI,SAAwB;EAC5B,IAAI;GACF,IAAI,eAA0C;GAC9C,IAAI,iBAAiB,eAAe,aAAa,GAC/C,eAAe,MAAM,KAAK,qBACxB,cACA,kBACA,aACF;GAGF,IAAI,mBAAwC;GAC5C,IAAI,CAAC,cAAc;IAEjB,IAAI,iBAAA,2BAA6B;KAE/B,MAAM,gBAAe,MADD,eAAe,KAAK,gBAAgB,EAAA,CAC7B,gBAAgB,MAAM;KACjD,IAAI,cACF,OAAO;IAEX;IAEA,mBAAmB,MAAM,KAAK,oBAC5B,cACA,kBACA,QACA,MACF;IAEA,IACE,oBACA,OAAO,yBAAyB,iBAAiB,OAAO,GAExD,SACG,iBAAiB,QAAQ,4BAC1B;GAEN;GAEA,IACE,iBAAiB,YAAY,KAC5B,oBACC,CAAC,OAAO,yBAAyB,iBAAiB,OAAO,GAC3D;IAEA,IAAI,iBAAiB,YAAY,KAAK,iBAAA,2BAA6B;KAEjE,MAAM,gBAAe,MADD,eAAe,KAAK,gBAAgB,EAAA,CAC7B,oBAAoB,QAAQ,YAAY;KACnE,IAAI,cACF,OAAO;IAEX;IAEA,OAAO,MACL;KAAE;KAAc;IAAiB,GACjC,8FACF;IACA,mBAAmB,MAAM,KAAK,oBAC5B,cACA,kBACA,MACF;IAEA,IAAI,gBAAgB,kBAAkB;KACpC,MAAM,SAAS,aAAa,UAAU,iBAAiB,IAAI;;KAE3D,IAAI,OAAO,SAAS;MAClB,MAAM,eAAe,OAAO;MAC5B,IACE,aAAa,cACX,+DACF,aAAa,cACX,2CAEG;YAAA,MAAM,YAAY,aAAa,WAClC,IAAI,SAAS,UAAU,iBAAiB,cAAc;QACpD,SAAS,SAAS;QAClB;OACF;aAOG,IACL,OAAO,yBAAyB,iBAAiB,OAAO,GAIxD,SAAS,iBAAiB,QACxB;KAGN,OACE,OAAO,MACL;MACE;MACA;MACA;MACA,MAAM,iBAAiB;MACvB,SAAS,iBAAiB;MAC1B,KAAK,OAAO;KACd,GACA,mCACF;IAEJ;IAEA,IAAI,CAAC,QAAQ;KACX,OAAO,MACL;MAAE;MAAc;MAAkB;KAAO,GACzC,6DACF;KACA,SAAS,8BAA8B,gBAAiB;IAC1D;GACF;GAEA,IACE,CAAC,oBACD,CAAC,iBAAiB,SAAS,GAAG,KAC9B,CAAC,YAAY,SAAS,GAAG,GACzB;IACA,OAAO,MACL,uBAAuB,aAAa,GAAG,iBAAiB,uBAC1D;IACA,OAAO,KAAK,UACV;KACE;KACA,aAAa,WAAW;KACxB;IACF,GACA,QACF;GACF;GAEA,IAAI,kBAEF,OAAO,MAAM,qBAAqB,QAAS;EAE/C,SAAS,gCAAgC;GACvC,IAAI,eAAe,mBACjB,MAAM;GAER,OAAO,MACL;IACE;IACA;IACA;GACF,GACA,8CACF;EACF;EACA,OAAO;CACT;CAEA,UACE,QACA,UACwB;EACxB,MAAM,SAAS,YAAY;EAC3B,MAAM,EAAE,cAAc,qBAAqB,sBACzC,OAAO,aACP,OAAO,WACT;EACA,OAAO,UACL;GACE,WAAW;GACX,KAAK,cACH,cACA,kBACA,QACA,OAAO,aACT;GACA,UAAU;EACZ,GACA,OAAO,QAAQ;GACb,MAAM,SAAS,MAAM,KAAK,WAAW,QAAQ,QAAQ;GACrD,IAAI,YAAY,iBAAiB,MAAM;GACvC,OAAO;EACT,CACF;CACF;CAEA,MAAc,kBACZ,kBAC2B;EAC3B,IAAI,MAAM,0CAA0C,iBAAiB;EAErE,MAAM,QAAQ,MAAM,eAAe,KAAK,gBAAgB;EACxD,MAAM,WAAW,aAAa,IAAI,gBAAgB;EAClD,MAAM,mBAAmB,+BAA+B,kBAAkB;EAC1E,IAAI,OAAO,GACT,eAAe;EACjB,OAAO,gBAAgB,OAAO,UAAU;GACtC,MAAM,EAAE,KAAK,QAAQ,MAAM,KAAK,KAC7B,YAAY,KAAK,iBAAiB,CAAC,CACnC,OAAO;GAEV,IAAI,KAAK;IACP,OAAO,MAAM,EAAE,IAAI,GAAG,4CAA4C;IAClE,OAAO;GACT;GACA;GACA,MAAM,EAAE,SAAS,MAAM,UAAU;GAEjC,eAAe,MAAM,UAAU,SAAS,KAAK;GAE7C,IAAI,CAAC,MACH;GAIF,MAAM,UAAU,qBAAqB,KAAK,MAAM,gBAAgB;GAChE,IAAI,CAAC,SAAS;IACZ,OAAO,KAAK,KACV;KAAE;KAAkB,SAAS;IAAK,GAClC,kEACF;IACA;GACF;GAEA,MAAM;EACR;EAEA,MAAM,MAAM,KAAK;EAGjB,OADc,MAAM,SACT,CAAC,CAAC,KAAK,EAAE,MAAM,SAAS,sBAAsB;GACvD,MAAM,UAAmB,EAAE,QAAQ;GAEnC,MAAM,mBAAmB,YAAY,eAAe;GACpD,IAAI,kBACF,QAAQ,mBAAmB;GAO7B,OAAO;EACT,CAAC;CACH;CAEA,iBAAiB,kBAAqD;EACpE,OAAO,UACL;GACE,WAAW;GACX,KAAK;EACP,SACM,KAAK,kBAAkB,gBAAgB,CAC/C;CACF;;;;;;;;;;;;CAaA,MAAc,aAAa,EACzB,aACA,eACmD;EACnD,MAAM,EAAE,cAAc,qBAAqB,sBACzC,aACA,WACF;EAOA,MAAM,gBACJ,OAAO,aACL,KAAK,QAAQ,cAAc,gBAAgB,GAC3C,YACF,CAAC,CAAC,WAAW,SAAS,KAAK,KAAK,aAAa,EAAE,QAAQ,EAAE,CAAC;EAE5D,MAAM,yBACJ,OAAO,aACL,KAAK,iBAAiB,gBAAgB,GACtC,iBACF,CAAC,CAAC,MAAM,OAAO;EAQjB,MAAM,EAAE,KAAK,UAAU,QAAQ,OAL7B,iBAAA,6BACA,CAAC,OAAO,CAAC,CAAC,qCACN,iBAAiB,IACjB,QAAQ,EAAA,CAEkC,OAAO;EACvD,IAAI,eAAe,OACjB,MAAM;OACD,IAAI,KACT,OAAO;EAGT,MAAM,MAAqB;GACzB,aAAa;GACb;EACF;EACA,IAAI,qBAAqB,aAEvB,IAAI,aAAa;EAGnB,MAAM,OAAO,SAAS,KAAK,YAAY,QAAQ,OAAO;EACtD,MAAM,YAAY,KAAK,SAAS,QAAQ,IACpC,WACC,iBAAiB,IAAI,KAAK,KAAK,GAAG,EAAE;;EAGzC,IAAI,CAAC,WACH,OAAO;EAET,MAAM,SAAS,MAAM,KAAK,UACxB,cACA,kBACA,SACF;EACA,IAAI,QAAQ;GACV,IAAI,iBAAiB,OAAA,oCAAmB,GACtC,IAAI,SAAS,OAAO;GAEtB,KAAK,MAAM,SAAS,cAClB,IAAI,iBAAiB,OAAO,MAAM,GAAG;IACnC,IAAI,YAAY,OAAO;IACvB;GACF;GAEF,IAAI,iBAAiB,OAAA,+BAAqB,GACxC,IAAI,WAAW,OAAO;EAE1B;EACA,OAAO;CACT;CAEA,YAAY,QAA0D;EACpE,MAAM,EAAE,cAAc,qBAAqB,sBACzC,OAAO,aACP,OAAO,WACT;EACA,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,gBAAgB;GACjD,QAAQ,iBAAiB;GACzB,UAAU;EACZ,SACM,KAAK,aAAa,MAAM,CAChC;CACF;AACF"}
1
+ {"version":3,"file":"index.js","names":["dockerVersioningId","HttpError"],"sources":["../../../../lib/modules/datasource/docker/index.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { PAGE_NOT_FOUND_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { buildCacheKey } from '../../../util/cache/package/key.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport {\n isBadRequest,\n isNotFound,\n isRateLimited,\n isServerError,\n isUnauthorized,\n} from '../../../util/http/status.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { hasKey } from '../../../util/object.ts';\nimport { type AsyncResult, Result } from '../../../util/result.ts';\nimport { isDockerDigest } from '../../../util/string-match.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport {\n ensurePathPrefix,\n joinUrlParts,\n parseLinkHeader,\n parseUrl,\n} from '../../../util/url.ts';\nimport { id as dockerVersioningId } from '../../versioning/docker/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type {\n DigestConfig,\n GetReleasesConfig,\n Release,\n ReleaseResult,\n} from '../types.ts';\nimport {\n isArtifactoryServer,\n isCrossOriginPaginationAllowed,\n resolvePaginationUrl,\n} from '../util.ts';\nimport {\n DOCKER_HUB,\n dockerDatasourceId,\n extractDigestFromResponseBody,\n findHelmSourceUrl,\n findLatestStable,\n getAuthHeaders,\n getRegistryRepository,\n gitRefLabel,\n imageUrlLabel,\n isDockerHost,\n sourceLabel,\n sourceLabels,\n} from './common.ts';\nimport { DockerHubCache } from './dockerhub-cache.ts';\nimport { ecrPublicRegex, ecrRegex, isECRMaxResultsError } from './ecr.ts';\nimport type {\n DistributionManifest,\n Manifest,\n OciImageManifest,\n} from './schema.ts';\nimport {\n DockerHubTagsPage,\n ManifestJson,\n OciHelmConfig,\n OciImageConfig,\n QuayTagsResponse,\n RegistryTagsList,\n} from './schema.ts';\n\nconst defaultConfig = {\n commitMessageTopic: '{{{depName}}} Docker tag',\n commitMessageExtra:\n 'to {{#if isPinDigest}}{{{newDigestShort}}}{{else}}{{#if isMajor}}{{{prettyNewMajor}}}{{else}}{{{prettyNewVersion}}}{{/if}}{{/if}}',\n digest: {\n branchTopic: '{{{depNameSanitized}}}-{{{currentValue}}}',\n commitMessageExtra: 'to {{newDigestShort}}',\n commitMessageTopic:\n '{{{depName}}}{{#if currentValue}}:{{{currentValue}}}{{/if}} Docker digest',\n group: {\n commitMessageTopic: '{{{groupName}}}',\n commitMessageExtra: '',\n },\n },\n pin: {\n commitMessageExtra: '',\n groupName: 'Docker digests',\n group: {\n commitMessageTopic: '{{{groupName}}}',\n branchTopic: 'digests-pin',\n },\n },\n};\n\nexport class DockerDatasource extends Datasource {\n static readonly id = dockerDatasourceId;\n\n override readonly defaultVersioning = dockerVersioningId;\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return [DOCKER_HUB];\n }\n\n override readonly defaultConfig = defaultConfig;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'Only supported on Docker Hub: The release timestamp is determined from the `tag_last_pushed` field in the results. **NOTE**: Currently, digests will receive the same release timestamp as the `tag_last_pushed`, which means that digests may appear newer than they are - see https://github.com/renovatebot/renovate/issues/38659';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from the `org.opencontainers.image.source` and `org.label-schema.vcs-url` labels present in the metadata of the **latest stable** image found on the Docker registry.';\n\n constructor() {\n super(DockerDatasource.id);\n }\n\n // TODO: debug why quay throws errors (#9612)\n private async getManifestResponse(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n mode: 'head' | 'getText' = 'getText',\n ): Promise<HttpResponse | null> {\n logger.debug(\n `getManifestResponse(${registryHost}, ${dockerRepository}, ${tag}, ${mode})`,\n );\n try {\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return null;\n }\n headers.accept = [\n 'application/vnd.docker.distribution.manifest.list.v2+json',\n 'application/vnd.docker.distribution.manifest.v2+json',\n 'application/vnd.oci.image.manifest.v1+json',\n 'application/vnd.oci.image.index.v1+json',\n ].join(', ');\n const url = `${registryHost}/v2/${dockerRepository}/manifests/${tag}`;\n const manifestResponse = await this.http[mode](url, {\n headers,\n noAuth: true,\n cacheProvider: memCacheProvider,\n });\n return manifestResponse;\n } catch (err) /* istanbul ignore next */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (isUnauthorized(err)) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Unauthorized docker lookup',\n );\n logger.debug({ err });\n return null;\n }\n if (isNotFound(err)) {\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Docker Manifest is unknown',\n );\n return null;\n }\n if (isRateLimited(err) && isDockerHost(registryHost)) {\n throw new ExternalHostError(err);\n }\n if (isServerError(err)) {\n throw new ExternalHostError(err);\n }\n if (err.code === 'ETIMEDOUT') {\n logger.debug(\n { registryHost },\n 'Timeout when attempting to connect to docker registry',\n );\n logger.debug({ err });\n return null;\n }\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Unknown Error looking up docker manifest',\n );\n return null;\n }\n }\n\n private async _getImageConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciImageConfig> | undefined> {\n logger.trace(\n `getImageConfig(${registryHost}, ${dockerRepository}, ${configDigest})`,\n );\n\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n /* v8 ignore next -- should never happen */\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return undefined;\n }\n const url = joinUrlParts(\n registryHost,\n 'v2',\n dockerRepository,\n 'blobs',\n configDigest,\n );\n return await this.http.getJson(\n url,\n {\n headers,\n noAuth: true,\n },\n OciImageConfig,\n );\n }\n\n getImageConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciImageConfig> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-imageconfig',\n key: buildCacheKey(registryHost, dockerRepository, configDigest),\n ttlMinutes: 1440 * 28,\n },\n () => this._getImageConfig(registryHost, dockerRepository, configDigest),\n );\n }\n\n private async _getHelmConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciHelmConfig> | undefined> {\n logger.trace(\n `getImageConfig(${registryHost}, ${dockerRepository}, ${configDigest})`,\n );\n\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n );\n /* v8 ignore next -- should never happen */\n if (!headers) {\n logger.warn('No docker auth found - returning');\n return undefined;\n }\n const url = joinUrlParts(\n registryHost,\n 'v2',\n dockerRepository,\n 'blobs',\n configDigest,\n );\n return await this.http.getJson(\n url,\n {\n headers,\n noAuth: true,\n },\n OciHelmConfig,\n );\n }\n\n getHelmConfig(\n registryHost: string,\n dockerRepository: string,\n configDigest: string,\n ): Promise<HttpResponse<OciHelmConfig> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-imageconfig',\n key: buildCacheKey(registryHost, dockerRepository, configDigest),\n ttlMinutes: 1440 * 28,\n },\n () => this._getHelmConfig(registryHost, dockerRepository, configDigest),\n );\n }\n\n private async getConfigDigest(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<string | null> {\n return (\n (await this.getManifest(registry, dockerRepository, tag))?.config\n ?.digest ?? null\n );\n }\n\n private async getManifestDocument(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Manifest | null> {\n const manifestResponse = await this.getManifestResponse(\n registry,\n dockerRepository,\n tag,\n );\n\n // If getting the manifest fails here, then abort\n // This means that the latest tag doesn't have a manifest, which shouldn't\n // be possible\n /* v8 ignore next -- should never happen */\n if (!manifestResponse) {\n return null;\n }\n\n // Softfail on invalid manifests\n const parsed = ManifestJson.safeParse(manifestResponse.body);\n if (!parsed.success) {\n logger.debug(\n {\n registry,\n dockerRepository,\n tag,\n body: manifestResponse.body,\n headers: manifestResponse.headers,\n err: parsed.error,\n },\n 'Invalid manifest response',\n );\n return null;\n }\n\n return parsed.data;\n }\n\n private async resolveImageManifest(\n registry: string,\n dockerRepository: string,\n tag: string,\n manifest: Manifest,\n ): Promise<OciImageManifest | DistributionManifest | null> {\n switch (manifest.mediaType) {\n case 'application/vnd.docker.distribution.manifest.v2+json':\n case 'application/vnd.oci.image.manifest.v1+json':\n return manifest;\n case 'application/vnd.docker.distribution.manifest.list.v2+json':\n case 'application/vnd.oci.image.index.v1+json':\n if (!manifest.manifests.length) {\n logger.debug(\n { manifest },\n 'Invalid manifest list with no manifests - returning',\n );\n return null;\n }\n logger.trace(\n { registry, dockerRepository, tag },\n 'Found manifest list, using first image',\n );\n return this.getManifest(\n registry,\n dockerRepository,\n manifest.manifests[0].digest,\n );\n // istanbul ignore next: can't happen\n default:\n return null;\n }\n }\n\n private async getManifest(\n registry: string,\n dockerRepository: string,\n tag: string,\n ): Promise<OciImageManifest | DistributionManifest | null> {\n const manifest = await this.getManifestDocument(\n registry,\n dockerRepository,\n tag,\n );\n if (!manifest) {\n return null;\n }\n return this.resolveImageManifest(registry, dockerRepository, tag, manifest);\n }\n\n private async _getImageArchitecture(\n registryHost: string,\n dockerRepository: string,\n currentDigest: string,\n ): Promise<string | null | undefined> {\n try {\n let manifestResponse: HttpResponse | null;\n\n try {\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n currentDigest,\n 'head',\n );\n } catch (_err) {\n const err =\n _err instanceof ExternalHostError\n ? _err.err\n : /* istanbul ignore next: can never happen */ _err;\n\n // v8 ignore else -- needs a non-5xx failure from the manifest request\n if (isServerError(err)) {\n // querying the digest manifest for a non existent image leads to a 500 statusCode\n return null;\n }\n\n /* istanbul ignore next */\n throw _err;\n }\n\n if (\n manifestResponse?.headers['content-type'] !==\n 'application/vnd.docker.distribution.manifest.v2+json' &&\n manifestResponse?.headers['content-type'] !==\n 'application/vnd.oci.image.manifest.v1+json'\n ) {\n return null;\n }\n\n const configDigest = await this.getConfigDigest(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n if (!configDigest) {\n return null;\n }\n\n const configResponse = await this.getImageConfig(\n registryHost,\n dockerRepository,\n configDigest,\n );\n\n // TODO: fix me, architecture is required in spec\n // v8 ignore else -- needs a config blob with neither key\n if (\n configResponse &&\n ['config', 'architecture'].some((key) => key in configResponse.body)\n ) {\n const architecture = configResponse.body.architecture ?? null;\n logger.debug(\n `Current digest ${currentDigest} relates to architecture ${\n architecture ?? 'null'\n }`,\n );\n\n return architecture;\n }\n } catch (err) /* istanbul ignore next */ {\n if (!isNotFound(err) || err.message === PAGE_NOT_FOUND_ERROR) {\n throw err;\n }\n logger.debug(\n { registryHost, dockerRepository, currentDigest, err },\n 'Unknown error getting image architecture',\n );\n }\n\n return undefined;\n }\n\n getImageArchitecture(\n registryHost: string,\n dockerRepository: string,\n currentDigest: string,\n ): Promise<string | null | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-architecture',\n key: buildCacheKey(registryHost, dockerRepository, currentDigest),\n ttlMinutes: 1440 * 28,\n },\n async (ctx) => {\n const architecture = await this._getImageArchitecture(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n ctx.cacheable = isNonEmptyString(architecture);\n return architecture;\n },\n );\n }\n\n /*\n * docker.getLabels\n *\n * This function will:\n * - Return the labels for the requested image\n */\n private async _getLabels(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Record<string, string> | undefined> {\n logger.debug(`getLabels(${registryHost}, ${dockerRepository}, ${tag})`);\n // Skip Docker Hub image if RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP is set\n if (\n getEnv().RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP &&\n registryHost === DOCKER_HUB\n ) {\n logger.debug(\n 'Docker Hub image - skipping label lookup due to RENOVATE_X_DOCKER_HUB_DISABLE_LABEL_LOOKUP',\n );\n return {};\n }\n try {\n let labels: Record<string, string> | undefined = {};\n const manifestDocument = await this.getManifestDocument(\n registryHost,\n dockerRepository,\n tag,\n );\n\n if (!manifestDocument) {\n logger.debug(\n { registryHost, dockerRepository, tag },\n 'No manifest found',\n );\n return undefined;\n }\n\n if ('annotations' in manifestDocument && manifestDocument.annotations) {\n labels = manifestDocument.annotations;\n }\n\n if ('manifests' in manifestDocument) {\n const descriptorAnnotations = manifestDocument.manifests\n .map((descriptor) => descriptor.annotations)\n .find(\n (annotations) =>\n isNonEmptyString(annotations?.[sourceLabel]) &&\n isNonEmptyString(annotations?.[gitRefLabel]),\n );\n if (descriptorAnnotations) {\n labels = { ...labels, ...descriptorAnnotations };\n }\n }\n\n if (\n 'manifests' in manifestDocument &&\n labels[sourceLabel] &&\n labels[gitRefLabel]\n ) {\n return labels;\n }\n\n const manifest = await this.resolveImageManifest(\n registryHost,\n dockerRepository,\n tag,\n manifestDocument,\n );\n if (!manifest) {\n return undefined;\n }\n\n if ('annotations' in manifest && manifest.annotations) {\n labels = { ...labels, ...manifest.annotations };\n }\n\n switch (manifest.config.mediaType) {\n case 'application/vnd.cncf.helm.config.v1+json': {\n if (labels[sourceLabel]) {\n // we already have the source url, so no need to pull the config\n return labels;\n }\n const configResponse = await this.getHelmConfig(\n registryHost,\n dockerRepository,\n manifest.config.digest,\n );\n\n // v8 ignore else -- needs the helm config blob request to come back empty\n if (configResponse) {\n // Helm chart\n const url = findHelmSourceUrl(configResponse.body);\n // v8 ignore else -- needs a helm chart with no source url\n if (url) {\n labels[sourceLabel] = url;\n }\n }\n break;\n }\n case 'application/vnd.oci.image.config.v1+json':\n case 'application/vnd.docker.container.image.v1+json': {\n if (labels[sourceLabel] && labels[gitRefLabel]) {\n // we already have the source url, so no need to pull the config\n return labels;\n }\n const configResponse = await this.getImageConfig(\n registryHost,\n dockerRepository,\n manifest.config.digest,\n );\n\n /* v8 ignore next -- should never happen */\n if (!configResponse) {\n return labels;\n }\n\n const body = configResponse.body;\n if (body.config) {\n labels = { ...labels, ...body.config.Labels };\n } else {\n logger.debug(\n { headers: configResponse.headers, body },\n `manifest blob response body missing the \"config\" property`,\n );\n }\n break;\n }\n }\n\n // v8 ignore else -- labels are always set by the branches above\n if (labels) {\n logger.debug(\n {\n labels,\n },\n 'found labels in manifest',\n );\n }\n return labels;\n } catch (err) /* istanbul ignore next: should be tested in future */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n if (isBadRequest(err) || isUnauthorized(err)) {\n logger.debug(\n { registryHost, dockerRepository, err },\n 'Unauthorized docker lookup',\n );\n } else if (isNotFound(err)) {\n logger.warn(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'Config Manifest is unknown',\n );\n } else if (isRateLimited(err) && isDockerHost(registryHost)) {\n logger.warn({ err }, 'docker registry failure: too many requests');\n } else if (isServerError(err)) {\n logger.debug(\n {\n err,\n registryHost,\n dockerRepository,\n tag,\n },\n 'docker registry failure: internal error',\n );\n } else if (\n err.code === 'ERR_TLS_CERT_ALTNAME_INVALID' ||\n err.code === 'ETIMEDOUT'\n ) {\n logger.debug(\n { registryHost, err },\n 'Error connecting to docker registry',\n );\n } else if (registryHost === 'https://quay.io') {\n // istanbul ignore next\n logger.debug(\n 'Ignoring quay.io errors until they fully support v2 schema',\n );\n } else {\n logger.info(\n { registryHost, dockerRepository, tag, err },\n 'Unknown error getting Docker labels',\n );\n }\n return {};\n }\n }\n\n getLabels(\n registryHost: string,\n dockerRepository: string,\n tag: string,\n ): Promise<Record<string, string> | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-labels',\n key: buildCacheKey(registryHost, dockerRepository, tag),\n ttlMinutes: 24 * 60,\n },\n () => this._getLabels(registryHost, dockerRepository, tag),\n );\n }\n\n private async getTagsQuayRegistry(\n registry: string,\n repository: string,\n ): Promise<string[]> {\n let tags: string[] = [];\n const limit = 100;\n\n function pageUrl(page: number): string {\n return `${registry}/api/v1/repository/${repository}/tag/?limit=${limit}&page=${page}&onlyActiveTags=true`;\n }\n\n let page = 1;\n let url: string | null = pageUrl(page);\n while (url && page <= 20) {\n const res: HttpResponse<QuayTagsResponse> = await this.http.getJson(\n url,\n QuayTagsResponse,\n );\n const pageTags = res.body.tags.map((tag) => tag.name);\n tags = tags.concat(pageTags);\n page += 1;\n url = res.body.has_additional ? pageUrl(page) : null;\n }\n return tags;\n }\n\n private async getDockerApiTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | undefined> {\n let tags: string[] = [];\n // AWS ECR limits the maximum number of results to 1000\n // See https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeRepositories.html#ECR-DescribeRepositories-request-maxResults\n // See https://docs.aws.amazon.com/AmazonECRPublic/latest/APIReference/API_DescribeRepositories.html#ecrpublic-DescribeRepositories-request-maxResults\n const limit =\n ecrRegex.test(registryHost) || ecrPublicRegex.test(registryHost)\n ? 1000\n : 10000;\n let url: string | null =\n `${registryHost}/${dockerRepository}/tags/list?n=${limit}`;\n url = ensurePathPrefix(url, '/v2');\n const headers = await getAuthHeaders(\n this.http,\n registryHost,\n dockerRepository,\n url,\n );\n if (!headers) {\n logger.debug('Failed to get authHeaders for getTags lookup');\n return undefined;\n }\n let page = 0;\n const hostsNeedingAllPages = [\n 'https://ghcr.io', // GHCR sorts from oldest to newest, so we need to get all pages\n 'https://quay.io', // Quay sorts from oldest to newest, so we need to get all pages\n 'https://cgr.dev', // Chainguard sorts lexically and publishes a tag per build, so current versions sort past the page limit\n 'https://registry.access.redhat.com', // RH catalog; Quay-style lexicographic sort, high tag counts\n 'https://registry.redhat.io', // RH authenticated catalog; same backend\n ];\n const pages = hostsNeedingAllPages.includes(registryHost)\n ? 1000\n : GlobalConfig.get('dockerMaxPages');\n logger.trace({ registryHost, dockerRepository, pages }, 'docker.getTags');\n const allowCrossOrigin = isCrossOriginPaginationAllowed(dockerDatasourceId);\n let foundMaxResultsError = false;\n do {\n let res: HttpResponse<RegistryTagsList>;\n try {\n res = await this.http.getJson(\n url,\n { headers, noAuth: true },\n RegistryTagsList,\n );\n } catch (err) {\n if (\n !foundMaxResultsError &&\n err instanceof HttpError &&\n isECRMaxResultsError(err)\n ) {\n const maxResults = 1000;\n url = `${registryHost}/${dockerRepository}/tags/list?n=${maxResults}`;\n url = ensurePathPrefix(url, '/v2');\n foundMaxResultsError = true;\n continue;\n }\n throw err;\n }\n tags = tags.concat(res.body.tags);\n const linkHeader = parseLinkHeader(res.headers.link);\n if (isArtifactoryServer(res)) {\n // Artifactory bug: next link comes back without virtual-repo prefix (RTFACT-18971)\n if (linkHeader?.next?.last) {\n // parse the current URL, strip any old \"last\" param, then set the new one\n const parsed = parseUrl(url);\n // v8 ignore if: url is always a valid HTTP URL as `ensurePathPrefix`\n if (!parsed) {\n url = null;\n break;\n }\n parsed.searchParams.delete('last');\n parsed.searchParams.set('last', linkHeader.next.last);\n url = parsed.href;\n } else {\n url = null;\n }\n } else if (linkHeader?.next?.url) {\n // Resolve the relative-or-absolute next link, not following cross-origin requests unless explicitly opted in\n const nextUrl = resolvePaginationUrl(\n url,\n linkHeader.next.url,\n allowCrossOrigin,\n );\n if (!nextUrl) {\n // make sure that users are aware if there are any (potentially malicious, or misconfigured) pagination links being returned\n logger.once.warn(\n { registryHost, nextUrl: linkHeader.next.url },\n 'Ignoring cross-origin or invalid Docker registry tags pagination link',\n );\n }\n url = nextUrl;\n } else {\n url = null;\n }\n page += 1;\n } while (url && page < pages);\n return tags;\n }\n\n private async _getTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | undefined> {\n try {\n const isQuay = registryHost === 'https://quay.io';\n let tags: string[] | undefined;\n if (isQuay) {\n try {\n // Due to pagination and sorting limits on Quay Docker v2 API implementation we try the Quay v1 API first\n tags = await this.getTagsQuayRegistry(registryHost, dockerRepository);\n } catch (err) {\n // If we get a 401 Unauthorized error (v1 API requires separate auth for private images), fall back to Docker v2 API\n if (isUnauthorized(err)) {\n logger.debug(\n { registryHost, dockerRepository },\n 'Quay v1 API unauthorized, falling back to Docker v2 API',\n );\n tags = await this.getDockerApiTags(registryHost, dockerRepository);\n } else {\n throw err;\n }\n }\n } else {\n tags = await this.getDockerApiTags(registryHost, dockerRepository);\n }\n return tags;\n } catch (_err) /* istanbul ignore next */ {\n const err = _err instanceof ExternalHostError ? _err.err : _err;\n\n const notFound = isNotFound(err) || err.message === PAGE_NOT_FOUND_ERROR;\n\n if (notFound && !dockerRepository.includes('/')) {\n logger.debug(\n `Retrying Tags for ${registryHost}/${dockerRepository} using library/ prefix`,\n );\n return this.getTags(registryHost, `library/${dockerRepository}`);\n }\n // JFrog Artifactory - Retry handling when resolving Docker Official Images\n // These follow the format of {{registryHost}}{{jFrogRepository}}/library/{{dockerRepository}}\n if (\n notFound &&\n isArtifactoryServer(err.response) &&\n dockerRepository.split('/').length === 2\n ) {\n logger.debug(\n `JFrog Artifactory: Retrying Tags for ${registryHost}/${dockerRepository} using library/ path between JFrog virtual repository and image`,\n );\n\n const dockerRepositoryParts = dockerRepository.split('/');\n const jfrogRepository = dockerRepositoryParts[0];\n const dockerImage = dockerRepositoryParts[1];\n\n return this.getTags(\n registryHost,\n `${jfrogRepository}/library/${dockerImage}`,\n );\n }\n if (isRateLimited(err) && isDockerHost(registryHost)) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry failure: too many requests',\n );\n throw new ExternalHostError(err);\n }\n if (isServerError(err)) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry failure: internal error',\n );\n throw new ExternalHostError(err);\n }\n const errorCodes = ['ECONNRESET', 'ETIMEDOUT'];\n if (errorCodes.includes(err.code)) {\n logger.warn(\n { registryHost, dockerRepository, err },\n 'docker registry connection failure',\n );\n throw new ExternalHostError(err);\n }\n if (isDockerHost(registryHost)) {\n logger.info({ err }, 'Docker Hub lookup failure');\n }\n throw _err;\n }\n }\n\n getTags(\n registryHost: string,\n dockerRepository: string,\n ): Promise<string[] | undefined> {\n return withCache(\n {\n namespace: 'datasource-docker-tags',\n key: buildCacheKey(registryHost, dockerRepository),\n public: registryHost === DOCKER_HUB,\n },\n () => this._getTags(registryHost, dockerRepository),\n );\n }\n\n /**\n * docker.getDigest\n *\n * The `newValue` supplied here should be a valid tag for the docker image.\n *\n * This function will:\n * - Look up a sha256 digest for a tag on its registry\n * - Return the digest as a string\n */\n private async _getDigest(\n { registryUrl, lookupName, packageName, currentDigest }: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n let registryHost: string;\n let dockerRepository: string;\n if (registryUrl && lookupName) {\n // Reuse the resolved values from getReleases()\n registryHost = registryUrl;\n dockerRepository = lookupName;\n } else {\n // Resolve values independently\n ({ registryHost, dockerRepository } = getRegistryRepository(\n packageName,\n registryUrl!,\n ));\n }\n logger.debug(\n // TODO: types (#22198)\n `getDigest(${registryHost}, ${dockerRepository}, ${newValue})`,\n );\n const newTag = isNonEmptyString(newValue) ? newValue : 'latest';\n let digest: string | null = null;\n try {\n let architecture: string | null | undefined = null;\n if (currentDigest && isDockerDigest(currentDigest)) {\n architecture = await this.getImageArchitecture(\n registryHost,\n dockerRepository,\n currentDigest,\n );\n }\n\n let manifestResponse: HttpResponse | null = null;\n if (!architecture) {\n // Reuse the digest cached from the Docker Hub tag API\n if (registryHost === DOCKER_HUB) {\n const cache = await DockerHubCache.init(dockerRepository);\n const cachedDigest = cache.getDigestForTag(newTag);\n if (cachedDigest) {\n return cachedDigest;\n }\n }\n\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n newTag,\n 'head',\n );\n\n if (\n manifestResponse &&\n hasKey('docker-content-digest', manifestResponse.headers)\n ) {\n digest =\n (manifestResponse.headers['docker-content-digest'] as string) ||\n null;\n }\n }\n\n const lacksContentDigest =\n manifestResponse &&\n !hasKey('docker-content-digest', manifestResponse.headers);\n if (isNonEmptyString(architecture) || lacksContentDigest) {\n // Reuse the per-arch digest cached from the Docker Hub tag API\n if (isNonEmptyString(architecture) && registryHost === DOCKER_HUB) {\n const cache = await DockerHubCache.init(dockerRepository);\n const cachedDigest = cache.getArchDigestForTag(newTag, architecture);\n if (cachedDigest) {\n return cachedDigest;\n }\n }\n\n logger.debug(\n { registryHost, dockerRepository },\n 'Architecture-specific digest or missing docker-content-digest header - pulling full manifest',\n );\n manifestResponse = await this.getManifestResponse(\n registryHost,\n dockerRepository,\n newTag,\n );\n\n if (architecture && manifestResponse) {\n const parsed = ManifestJson.safeParse(manifestResponse.body);\n /* istanbul ignore else: hard to test */\n if (parsed.success) {\n const manifestList = parsed.data;\n if (\n manifestList.mediaType ===\n 'application/vnd.docker.distribution.manifest.list.v2+json' ||\n manifestList.mediaType ===\n 'application/vnd.oci.image.index.v1+json'\n ) {\n for (const manifest of manifestList.manifests) {\n if (manifest.platform?.architecture === architecture) {\n digest = manifest.digest;\n break;\n }\n }\n // TODO: return null if no matching architecture digest found\n // https://github.com/renovatebot/renovate/discussions/22639\n // NOTE: reaching the implicit else needs a manifest list with no\n // digest header. A coverage-ignore hint cannot suppress it on an\n // `else if`.\n } else if (\n hasKey('docker-content-digest', manifestResponse.headers)\n ) {\n // TODO: return null if no matching architecture, requires to fetch the config manifest\n // https://github.com/renovatebot/renovate/discussions/22639\n digest = manifestResponse.headers[\n 'docker-content-digest'\n ] as string;\n }\n } else {\n logger.debug(\n {\n registryHost,\n dockerRepository,\n newTag,\n body: manifestResponse.body,\n headers: manifestResponse.headers,\n err: parsed.error,\n },\n 'Failed to parse manifest response',\n );\n }\n }\n\n if (!digest) {\n logger.debug(\n { registryHost, dockerRepository, newTag },\n 'Extraction digest from manifest response body is deprecated',\n );\n digest = extractDigestFromResponseBody(manifestResponse!);\n }\n }\n\n if (\n !manifestResponse &&\n !dockerRepository.includes('/') &&\n !packageName.includes('/')\n ) {\n logger.debug(\n `Retrying Digest for ${registryHost}/${dockerRepository} using library/ prefix`,\n );\n return this.getDigest(\n {\n registryUrl,\n packageName: `library/${packageName}`,\n currentDigest,\n },\n newValue,\n );\n }\n\n if (manifestResponse) {\n // TODO: fix types (#22198)\n logger.debug(`Got docker digest ${digest!}`);\n }\n } catch (err) /* istanbul ignore next */ {\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n {\n err,\n packageName,\n newTag,\n },\n 'Unknown Error looking up docker image digest',\n );\n }\n return digest;\n }\n\n override getDigest(\n config: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n const newTag = newValue ?? 'latest';\n const { registryHost, dockerRepository } = getRegistryRepository(\n config.packageName,\n config.registryUrl!,\n );\n return withCache(\n {\n namespace: 'datasource-docker-digest',\n key: buildCacheKey(\n registryHost,\n dockerRepository,\n newTag,\n config.currentDigest,\n ),\n fallback: true,\n },\n async (ctx) => {\n const digest = await this._getDigest(config, newValue);\n ctx.cacheable = isNonEmptyString(digest);\n return digest;\n },\n );\n }\n\n private async _getDockerHubTags(\n dockerRepository: string,\n ): Promise<Release[] | null> {\n let url = `https://hub.docker.com/v2/repositories/${dockerRepository}/tags?page_size=1000&ordering=last_updated`;\n\n const cache = await DockerHubCache.init(dockerRepository);\n const maxPages = GlobalConfig.get('dockerMaxPages');\n const allowCrossOrigin = isCrossOriginPaginationAllowed(dockerDatasourceId);\n let page = 0,\n needNextPage = true;\n while (needNextPage && page < maxPages) {\n const { val, err } = await this.http\n .getJsonSafe(url, DockerHubTagsPage)\n .unwrap();\n\n if (err) {\n logger.debug({ err }, `Docker: error fetching data from DockerHub`);\n return null;\n }\n page++;\n const { results, next, count } = val;\n\n needNextPage = cache.reconcile(results, count);\n\n if (!next) {\n break;\n }\n\n // Only follow the `next` link when it's on the same origin, unless explicitly opted in\n const nextUrl = resolvePaginationUrl(url, next, allowCrossOrigin);\n if (!nextUrl) {\n logger.once.warn(\n { dockerRepository, nextUrl: next },\n 'Ignoring cross-origin or invalid Docker Hub tags pagination link',\n );\n break;\n }\n\n url = nextUrl;\n }\n\n await cache.save();\n\n const items = cache.getItems();\n return items.map(({ name: version, tag_last_pushed }) => {\n const release: Release = { version };\n\n const releaseTimestamp = asTimestamp(tag_last_pushed);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n\n // Digest is intentionally not propagated — the Docker Hub tag API\n // returns the manifest-list digest, which would bypass arch-aware\n // resolution in `getDigest()`. `getDigest()` consults the same cache\n // as a shortcut when no arch resolution is needed.\n return release;\n });\n }\n\n getDockerHubTags(dockerRepository: string): Promise<Release[] | null> {\n return withCache(\n {\n namespace: 'datasource-docker-hub-tags',\n key: dockerRepository,\n },\n () => this._getDockerHubTags(dockerRepository),\n );\n }\n\n /**\n * docker.getReleases\n *\n * A docker image usually looks something like this: somehost.io/owner/repo:8.1.0-alpine\n * In the above:\n * - 'somehost.io' is the registry\n * - 'owner/repo' is the package name\n * - '8.1.0-alpine' is the tag\n *\n * This function will filter only tags that contain a semver version\n */\n private async _getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n const { registryHost, dockerRepository } = getRegistryRepository(\n packageName,\n registryUrl!,\n );\n\n type TagsResultType = AsyncResult<\n Release[],\n NonNullable<Error | 'tags-error' | 'dockerhub-error'>\n >;\n\n const getTags = (): TagsResultType =>\n Result.wrapNullable(\n this.getTags(registryHost, dockerRepository),\n 'tags-error' as const,\n ).transform((tags) => tags.map((version) => ({ version })));\n\n const getDockerHubTags = (): TagsResultType =>\n Result.wrapNullable(\n this.getDockerHubTags(dockerRepository),\n 'dockerhub-error' as const,\n ).catch(getTags);\n\n const tagsResult =\n registryHost === DOCKER_HUB &&\n !getEnv().RENOVATE_X_DOCKER_HUB_TAGS_DISABLE\n ? getDockerHubTags()\n : getTags();\n\n const { val: releases, err } = await tagsResult.unwrap();\n if (err instanceof Error) {\n throw err;\n } else if (err) {\n return null;\n }\n\n const ret: ReleaseResult = {\n registryUrl: registryHost,\n releases,\n };\n if (dockerRepository !== packageName) {\n // This will be reused later if a getDigest() call is made\n ret.lookupName = dockerRepository;\n }\n\n const tags = releases.map((release) => release.version);\n const latestTag = tags.includes('latest')\n ? 'latest'\n : (findLatestStable(tags) ?? tags.at(-1));\n\n /* v8 ignore next -- TODO: add test */\n if (!latestTag) {\n return ret;\n }\n const labels = await this.getLabels(\n registryHost,\n dockerRepository,\n latestTag,\n );\n if (labels) {\n if (isNonEmptyString(labels[gitRefLabel])) {\n ret.gitRef = labels[gitRefLabel];\n }\n for (const label of sourceLabels) {\n if (isNonEmptyString(labels[label])) {\n ret.sourceUrl = labels[label];\n break;\n }\n }\n if (isNonEmptyString(labels[imageUrlLabel])) {\n ret.homepage = labels[imageUrlLabel];\n }\n }\n return ret;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n const { registryHost, dockerRepository } = getRegistryRepository(\n config.packageName,\n config.registryUrl!,\n );\n return withCache(\n {\n namespace: 'datasource-docker-releases-v2',\n key: buildCacheKey(registryHost, dockerRepository),\n public: registryHost === DOCKER_HUB,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAuEA,MAAM,gBAAgB;CACpB,oBAAoB;CACpB,oBACE;CACF,QAAQ;EACN,aAAa;EACb,oBAAoB;EACpB,oBACE;EACF,OAAO;GACL,oBAAoB;GACpB,oBAAoB;EACtB;CACF;CACA,KAAK;EACH,oBAAoB;EACpB,WAAW;EACX,OAAO;GACL,oBAAoB;GACpB,aAAa;EACf;CACF;AACF;AAEA,IAAa,mBAAb,MAAa,yBAAyB,WAAW;CAC/C,OAAgB,KAAK;CAErB,oBAAsCA;CAEtC,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,UAAU;CACpB;CAEA,gBAAkC;CAElC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,cAAc;EACZ,MAAM,iBAAiB,EAAE;CAC3B;CAGA,MAAc,oBACZ,cACA,kBACA,KACA,OAA2B,WACG;EAC9B,OAAO,MACL,uBAAuB,aAAa,IAAI,iBAAiB,IAAI,IAAI,IAAI,KAAK,EAC5E;EACA,IAAI;GACF,MAAM,UAAU,MAAM,eACpB,KAAK,MACL,cACA,gBACF;GACA,IAAI,CAAC,SAAS;IACZ,OAAO,KAAK,kCAAkC;IAC9C,OAAO;GACT;GACA,QAAQ,SAAS;IACf;IACA;IACA;IACA;GACF,CAAC,CAAC,KAAK,IAAI;GACX,MAAM,MAAM,GAAG,aAAa,MAAM,iBAAiB,aAAa;GAMhE,OAAO,MALwB,KAAK,KAAK,KAAK,CAAC,KAAK;IAClD;IACA,QAAQ;IACR,eAAe;GACjB,CAAC;EAEH,SAAS,gCAAgC;GACvC,IAAI,eAAe,mBACjB,MAAM;GAER,IAAI,eAAe,GAAG,GAAG;IACvB,OAAO,MACL;KAAE;KAAc;IAAiB,GACjC,4BACF;IACA,OAAO,MAAM,EAAE,IAAI,CAAC;IACpB,OAAO;GACT;GACA,IAAI,WAAW,GAAG,GAAG;IACnB,OAAO,MACL;KACE;KACA;KACA;KACA;IACF,GACA,4BACF;IACA,OAAO;GACT;GACA,IAAI,cAAc,GAAG,KAAK,aAAa,YAAY,GACjD,MAAM,IAAI,kBAAkB,GAAG;GAEjC,IAAI,cAAc,GAAG,GACnB,MAAM,IAAI,kBAAkB,GAAG;GAEjC,IAAI,IAAI,SAAS,aAAa;IAC5B,OAAO,MACL,EAAE,aAAa,GACf,uDACF;IACA,OAAO,MAAM,EAAE,IAAI,CAAC;IACpB,OAAO;GACT;GACA,OAAO,MACL;IACE;IACA;IACA;IACA;GACF,GACA,0CACF;GACA,OAAO;EACT;CACF;CAEA,MAAc,gBACZ,cACA,kBACA,cACmD;EACnD,OAAO,MACL,kBAAkB,aAAa,IAAI,iBAAiB,IAAI,aAAa,EACvE;EAEA,MAAM,UAAU,MAAM,eACpB,KAAK,MACL,cACA,gBACF;;EAEA,IAAI,CAAC,SAAS;GACZ,OAAO,KAAK,kCAAkC;GAC9C;EACF;EACA,MAAM,MAAM,aACV,cACA,MACA,kBACA,SACA,YACF;EACA,OAAO,MAAM,KAAK,KAAK,QACrB,KACA;GACE;GACA,QAAQ;EACV,GACA,cACF;CACF;CAEA,eACE,cACA,kBACA,cACmD;EACnD,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,kBAAkB,YAAY;GAC/D,YAAY;EACd,SACM,KAAK,gBAAgB,cAAc,kBAAkB,YAAY,CACzE;CACF;CAEA,MAAc,eACZ,cACA,kBACA,cACkD;EAClD,OAAO,MACL,kBAAkB,aAAa,IAAI,iBAAiB,IAAI,aAAa,EACvE;EAEA,MAAM,UAAU,MAAM,eACpB,KAAK,MACL,cACA,gBACF;;EAEA,IAAI,CAAC,SAAS;GACZ,OAAO,KAAK,kCAAkC;GAC9C;EACF;EACA,MAAM,MAAM,aACV,cACA,MACA,kBACA,SACA,YACF;EACA,OAAO,MAAM,KAAK,KAAK,QACrB,KACA;GACE;GACA,QAAQ;EACV,GACA,aACF;CACF;CAEA,cACE,cACA,kBACA,cACkD;EAClD,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,kBAAkB,YAAY;GAC/D,YAAY;EACd,SACM,KAAK,eAAe,cAAc,kBAAkB,YAAY,CACxE;CACF;CAEA,MAAc,gBACZ,UACA,kBACA,KACwB;EACxB,QACG,MAAM,KAAK,YAAY,UAAU,kBAAkB,GAAG,EAAA,EAAI,QACvD,UAAU;CAElB;CAEA,MAAc,oBACZ,UACA,kBACA,KAC0B;EAC1B,MAAM,mBAAmB,MAAM,KAAK,oBAClC,UACA,kBACA,GACF;;EAMA,IAAI,CAAC,kBACH,OAAO;EAIT,MAAM,SAAS,aAAa,UAAU,iBAAiB,IAAI;EAC3D,IAAI,CAAC,OAAO,SAAS;GACnB,OAAO,MACL;IACE;IACA;IACA;IACA,MAAM,iBAAiB;IACvB,SAAS,iBAAiB;IAC1B,KAAK,OAAO;GACd,GACA,2BACF;GACA,OAAO;EACT;EAEA,OAAO,OAAO;CAChB;CAEA,MAAc,qBACZ,UACA,kBACA,KACA,UACyD;EACzD,QAAQ,SAAS,WAAjB;GACE,KAAK;GACL,KAAK,8CACH,OAAO;GACT,KAAK;GACL,KAAK;IACH,IAAI,CAAC,SAAS,UAAU,QAAQ;KAC9B,OAAO,MACL,EAAE,SAAS,GACX,qDACF;KACA,OAAO;IACT;IACA,OAAO,MACL;KAAE;KAAU;KAAkB;IAAI,GAClC,wCACF;IACA,OAAO,KAAK,YACV,UACA,kBACA,SAAS,UAAU,EAAE,CAAC,MACxB;;GAEF,SACE,OAAO;EACX;CACF;CAEA,MAAc,YACZ,UACA,kBACA,KACyD;EACzD,MAAM,WAAW,MAAM,KAAK,oBAC1B,UACA,kBACA,GACF;EACA,IAAI,CAAC,UACH,OAAO;EAET,OAAO,KAAK,qBAAqB,UAAU,kBAAkB,KAAK,QAAQ;CAC5E;CAEA,MAAc,sBACZ,cACA,kBACA,eACoC;EACpC,IAAI;GACF,IAAI;GAEJ,IAAI;IACF,mBAAmB,MAAM,KAAK,oBAC5B,cACA,kBACA,eACA,MACF;GACF,SAAS,MAAM;IACb,MAAM,MACJ,gBAAgB,oBACZ,KAAK,mDACwC;;IAGnD,IAAI,cAAc,GAAG,GAEnB,OAAO;;IAIT,MAAM;GACR;GAEA,IACE,kBAAkB,QAAQ,oBACxB,0DACF,kBAAkB,QAAQ,oBACxB,8CAEF,OAAO;GAGT,MAAM,eAAe,MAAM,KAAK,gBAC9B,cACA,kBACA,aACF;GACA,IAAI,CAAC,cACH,OAAO;GAGT,MAAM,iBAAiB,MAAM,KAAK,eAChC,cACA,kBACA,YACF;;GAIA,IACE,kBACA,CAAC,UAAU,cAAc,CAAC,CAAC,MAAM,QAAQ,OAAO,eAAe,IAAI,GACnE;IACA,MAAM,eAAe,eAAe,KAAK,gBAAgB;IACzD,OAAO,MACL,kBAAkB,cAAc,2BAC9B,gBAAgB,QAEpB;IAEA,OAAO;GACT;EACF,SAAS,gCAAgC;GACvC,IAAI,CAAC,WAAW,GAAG,KAAK,IAAI,YAAA,kBAC1B,MAAM;GAER,OAAO,MACL;IAAE;IAAc;IAAkB;IAAe;GAAI,GACrD,0CACF;EACF;CAGF;CAEA,qBACE,cACA,kBACA,eACoC;EACpC,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,kBAAkB,aAAa;GAChE,YAAY;EACd,GACA,OAAO,QAAQ;GACb,MAAM,eAAe,MAAM,KAAK,sBAC9B,cACA,kBACA,aACF;GACA,IAAI,YAAY,iBAAiB,YAAY;GAC7C,OAAO;EACT,CACF;CACF;CAQA,MAAc,WACZ,cACA,kBACA,KAC6C;EAC7C,OAAO,MAAM,aAAa,aAAa,IAAI,iBAAiB,IAAI,IAAI,EAAE;EAEtE,IACE,OAAO,CAAC,CAAC,8CACT,iBAAA,2BACA;GACA,OAAO,MACL,4FACF;GACA,OAAO,CAAC;EACV;EACA,IAAI;GACF,IAAI,SAA6C,CAAC;GAClD,MAAM,mBAAmB,MAAM,KAAK,oBAClC,cACA,kBACA,GACF;GAEA,IAAI,CAAC,kBAAkB;IACrB,OAAO,MACL;KAAE;KAAc;KAAkB;IAAI,GACtC,mBACF;IACA;GACF;GAEA,IAAI,iBAAiB,oBAAoB,iBAAiB,aACxD,SAAS,iBAAiB;GAG5B,IAAI,eAAe,kBAAkB;IACnC,MAAM,wBAAwB,iBAAiB,UAC5C,KAAK,eAAe,WAAW,WAAW,CAAC,CAC3C,MACE,gBACC,iBAAiB,cAAA,kCAA0B,KAC3C,iBAAiB,cAAA,oCAA0B,CAC/C;IACF,IAAI,uBACF,SAAS;KAAE,GAAG;KAAQ,GAAG;IAAsB;GAEnD;GAEA,IACE,eAAe,oBACf,OAAA,sCACA,OAAA,sCAEA,OAAO;GAGT,MAAM,WAAW,MAAM,KAAK,qBAC1B,cACA,kBACA,KACA,gBACF;GACA,IAAI,CAAC,UACH;GAGF,IAAI,iBAAiB,YAAY,SAAS,aACxC,SAAS;IAAE,GAAG;IAAQ,GAAG,SAAS;GAAY;GAGhD,QAAQ,SAAS,OAAO,WAAxB;IACE,KAAK,4CAA4C;KAC/C,IAAI,OAAA,oCAEF,OAAO;KAET,MAAM,iBAAiB,MAAM,KAAK,cAChC,cACA,kBACA,SAAS,OAAO,MAClB;;KAGA,IAAI,gBAAgB;MAElB,MAAM,MAAM,kBAAkB,eAAe,IAAI;;MAEjD,IAAI,KACF,OAAO,eAAe;KAE1B;KACA;IACF;IACA,KAAK;IACL,KAAK,kDAAkD;KACrD,IAAI,OAAA,sCAAuB,OAAA,sCAEzB,OAAO;KAET,MAAM,iBAAiB,MAAM,KAAK,eAChC,cACA,kBACA,SAAS,OAAO,MAClB;;KAGA,IAAI,CAAC,gBACH,OAAO;KAGT,MAAM,OAAO,eAAe;KAC5B,IAAI,KAAK,QACP,SAAS;MAAE,GAAG;MAAQ,GAAG,KAAK,OAAO;KAAO;UAE5C,OAAO,MACL;MAAE,SAAS,eAAe;MAAS;KAAK,GACxC,2DACF;KAEF;IACF;GACF;;GAGA,IAAI,QACF,OAAO,MACL,EACE,OACF,GACA,0BACF;GAEF,OAAO;EACT,SAAS,4DAA4D;GACnE,IAAI,eAAe,mBACjB,MAAM;GAER,IAAI,aAAa,GAAG,KAAK,eAAe,GAAG,GACzC,OAAO,MACL;IAAE;IAAc;IAAkB;GAAI,GACtC,4BACF;QACK,IAAI,WAAW,GAAG,GACvB,OAAO,KACL;IACE;IACA;IACA;IACA;GACF,GACA,4BACF;QACK,IAAI,cAAc,GAAG,KAAK,aAAa,YAAY,GACxD,OAAO,KAAK,EAAE,IAAI,GAAG,4CAA4C;QAC5D,IAAI,cAAc,GAAG,GAC1B,OAAO,MACL;IACE;IACA;IACA;IACA;GACF,GACA,yCACF;QACK,IACL,IAAI,SAAS,kCACb,IAAI,SAAS,aAEb,OAAO,MACL;IAAE;IAAc;GAAI,GACpB,qCACF;QACK,IAAI,iBAAiB;;GAE1B,OAAO,MACL,4DACF;QAEA,OAAO,KACL;IAAE;IAAc;IAAkB;IAAK;GAAI,GAC3C,qCACF;GAEF,OAAO,CAAC;EACV;CACF;CAEA,UACE,cACA,kBACA,KAC6C;EAC7C,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,kBAAkB,GAAG;GACtD,YAAY;EACd,SACM,KAAK,WAAW,cAAc,kBAAkB,GAAG,CAC3D;CACF;CAEA,MAAc,oBACZ,UACA,YACmB;EACnB,IAAI,OAAiB,CAAC;EACtB,MAAM,QAAQ;EAEd,SAAS,QAAQ,MAAsB;GACrC,OAAO,GAAG,SAAS,qBAAqB,WAAW,cAAc,MAAM,QAAQ,KAAK;EACtF;EAEA,IAAI,OAAO;EACX,IAAI,MAAqB,QAAQ,IAAI;EACrC,OAAO,OAAO,QAAQ,IAAI;GACxB,MAAM,MAAsC,MAAM,KAAK,KAAK,QAC1D,KACA,gBACF;GACA,MAAM,WAAW,IAAI,KAAK,KAAK,KAAK,QAAQ,IAAI,IAAI;GACpD,OAAO,KAAK,OAAO,QAAQ;GAC3B,QAAQ;GACR,MAAM,IAAI,KAAK,iBAAiB,QAAQ,IAAI,IAAI;EAClD;EACA,OAAO;CACT;CAEA,MAAc,iBACZ,cACA,kBAC+B;EAC/B,IAAI,OAAiB,CAAC;EAQtB,IAAI,MACF,GAAG,aAAa,GAAG,iBAAiB,eAJpC,SAAS,KAAK,YAAY,KAAK,eAAe,KAAK,YAAY,IAC3D,MACA;EAGN,MAAM,iBAAiB,KAAK,KAAK;EACjC,MAAM,UAAU,MAAM,eACpB,KAAK,MACL,cACA,kBACA,GACF;EACA,IAAI,CAAC,SAAS;GACZ,OAAO,MAAM,8CAA8C;GAC3D;EACF;EACA,IAAI,OAAO;EAQX,MAAM,QAAQ;GANZ;GACA;GACA;GACA;GACA;EAE+B,CAAC,CAAC,SAAS,YAAY,IACpD,MACA,aAAa,IAAI,gBAAgB;EACrC,OAAO,MAAM;GAAE;GAAc;GAAkB;EAAM,GAAG,gBAAgB;EACxE,MAAM,mBAAmB,+BAA+B,kBAAkB;EAC1E,IAAI,uBAAuB;EAC3B,GAAG;GACD,IAAI;GACJ,IAAI;IACF,MAAM,MAAM,KAAK,KAAK,QACpB,KACA;KAAE;KAAS,QAAQ;IAAK,GACxB,gBACF;GACF,SAAS,KAAK;IACZ,IACE,CAAC,wBACD,eAAeC,gBACf,qBAAqB,GAAG,GACxB;KAEA,MAAM,GAAG,aAAa,GAAG,iBAAiB;KAC1C,MAAM,iBAAiB,KAAK,KAAK;KACjC,uBAAuB;KACvB;IACF;IACA,MAAM;GACR;GACA,OAAO,KAAK,OAAO,IAAI,KAAK,IAAI;GAChC,MAAM,aAAa,gBAAgB,IAAI,QAAQ,IAAI;GACnD,IAAI,oBAAoB,GAAG,GAAG;IAE5B,IAAI,YAAY,MAAM,MAAM;KAE1B,MAAM,SAAS,SAAS,GAAG;;KAE3B,IAAI,CAAC,QAAQ;MACX,MAAM;MACN;KACF;KACA,OAAO,aAAa,OAAO,MAAM;KACjC,OAAO,aAAa,IAAI,QAAQ,WAAW,KAAK,IAAI;KACpD,MAAM,OAAO;IACf,OACE,MAAM;GAEV,OAAO,IAAI,YAAY,MAAM,KAAK;IAEhC,MAAM,UAAU,qBACd,KACA,WAAW,KAAK,KAChB,gBACF;IACA,IAAI,CAAC,SAEH,OAAO,KAAK,KACV;KAAE;KAAc,SAAS,WAAW,KAAK;IAAI,GAC7C,uEACF;IAEF,MAAM;GACR,OACE,MAAM;GAER,QAAQ;EACV,SAAS,OAAO,OAAO;EACvB,OAAO;CACT;CAEA,MAAc,SACZ,cACA,kBAC+B;EAC/B,IAAI;GACF,MAAM,SAAS,iBAAiB;GAChC,IAAI;GACJ,IAAI,QACF,IAAI;IAEF,OAAO,MAAM,KAAK,oBAAoB,cAAc,gBAAgB;GACtE,SAAS,KAAK;IAEZ,IAAI,eAAe,GAAG,GAAG;KACvB,OAAO,MACL;MAAE;MAAc;KAAiB,GACjC,yDACF;KACA,OAAO,MAAM,KAAK,iBAAiB,cAAc,gBAAgB;IACnE,OACE,MAAM;GAEV;QAEA,OAAO,MAAM,KAAK,iBAAiB,cAAc,gBAAgB;GAEnE,OAAO;EACT,SAAS,iCAAiC;GACxC,MAAM,MAAM,gBAAgB,oBAAoB,KAAK,MAAM;GAE3D,MAAM,WAAW,WAAW,GAAG,KAAK,IAAI,YAAA;GAExC,IAAI,YAAY,CAAC,iBAAiB,SAAS,GAAG,GAAG;IAC/C,OAAO,MACL,qBAAqB,aAAa,GAAG,iBAAiB,uBACxD;IACA,OAAO,KAAK,QAAQ,cAAc,WAAW,kBAAkB;GACjE;GAGA,IACE,YACA,oBAAoB,IAAI,QAAQ,KAChC,iBAAiB,MAAM,GAAG,CAAC,CAAC,WAAW,GACvC;IACA,OAAO,MACL,wCAAwC,aAAa,GAAG,iBAAiB,gEAC3E;IAEA,MAAM,wBAAwB,iBAAiB,MAAM,GAAG;IACxD,MAAM,kBAAkB,sBAAsB;IAC9C,MAAM,cAAc,sBAAsB;IAE1C,OAAO,KAAK,QACV,cACA,GAAG,gBAAgB,WAAW,aAChC;GACF;GACA,IAAI,cAAc,GAAG,KAAK,aAAa,YAAY,GAAG;IACpD,OAAO,KACL;KAAE;KAAc;KAAkB;IAAI,GACtC,4CACF;IACA,MAAM,IAAI,kBAAkB,GAAG;GACjC;GACA,IAAI,cAAc,GAAG,GAAG;IACtB,OAAO,KACL;KAAE;KAAc;KAAkB;IAAI,GACtC,yCACF;IACA,MAAM,IAAI,kBAAkB,GAAG;GACjC;GAEA,IAAI,CADgB,cAAc,WACrB,CAAC,CAAC,SAAS,IAAI,IAAI,GAAG;IACjC,OAAO,KACL;KAAE;KAAc;KAAkB;IAAI,GACtC,oCACF;IACA,MAAM,IAAI,kBAAkB,GAAG;GACjC;GACA,IAAI,aAAa,YAAY,GAC3B,OAAO,KAAK,EAAE,IAAI,GAAG,2BAA2B;GAElD,MAAM;EACR;CACF;CAEA,QACE,cACA,kBAC+B;EAC/B,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,gBAAgB;GACjD,QAAQ,iBAAiB;EAC3B,SACM,KAAK,SAAS,cAAc,gBAAgB,CACpD;CACF;;;;;;;;;;CAWA,MAAc,WACZ,EAAE,aAAa,YAAY,aAAa,iBACxC,UACwB;EACxB,IAAI;EACJ,IAAI;EACJ,IAAI,eAAe,YAAY;GAE7B,eAAe;GACf,mBAAmB;EACrB,OAEE,CAAC,CAAE,cAAc,oBAAqB,sBACpC,aACA,WACF;EAEF,OAAO,MAEL,aAAa,aAAa,IAAI,iBAAiB,IAAI,SAAS,EAC9D;EACA,MAAM,SAAS,iBAAiB,QAAQ,IAAI,WAAW;EACvD,IAAI,SAAwB;EAC5B,IAAI;GACF,IAAI,eAA0C;GAC9C,IAAI,iBAAiB,eAAe,aAAa,GAC/C,eAAe,MAAM,KAAK,qBACxB,cACA,kBACA,aACF;GAGF,IAAI,mBAAwC;GAC5C,IAAI,CAAC,cAAc;IAEjB,IAAI,iBAAA,2BAA6B;KAE/B,MAAM,gBAAe,MADD,eAAe,KAAK,gBAAgB,EAAA,CAC7B,gBAAgB,MAAM;KACjD,IAAI,cACF,OAAO;IAEX;IAEA,mBAAmB,MAAM,KAAK,oBAC5B,cACA,kBACA,QACA,MACF;IAEA,IACE,oBACA,OAAO,yBAAyB,iBAAiB,OAAO,GAExD,SACG,iBAAiB,QAAQ,4BAC1B;GAEN;GAEA,MAAM,qBACJ,oBACA,CAAC,OAAO,yBAAyB,iBAAiB,OAAO;GAC3D,IAAI,iBAAiB,YAAY,KAAK,oBAAoB;IAExD,IAAI,iBAAiB,YAAY,KAAK,iBAAA,2BAA6B;KAEjE,MAAM,gBAAe,MADD,eAAe,KAAK,gBAAgB,EAAA,CAC7B,oBAAoB,QAAQ,YAAY;KACnE,IAAI,cACF,OAAO;IAEX;IAEA,OAAO,MACL;KAAE;KAAc;IAAiB,GACjC,8FACF;IACA,mBAAmB,MAAM,KAAK,oBAC5B,cACA,kBACA,MACF;IAEA,IAAI,gBAAgB,kBAAkB;KACpC,MAAM,SAAS,aAAa,UAAU,iBAAiB,IAAI;;KAE3D,IAAI,OAAO,SAAS;MAClB,MAAM,eAAe,OAAO;MAC5B,IACE,aAAa,cACX,+DACF,aAAa,cACX,2CAEG;YAAA,MAAM,YAAY,aAAa,WAClC,IAAI,SAAS,UAAU,iBAAiB,cAAc;QACpD,SAAS,SAAS;QAClB;OACF;aAOG,IACL,OAAO,yBAAyB,iBAAiB,OAAO,GAIxD,SAAS,iBAAiB,QACxB;KAGN,OACE,OAAO,MACL;MACE;MACA;MACA;MACA,MAAM,iBAAiB;MACvB,SAAS,iBAAiB;MAC1B,KAAK,OAAO;KACd,GACA,mCACF;IAEJ;IAEA,IAAI,CAAC,QAAQ;KACX,OAAO,MACL;MAAE;MAAc;MAAkB;KAAO,GACzC,6DACF;KACA,SAAS,8BAA8B,gBAAiB;IAC1D;GACF;GAEA,IACE,CAAC,oBACD,CAAC,iBAAiB,SAAS,GAAG,KAC9B,CAAC,YAAY,SAAS,GAAG,GACzB;IACA,OAAO,MACL,uBAAuB,aAAa,GAAG,iBAAiB,uBAC1D;IACA,OAAO,KAAK,UACV;KACE;KACA,aAAa,WAAW;KACxB;IACF,GACA,QACF;GACF;GAEA,IAAI,kBAEF,OAAO,MAAM,qBAAqB,QAAS;EAE/C,SAAS,gCAAgC;GACvC,IAAI,eAAe,mBACjB,MAAM;GAER,OAAO,MACL;IACE;IACA;IACA;GACF,GACA,8CACF;EACF;EACA,OAAO;CACT;CAEA,UACE,QACA,UACwB;EACxB,MAAM,SAAS,YAAY;EAC3B,MAAM,EAAE,cAAc,qBAAqB,sBACzC,OAAO,aACP,OAAO,WACT;EACA,OAAO,UACL;GACE,WAAW;GACX,KAAK,cACH,cACA,kBACA,QACA,OAAO,aACT;GACA,UAAU;EACZ,GACA,OAAO,QAAQ;GACb,MAAM,SAAS,MAAM,KAAK,WAAW,QAAQ,QAAQ;GACrD,IAAI,YAAY,iBAAiB,MAAM;GACvC,OAAO;EACT,CACF;CACF;CAEA,MAAc,kBACZ,kBAC2B;EAC3B,IAAI,MAAM,0CAA0C,iBAAiB;EAErE,MAAM,QAAQ,MAAM,eAAe,KAAK,gBAAgB;EACxD,MAAM,WAAW,aAAa,IAAI,gBAAgB;EAClD,MAAM,mBAAmB,+BAA+B,kBAAkB;EAC1E,IAAI,OAAO,GACT,eAAe;EACjB,OAAO,gBAAgB,OAAO,UAAU;GACtC,MAAM,EAAE,KAAK,QAAQ,MAAM,KAAK,KAC7B,YAAY,KAAK,iBAAiB,CAAC,CACnC,OAAO;GAEV,IAAI,KAAK;IACP,OAAO,MAAM,EAAE,IAAI,GAAG,4CAA4C;IAClE,OAAO;GACT;GACA;GACA,MAAM,EAAE,SAAS,MAAM,UAAU;GAEjC,eAAe,MAAM,UAAU,SAAS,KAAK;GAE7C,IAAI,CAAC,MACH;GAIF,MAAM,UAAU,qBAAqB,KAAK,MAAM,gBAAgB;GAChE,IAAI,CAAC,SAAS;IACZ,OAAO,KAAK,KACV;KAAE;KAAkB,SAAS;IAAK,GAClC,kEACF;IACA;GACF;GAEA,MAAM;EACR;EAEA,MAAM,MAAM,KAAK;EAGjB,OADc,MAAM,SACT,CAAC,CAAC,KAAK,EAAE,MAAM,SAAS,sBAAsB;GACvD,MAAM,UAAmB,EAAE,QAAQ;GAEnC,MAAM,mBAAmB,YAAY,eAAe;GACpD,IAAI,kBACF,QAAQ,mBAAmB;GAO7B,OAAO;EACT,CAAC;CACH;CAEA,iBAAiB,kBAAqD;EACpE,OAAO,UACL;GACE,WAAW;GACX,KAAK;EACP,SACM,KAAK,kBAAkB,gBAAgB,CAC/C;CACF;;;;;;;;;;;;CAaA,MAAc,aAAa,EACzB,aACA,eACmD;EACnD,MAAM,EAAE,cAAc,qBAAqB,sBACzC,aACA,WACF;EAOA,MAAM,gBACJ,OAAO,aACL,KAAK,QAAQ,cAAc,gBAAgB,GAC3C,YACF,CAAC,CAAC,WAAW,SAAS,KAAK,KAAK,aAAa,EAAE,QAAQ,EAAE,CAAC;EAE5D,MAAM,yBACJ,OAAO,aACL,KAAK,iBAAiB,gBAAgB,GACtC,iBACF,CAAC,CAAC,MAAM,OAAO;EAQjB,MAAM,EAAE,KAAK,UAAU,QAAQ,OAL7B,iBAAA,6BACA,CAAC,OAAO,CAAC,CAAC,qCACN,iBAAiB,IACjB,QAAQ,EAAA,CAEkC,OAAO;EACvD,IAAI,eAAe,OACjB,MAAM;OACD,IAAI,KACT,OAAO;EAGT,MAAM,MAAqB;GACzB,aAAa;GACb;EACF;EACA,IAAI,qBAAqB,aAEvB,IAAI,aAAa;EAGnB,MAAM,OAAO,SAAS,KAAK,YAAY,QAAQ,OAAO;EACtD,MAAM,YAAY,KAAK,SAAS,QAAQ,IACpC,WACC,iBAAiB,IAAI,KAAK,KAAK,GAAG,EAAE;;EAGzC,IAAI,CAAC,WACH,OAAO;EAET,MAAM,SAAS,MAAM,KAAK,UACxB,cACA,kBACA,SACF;EACA,IAAI,QAAQ;GACV,IAAI,iBAAiB,OAAA,oCAAmB,GACtC,IAAI,SAAS,OAAO;GAEtB,KAAK,MAAM,SAAS,cAClB,IAAI,iBAAiB,OAAO,MAAM,GAAG;IACnC,IAAI,YAAY,OAAO;IACvB;GACF;GAEF,IAAI,iBAAiB,OAAA,+BAAqB,GACxC,IAAI,WAAW,OAAO;EAE1B;EACA,OAAO;CACT;CAEA,YAAY,QAA0D;EACpE,MAAM,EAAE,cAAc,qBAAqB,sBACzC,OAAO,aACP,OAAO,WACT;EACA,OAAO,UACL;GACE,WAAW;GACX,KAAK,cAAc,cAAc,gBAAgB;GACjD,QAAQ,iBAAiB;GACzB,UAAU;EACZ,SACM,KAAK,aAAa,MAAM,CAChC;CACF;AACF"}
@@ -1,7 +1,6 @@
1
1
  import { logger } from "../../../logger/index.js";
2
2
  import { parseUrl } from "../../../util/url.js";
3
- import { RequestError } from "../../../util/http/got.js";
4
- import "../../../util/http/index.js";
3
+ import { isNotFound } from "../../../util/http/status.js";
5
4
  import { GitHostTagsDigestDatasource } from "../git-host-tags.js";
6
5
  import { GiteaHttp } from "../../../util/http/gitea.js";
7
6
  import { Commits, Tag } from "./schema.js";
@@ -63,7 +62,7 @@ var GiteaDatasource = class GiteaDatasource extends GitHostTagsDigestDatasource
63
62
  try {
64
63
  return await super.fetchDigest(config, newValue);
65
64
  } catch (err) {
66
- if (err instanceof RequestError && err.response?.statusCode === 404) {
65
+ if (isNotFound(err)) {
67
66
  logger.debug({
68
67
  giteaRepo: config.packageName,
69
68
  err,
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","names":["HttpError"],"sources":["../../../../lib/modules/datasource/gitea-tags/base.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport type { PackageCacheNamespace } from '../../../util/cache/package/types.ts';\nimport { GiteaHttp } from '../../../util/http/gitea.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { GitHostTagsDigestDatasource } from '../git-host-tags.ts';\nimport type { DigestConfig } from '../types.ts';\nimport { Commits, Tag } from './schema.ts';\nimport { getApiUrl, getSourceUrl } from './util.ts';\n\n/**\n * Shared implementation of the datasources which speak the Gitea API.\n *\n * Forgejo is a fork of Gitea and serves the same API, so the Forgejo\n * datasources extend the Gitea ones and only differ in their id, their default\n * registry URL and their cache namespace. The digest lookup is the same for\n * tags and releases, so it lives here and a subclass only fetches and maps the\n * releases of its own endpoint.\n */\nexport abstract class GiteaDatasource extends GitHostTagsDigestDatasource<GiteaHttp> {\n static readonly defaultRegistryUrls = ['https://gitea.com'];\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return GiteaDatasource.defaultRegistryUrls;\n }\n\n protected abstract override readonly cacheNamespace: PackageCacheNamespace;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote: string;\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined by using the `packageName` and `registryUrl`.';\n\n /**\n * @param releaseTimestampField the field of the endpoint `getReleases()` reads\n * which the release timestamp comes from, rendered into the generated\n * documentation.\n * @param http lets a subclass for another Gitea-compatible host supply a\n * client scoped to its own host type.\n */\n protected constructor(\n id: string,\n releaseTimestampField: string,\n http: GiteaHttp = new GiteaHttp(id),\n ) {\n super(id, http);\n this.releaseTimestampNote = `The release timestamp is determined from the \\`${releaseTimestampField}\\` field in the results.`;\n }\n\n static getSourceUrl(packageName: string, registryUrl?: string): string {\n return getSourceUrl(\n packageName,\n registryUrl ?? this.defaultRegistryUrls[0],\n );\n }\n\n protected getSourceUrl(packageName: string, registryUrl?: string): string {\n return getSourceUrl(packageName, this.getRegistryUrl(registryUrl));\n }\n\n /**\n * Self-hosted instances can serve private repositories.\n */\n protected override isPublic(registryUrl: string): boolean {\n return (\n parseUrl(registryUrl)?.hostname ===\n parseUrl(this.getDefaultRegistryUrls('')[0])?.hostname\n );\n }\n\n // fetchTagCommit fetches the commit hash for the specified tag\n protected async fetchTagCommit(\n registryUrl: string | undefined,\n repo: string,\n tag: string,\n ): Promise<string | null> {\n const url = `${getApiUrl(this.getRegistryUrl(registryUrl))}repos/${repo}/tags/${tag}`;\n\n const { body } = await this.http.getJson(url, Tag);\n\n return body.commit.sha;\n }\n\n // fetchLatestCommit fetches the latest commit of the main branch\n protected async fetchLatestCommit(\n registryUrl: string | undefined,\n repo: string,\n ): Promise<string | null> {\n const url = `${getApiUrl(\n this.getRegistryUrl(registryUrl),\n )}repos/${repo}/commits?stat=false&verification=false&files=false&page=1&limit=1`;\n const { body } = await this.http.getJson(url, Commits);\n\n if (body.length === 0) {\n return null;\n }\n\n return body[0].sha;\n }\n\n protected override async fetchDigest(\n config: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n try {\n return await super.fetchDigest(config, newValue);\n } catch (err) {\n if (err instanceof HttpError && err.response?.statusCode === 404) {\n logger.debug(\n {\n giteaRepo: config.packageName,\n err,\n registryUrl: config.registryUrl,\n },\n 'Gitea repo or ref not found when getting commit',\n );\n return null;\n }\n this.handleGenericErrors(err);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,IAAsB,kBAAtB,MAAsB,wBAAwB,4BAAuC;CACnF,OAAgB,sBAAsB,CAAC,mBAAmB;CAE1D,uBAAgC,cAAgC;EAC9D,OAAO,gBAAgB;CACzB;CAIA,0BAA4C;CAC5C;CACA,mBAAqC;CACrC,gBACE;;;;;;;;CASF,YACE,IACA,uBACA,OAAkB,IAAI,UAAU,EAAE,GAClC;EACA,MAAM,IAAI,IAAI;EACd,KAAK,uBAAuB,kDAAkD,sBAAsB;CACtG;CAEA,OAAO,aAAa,aAAqB,aAA8B;EACrE,OAAO,aACL,aACA,eAAe,KAAK,oBAAoB,EAC1C;CACF;CAEA,aAAuB,aAAqB,aAA8B;EACxE,OAAO,aAAa,aAAa,KAAK,eAAe,WAAW,CAAC;CACnE;;;;CAKA,SAA4B,aAA8B;EACxD,OACE,SAAS,WAAW,CAAC,EAAE,aACvB,SAAS,KAAK,uBAAuB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE;CAElD;CAGA,MAAgB,eACd,aACA,MACA,KACwB;EACxB,MAAM,MAAM,GAAG,UAAU,KAAK,eAAe,WAAW,CAAC,EAAE,QAAQ,KAAK,QAAQ;EAEhF,MAAM,EAAE,SAAS,MAAM,KAAK,KAAK,QAAQ,KAAK,GAAG;EAEjD,OAAO,KAAK,OAAO;CACrB;CAGA,MAAgB,kBACd,aACA,MACwB;EACxB,MAAM,MAAM,GAAG,UACb,KAAK,eAAe,WAAW,CACjC,EAAE,QAAQ,KAAK;EACf,MAAM,EAAE,SAAS,MAAM,KAAK,KAAK,QAAQ,KAAK,OAAO;EAErD,IAAI,KAAK,WAAW,GAClB,OAAO;EAGT,OAAO,KAAK,EAAE,CAAC;CACjB;CAEA,MAAyB,YACvB,QACA,UACwB;EACxB,IAAI;GACF,OAAO,MAAM,MAAM,YAAY,QAAQ,QAAQ;EACjD,SAAS,KAAK;GACZ,IAAI,eAAeA,gBAAa,IAAI,UAAU,eAAe,KAAK;IAChE,OAAO,MACL;KACE,WAAW,OAAO;KAClB;KACA,aAAa,OAAO;IACtB,GACA,iDACF;IACA,OAAO;GACT;GACA,KAAK,oBAAoB,GAAG;EAC9B;CACF;AACF"}
1
+ {"version":3,"file":"base.js","names":[],"sources":["../../../../lib/modules/datasource/gitea-tags/base.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport type { PackageCacheNamespace } from '../../../util/cache/package/types.ts';\nimport { GiteaHttp } from '../../../util/http/gitea.ts';\nimport { isNotFound } from '../../../util/http/status.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { GitHostTagsDigestDatasource } from '../git-host-tags.ts';\nimport type { DigestConfig } from '../types.ts';\nimport { Commits, Tag } from './schema.ts';\nimport { getApiUrl, getSourceUrl } from './util.ts';\n\n/**\n * Shared implementation of the datasources which speak the Gitea API.\n *\n * Forgejo is a fork of Gitea and serves the same API, so the Forgejo\n * datasources extend the Gitea ones and only differ in their id, their default\n * registry URL and their cache namespace. The digest lookup is the same for\n * tags and releases, so it lives here and a subclass only fetches and maps the\n * releases of its own endpoint.\n */\nexport abstract class GiteaDatasource extends GitHostTagsDigestDatasource<GiteaHttp> {\n static readonly defaultRegistryUrls = ['https://gitea.com'];\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return GiteaDatasource.defaultRegistryUrls;\n }\n\n protected abstract override readonly cacheNamespace: PackageCacheNamespace;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote: string;\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined by using the `packageName` and `registryUrl`.';\n\n /**\n * @param releaseTimestampField the field of the endpoint `getReleases()` reads\n * which the release timestamp comes from, rendered into the generated\n * documentation.\n * @param http lets a subclass for another Gitea-compatible host supply a\n * client scoped to its own host type.\n */\n protected constructor(\n id: string,\n releaseTimestampField: string,\n http: GiteaHttp = new GiteaHttp(id),\n ) {\n super(id, http);\n this.releaseTimestampNote = `The release timestamp is determined from the \\`${releaseTimestampField}\\` field in the results.`;\n }\n\n static getSourceUrl(packageName: string, registryUrl?: string): string {\n return getSourceUrl(\n packageName,\n registryUrl ?? this.defaultRegistryUrls[0],\n );\n }\n\n protected getSourceUrl(packageName: string, registryUrl?: string): string {\n return getSourceUrl(packageName, this.getRegistryUrl(registryUrl));\n }\n\n /**\n * Self-hosted instances can serve private repositories.\n */\n protected override isPublic(registryUrl: string): boolean {\n return (\n parseUrl(registryUrl)?.hostname ===\n parseUrl(this.getDefaultRegistryUrls('')[0])?.hostname\n );\n }\n\n // fetchTagCommit fetches the commit hash for the specified tag\n protected async fetchTagCommit(\n registryUrl: string | undefined,\n repo: string,\n tag: string,\n ): Promise<string | null> {\n const url = `${getApiUrl(this.getRegistryUrl(registryUrl))}repos/${repo}/tags/${tag}`;\n\n const { body } = await this.http.getJson(url, Tag);\n\n return body.commit.sha;\n }\n\n // fetchLatestCommit fetches the latest commit of the main branch\n protected async fetchLatestCommit(\n registryUrl: string | undefined,\n repo: string,\n ): Promise<string | null> {\n const url = `${getApiUrl(\n this.getRegistryUrl(registryUrl),\n )}repos/${repo}/commits?stat=false&verification=false&files=false&page=1&limit=1`;\n const { body } = await this.http.getJson(url, Commits);\n\n if (body.length === 0) {\n return null;\n }\n\n return body[0].sha;\n }\n\n protected override async fetchDigest(\n config: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n try {\n return await super.fetchDigest(config, newValue);\n } catch (err) {\n if (isNotFound(err)) {\n logger.debug(\n {\n giteaRepo: config.packageName,\n err,\n registryUrl: config.registryUrl,\n },\n 'Gitea repo or ref not found when getting commit',\n );\n return null;\n }\n this.handleGenericErrors(err);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAmBA,IAAsB,kBAAtB,MAAsB,wBAAwB,4BAAuC;CACnF,OAAgB,sBAAsB,CAAC,mBAAmB;CAE1D,uBAAgC,cAAgC;EAC9D,OAAO,gBAAgB;CACzB;CAIA,0BAA4C;CAC5C;CACA,mBAAqC;CACrC,gBACE;;;;;;;;CASF,YACE,IACA,uBACA,OAAkB,IAAI,UAAU,EAAE,GAClC;EACA,MAAM,IAAI,IAAI;EACd,KAAK,uBAAuB,kDAAkD,sBAAsB;CACtG;CAEA,OAAO,aAAa,aAAqB,aAA8B;EACrE,OAAO,aACL,aACA,eAAe,KAAK,oBAAoB,EAC1C;CACF;CAEA,aAAuB,aAAqB,aAA8B;EACxE,OAAO,aAAa,aAAa,KAAK,eAAe,WAAW,CAAC;CACnE;;;;CAKA,SAA4B,aAA8B;EACxD,OACE,SAAS,WAAW,CAAC,EAAE,aACvB,SAAS,KAAK,uBAAuB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE;CAElD;CAGA,MAAgB,eACd,aACA,MACA,KACwB;EACxB,MAAM,MAAM,GAAG,UAAU,KAAK,eAAe,WAAW,CAAC,EAAE,QAAQ,KAAK,QAAQ;EAEhF,MAAM,EAAE,SAAS,MAAM,KAAK,KAAK,QAAQ,KAAK,GAAG;EAEjD,OAAO,KAAK,OAAO;CACrB;CAGA,MAAgB,kBACd,aACA,MACwB;EACxB,MAAM,MAAM,GAAG,UACb,KAAK,eAAe,WAAW,CACjC,EAAE,QAAQ,KAAK;EACf,MAAM,EAAE,SAAS,MAAM,KAAK,KAAK,QAAQ,KAAK,OAAO;EAErD,IAAI,KAAK,WAAW,GAClB,OAAO;EAGT,OAAO,KAAK,EAAE,CAAC;CACjB;CAEA,MAAyB,YACvB,QACA,UACwB;EACxB,IAAI;GACF,OAAO,MAAM,MAAM,YAAY,QAAQ,QAAQ;EACjD,SAAS,KAAK;GACZ,IAAI,WAAW,GAAG,GAAG;IACnB,OAAO,MACL;KACE,WAAW,OAAO;KAClB;KACA,aAAa,OAAO;IACtB,GACA,iDACF;IACA,OAAO;GACT;GACA,KAAK,oBAAoB,GAAG;EAC9B;CACF;AACF"}
@@ -58,7 +58,8 @@ var GithubTagsDatasource = class GithubTagsDatasource extends GitHostTagsDigestD
58
58
  const isReleaseStable = releasesMap.get(release.version)?.isStable;
59
59
  if (isBoolean(isReleaseStable)) release.isStable = isReleaseStable;
60
60
  const releaseTimestamp = releasesMap.get(release.version)?.releaseTimestamp;
61
- if (releaseTimestamp && (isNullOrUndefined(release.releaseTimestamp) || releaseTimestamp > release.releaseTimestamp)) release.releaseTimestamp = releaseTimestamp;
61
+ if (!releaseTimestamp) continue;
62
+ if (isNullOrUndefined(release.releaseTimestamp) || releaseTimestamp > release.releaseTimestamp) release.releaseTimestamp = releaseTimestamp;
62
63
  }
63
64
  } catch (err) /* istanbul ignore next */ {
64
65
  logger.debug({ err }, `Error fetching additional info for GitHub tags`);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../lib/modules/datasource/github-tags/index.ts"],"sourcesContent":["import { isBoolean, isNullOrUndefined } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport {\n queryReleases,\n queryTags,\n} from '../../../util/github/graphql/index.ts';\nimport type { GithubReleaseItem } from '../../../util/github/graphql/types.ts';\nimport { findCommitOfTag } from '../../../util/github/tags.ts';\nimport { getApiBaseUrl, getSourceUrl } from '../../../util/github/url.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { GithubHttp } from '../../../util/http/github.ts';\nimport { GitHostTagsDigestDatasource } from '../git-host-tags.ts';\nimport type { GetReleasesConfig, GitHostTag } from '../types.ts';\n\nexport class GithubTagsDatasource extends GitHostTagsDigestDatasource<GithubHttp> {\n static readonly id = 'github-tags';\n\n protected getSourceUrl(packageName: string, registryUrl?: string): string {\n return getSourceUrl(packageName, registryUrl);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://github.com'];\n }\n\n override readonly registryStrategy = 'hunt';\n\n // the GraphQL fetcher caches the tags and releases itself, and the latest\n // commit lookup uses the HTTP memory cache\n protected override cachedLookup<T>(\n _registryUrl: string | undefined,\n _key: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n\n override readonly releaseTimestampSupport = true;\n // Note: not sure\n override readonly releaseTimestampNote =\n 'The get release timestamp is determined from the `releaseTimestamp` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined by using the `packageName` and `registryUrl`.';\n\n constructor() {\n super(GithubTagsDatasource.id, new GithubHttp(GithubTagsDatasource.id));\n }\n\n protected fetchTagCommit(\n registryUrl: string | undefined,\n repo: string,\n tag: string,\n ): Promise<string | null> {\n return findCommitOfTag(registryUrl, repo, tag, this.http);\n }\n\n protected async fetchLatestCommit(\n registryUrl: string | undefined,\n githubRepo: string,\n ): Promise<string | null> {\n const apiBaseUrl = getApiBaseUrl(registryUrl);\n let digest: string | null = null;\n try {\n const url = `${apiBaseUrl}repos/${githubRepo}/commits?per_page=1`;\n const res = await this.http.getJsonUnchecked<{ sha: string }[]>(url, {\n cacheProvider: memCacheProvider,\n });\n digest = res.body[0].sha;\n } catch (err) {\n logger.debug(\n { githubRepo, err, registryUrl },\n 'Error getting latest commit from GitHub repo',\n );\n }\n return digest;\n }\n\n protected async fetchTags(config: GetReleasesConfig): Promise<GitHostTag[]> {\n const tagsResult = await queryTags(config, this.http);\n const releases: GitHostTag[] = tagsResult.map(\n ({ version, releaseTimestamp, hash }) => ({\n newDigest: hash,\n version,\n releaseTimestamp,\n }),\n );\n\n try {\n // Fetch additional data from releases endpoint when possible\n const releasesResult = await queryReleases(config, this.http);\n const releasesMap = new Map<string, GithubReleaseItem>();\n for (const release of releasesResult) {\n releasesMap.set(release.version, release);\n }\n\n for (const release of releases) {\n const isReleaseStable = releasesMap.get(release.version)?.isStable;\n if (isBoolean(isReleaseStable)) {\n release.isStable = isReleaseStable;\n }\n\n const releaseTimestamp = releasesMap.get(\n release.version,\n )?.releaseTimestamp;\n if (\n releaseTimestamp &&\n (isNullOrUndefined(release.releaseTimestamp) ||\n releaseTimestamp > release.releaseTimestamp)\n ) {\n release.releaseTimestamp = releaseTimestamp;\n }\n }\n } catch (err) /* istanbul ignore next */ {\n logger.debug({ err }, `Error fetching additional info for GitHub tags`);\n }\n\n return releases;\n }\n}\n"],"mappings":";;;;;;;;;AAcA,IAAa,uBAAb,MAAa,6BAA6B,4BAAwC;CAChF,OAAgB,KAAK;CAErB,aAAuB,aAAqB,aAA8B;EACxE,OAAO,aAAa,aAAa,WAAW;CAC9C;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,oBAAoB;CAC9B;CAEA,mBAAqC;CAIrC,aACE,cACA,MACA,IACY;EACZ,OAAO,GAAG;CACZ;CAEA,0BAA4C;CAE5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,cAAc;EACZ,MAAM,qBAAqB,IAAI,IAAI,WAAW,qBAAqB,EAAE,CAAC;CACxE;CAEA,eACE,aACA,MACA,KACwB;EACxB,OAAO,gBAAgB,aAAa,MAAM,KAAK,KAAK,IAAI;CAC1D;CAEA,MAAgB,kBACd,aACA,YACwB;EACxB,MAAM,aAAa,cAAc,WAAW;EAC5C,IAAI,SAAwB;EAC5B,IAAI;GACF,MAAM,MAAM,GAAG,WAAW,QAAQ,WAAW;GAI7C,UAAS,MAHS,KAAK,KAAK,iBAAoC,KAAK,EACnE,eAAe,iBACjB,CAAC,EAAA,CACY,KAAK,EAAE,CAAC;EACvB,SAAS,KAAK;GACZ,OAAO,MACL;IAAE;IAAY;IAAK;GAAY,GAC/B,8CACF;EACF;EACA,OAAO;CACT;CAEA,MAAgB,UAAU,QAAkD;EAE1E,MAAM,YAAyB,MADN,UAAU,QAAQ,KAAK,IAAI,EAAA,CACV,KACvC,EAAE,SAAS,kBAAkB,YAAY;GACxC,WAAW;GACX;GACA;EACF,EACF;EAEA,IAAI;GAEF,MAAM,iBAAiB,MAAM,cAAc,QAAQ,KAAK,IAAI;GAC5D,MAAM,8BAAc,IAAI,IAA+B;GACvD,KAAK,MAAM,WAAW,gBACpB,YAAY,IAAI,QAAQ,SAAS,OAAO;GAG1C,KAAK,MAAM,WAAW,UAAU;IAC9B,MAAM,kBAAkB,YAAY,IAAI,QAAQ,OAAO,CAAC,EAAE;IAC1D,IAAI,UAAU,eAAe,GAC3B,QAAQ,WAAW;IAGrB,MAAM,mBAAmB,YAAY,IACnC,QAAQ,OACV,CAAC,EAAE;IACH,IACE,qBACC,kBAAkB,QAAQ,gBAAgB,KACzC,mBAAmB,QAAQ,mBAE7B,QAAQ,mBAAmB;GAE/B;EACF,SAAS,gCAAgC;GACvC,OAAO,MAAM,EAAE,IAAI,GAAG,gDAAgD;EACxE;EAEA,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../lib/modules/datasource/github-tags/index.ts"],"sourcesContent":["import { isBoolean, isNullOrUndefined } from '@sindresorhus/is';\nimport { logger } from '../../../logger/index.ts';\nimport {\n queryReleases,\n queryTags,\n} from '../../../util/github/graphql/index.ts';\nimport type { GithubReleaseItem } from '../../../util/github/graphql/types.ts';\nimport { findCommitOfTag } from '../../../util/github/tags.ts';\nimport { getApiBaseUrl, getSourceUrl } from '../../../util/github/url.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport { GithubHttp } from '../../../util/http/github.ts';\nimport { GitHostTagsDigestDatasource } from '../git-host-tags.ts';\nimport type { GetReleasesConfig, GitHostTag } from '../types.ts';\n\nexport class GithubTagsDatasource extends GitHostTagsDigestDatasource<GithubHttp> {\n static readonly id = 'github-tags';\n\n protected getSourceUrl(packageName: string, registryUrl?: string): string {\n return getSourceUrl(packageName, registryUrl);\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return ['https://github.com'];\n }\n\n override readonly registryStrategy = 'hunt';\n\n // the GraphQL fetcher caches the tags and releases itself, and the latest\n // commit lookup uses the HTTP memory cache\n protected override cachedLookup<T>(\n _registryUrl: string | undefined,\n _key: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n\n override readonly releaseTimestampSupport = true;\n // Note: not sure\n override readonly releaseTimestampNote =\n 'The get release timestamp is determined from the `releaseTimestamp` field in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined by using the `packageName` and `registryUrl`.';\n\n constructor() {\n super(GithubTagsDatasource.id, new GithubHttp(GithubTagsDatasource.id));\n }\n\n protected fetchTagCommit(\n registryUrl: string | undefined,\n repo: string,\n tag: string,\n ): Promise<string | null> {\n return findCommitOfTag(registryUrl, repo, tag, this.http);\n }\n\n protected async fetchLatestCommit(\n registryUrl: string | undefined,\n githubRepo: string,\n ): Promise<string | null> {\n const apiBaseUrl = getApiBaseUrl(registryUrl);\n let digest: string | null = null;\n try {\n const url = `${apiBaseUrl}repos/${githubRepo}/commits?per_page=1`;\n const res = await this.http.getJsonUnchecked<{ sha: string }[]>(url, {\n cacheProvider: memCacheProvider,\n });\n digest = res.body[0].sha;\n } catch (err) {\n logger.debug(\n { githubRepo, err, registryUrl },\n 'Error getting latest commit from GitHub repo',\n );\n }\n return digest;\n }\n\n protected async fetchTags(config: GetReleasesConfig): Promise<GitHostTag[]> {\n const tagsResult = await queryTags(config, this.http);\n const releases: GitHostTag[] = tagsResult.map(\n ({ version, releaseTimestamp, hash }) => ({\n newDigest: hash,\n version,\n releaseTimestamp,\n }),\n );\n\n try {\n // Fetch additional data from releases endpoint when possible\n const releasesResult = await queryReleases(config, this.http);\n const releasesMap = new Map<string, GithubReleaseItem>();\n for (const release of releasesResult) {\n releasesMap.set(release.version, release);\n }\n\n for (const release of releases) {\n const isReleaseStable = releasesMap.get(release.version)?.isStable;\n if (isBoolean(isReleaseStable)) {\n release.isStable = isReleaseStable;\n }\n\n const releaseTimestamp = releasesMap.get(\n release.version,\n )?.releaseTimestamp;\n if (!releaseTimestamp) {\n continue;\n }\n\n if (\n isNullOrUndefined(release.releaseTimestamp) ||\n releaseTimestamp > release.releaseTimestamp\n ) {\n release.releaseTimestamp = releaseTimestamp;\n }\n }\n } catch (err) /* istanbul ignore next */ {\n logger.debug({ err }, `Error fetching additional info for GitHub tags`);\n }\n\n return releases;\n }\n}\n"],"mappings":";;;;;;;;;AAcA,IAAa,uBAAb,MAAa,6BAA6B,4BAAwC;CAChF,OAAgB,KAAK;CAErB,aAAuB,aAAqB,aAA8B;EACxE,OAAO,aAAa,aAAa,WAAW;CAC9C;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,oBAAoB;CAC9B;CAEA,mBAAqC;CAIrC,aACE,cACA,MACA,IACY;EACZ,OAAO,GAAG;CACZ;CAEA,0BAA4C;CAE5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,cAAc;EACZ,MAAM,qBAAqB,IAAI,IAAI,WAAW,qBAAqB,EAAE,CAAC;CACxE;CAEA,eACE,aACA,MACA,KACwB;EACxB,OAAO,gBAAgB,aAAa,MAAM,KAAK,KAAK,IAAI;CAC1D;CAEA,MAAgB,kBACd,aACA,YACwB;EACxB,MAAM,aAAa,cAAc,WAAW;EAC5C,IAAI,SAAwB;EAC5B,IAAI;GACF,MAAM,MAAM,GAAG,WAAW,QAAQ,WAAW;GAI7C,UAAS,MAHS,KAAK,KAAK,iBAAoC,KAAK,EACnE,eAAe,iBACjB,CAAC,EAAA,CACY,KAAK,EAAE,CAAC;EACvB,SAAS,KAAK;GACZ,OAAO,MACL;IAAE;IAAY;IAAK;GAAY,GAC/B,8CACF;EACF;EACA,OAAO;CACT;CAEA,MAAgB,UAAU,QAAkD;EAE1E,MAAM,YAAyB,MADN,UAAU,QAAQ,KAAK,IAAI,EAAA,CACV,KACvC,EAAE,SAAS,kBAAkB,YAAY;GACxC,WAAW;GACX;GACA;EACF,EACF;EAEA,IAAI;GAEF,MAAM,iBAAiB,MAAM,cAAc,QAAQ,KAAK,IAAI;GAC5D,MAAM,8BAAc,IAAI,IAA+B;GACvD,KAAK,MAAM,WAAW,gBACpB,YAAY,IAAI,QAAQ,SAAS,OAAO;GAG1C,KAAK,MAAM,WAAW,UAAU;IAC9B,MAAM,kBAAkB,YAAY,IAAI,QAAQ,OAAO,CAAC,EAAE;IAC1D,IAAI,UAAU,eAAe,GAC3B,QAAQ,WAAW;IAGrB,MAAM,mBAAmB,YAAY,IACnC,QAAQ,OACV,CAAC,EAAE;IACH,IAAI,CAAC,kBACH;IAGF,IACE,kBAAkB,QAAQ,gBAAgB,KAC1C,mBAAmB,QAAQ,kBAE3B,QAAQ,mBAAmB;GAE/B;EACF,SAAS,gCAAgC;GACvC,OAAO,MAAM,EAAE,IAAI,GAAG,gDAAgD;EACxE;EAEA,OAAO;CACT;AACF"}
@@ -1,7 +1,6 @@
1
1
  import { logger } from "../../../logger/index.js";
2
2
  import { joinUrlParts } from "../../../util/url.js";
3
- import { RequestError } from "../../../util/http/got.js";
4
- import "../../../util/http/index.js";
3
+ import { isNotFound } from "../../../util/http/status.js";
5
4
  import { asTimestamp } from "../../../util/timestamp.js";
6
5
  import { GitHostTagsDigestDatasource } from "../git-host-tags.js";
7
6
  import { defaultRegistryUrl, getApiBaseUrl, getDepHost, getSourceUrl } from "../../../util/gitlab/url.js";
@@ -47,7 +46,7 @@ var GitlabTagsDatasource = class GitlabTagsDatasource extends GitHostTagsDigestD
47
46
  try {
48
47
  return await super.fetchDigest(config, newValue);
49
48
  } catch (err) {
50
- if (err instanceof RequestError && err.response?.statusCode === 404) {
49
+ if (isNotFound(err)) {
51
50
  logger.debug({
52
51
  gitlabRepo: config.packageName,
53
52
  err,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["HttpError"],"sources":["../../../../lib/modules/datasource/gitlab-tags/index.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport {\n defaultRegistryUrl,\n getApiBaseUrl,\n getDepHost,\n getSourceUrl,\n} from '../../../util/gitlab/url.ts';\nimport { GitlabHttp } from '../../../util/http/gitlab.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { joinUrlParts } from '../../../util/url.ts';\nimport { GitHostTagsDigestDatasource } from '../git-host-tags.ts';\nimport type { DigestConfig, GetReleasesConfig, GitHostTag } from '../types.ts';\nimport { GitlabCommit, GitlabCommits, GitlabTags } from './schema.ts';\n\nexport class GitlabTagsDatasource extends GitHostTagsDigestDatasource<GitlabHttp> {\n static readonly id = 'gitlab-tags';\n\n protected getSourceUrl(packageName: string, registryUrl?: string): string {\n return getSourceUrl(packageName, registryUrl);\n }\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'To get release timestamp we use the `created_at` field from the response.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined by using the `packageName` and `registryUrl`.';\n\n constructor() {\n super(GitlabTagsDatasource.id, new GitlabHttp(GitlabTagsDatasource.id));\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return [defaultRegistryUrl];\n }\n\n /** Strips the `/api/v4` suffix, so both spellings share a cache key. */\n protected override getRegistryUrl(registryUrl?: string): string {\n return getDepHost(registryUrl);\n }\n\n protected async fetchTags({\n registryUrl,\n packageName: repo,\n }: GetReleasesConfig): Promise<GitHostTag[]> {\n const apiBaseUrl = getApiBaseUrl(registryUrl);\n\n const urlEncodedRepo = encodeURIComponent(repo);\n\n // tag\n const url = joinUrlParts(\n apiBaseUrl,\n `projects`,\n urlEncodedRepo,\n `repository/tags?per_page=100`,\n );\n\n const gitlabTags = (\n await this.http.getJson(url, { paginate: true }, GitlabTags)\n ).body;\n\n return gitlabTags.map(({ name, commit }) => ({\n version: name,\n releaseTimestamp: asTimestamp(commit.created_at),\n }));\n }\n\n protected async fetchTagCommit(\n registryUrl: string | undefined,\n repo: string,\n tag: string,\n ): Promise<string | null> {\n const url = joinUrlParts(\n getApiBaseUrl(registryUrl),\n `projects`,\n encodeURIComponent(repo),\n `repository/commits/`,\n encodeURIComponent(tag),\n );\n const gitlabCommit = await this.http.getJson(url, GitlabCommit);\n return gitlabCommit.body.id;\n }\n\n protected async fetchLatestCommit(\n registryUrl: string | undefined,\n repo: string,\n ): Promise<string | null> {\n const url = joinUrlParts(\n getApiBaseUrl(registryUrl),\n `projects`,\n encodeURIComponent(repo),\n `repository/commits?per_page=1`,\n );\n const gitlabCommits = await this.http.getJson(url, GitlabCommits);\n return gitlabCommits.body[0]?.id ?? null;\n }\n\n protected override async fetchDigest(\n config: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n try {\n return await super.fetchDigest(config, newValue);\n } catch (err) {\n if (err instanceof HttpError && err.response?.statusCode === 404) {\n logger.debug(\n {\n gitlabRepo: config.packageName,\n err,\n registryUrl: config.registryUrl,\n },\n 'Gitlab repo or ref not found when getting commit',\n );\n return null;\n }\n this.handleGenericErrors(err);\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAeA,IAAa,uBAAb,MAAa,6BAA6B,4BAAwC;CAChF,OAAgB,KAAK;CAErB,aAAuB,aAAqB,aAA8B;EACxE,OAAO,aAAa,aAAa,WAAW;CAC9C;CAEA,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,cAAc;EACZ,MAAM,qBAAqB,IAAI,IAAI,WAAW,qBAAqB,EAAE,CAAC;CACxE;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,kBAAkB;CAC5B;;CAGA,eAAkC,aAA8B;EAC9D,OAAO,WAAW,WAAW;CAC/B;CAEA,MAAgB,UAAU,EACxB,aACA,aAAa,QAC8B;EAC3C,MAAM,aAAa,cAAc,WAAW;EAK5C,MAAM,MAAM,aACV,YACA,YALqB,mBAAmB,IAM3B,GACb,8BACF;EAMA,QAHE,MAAM,KAAK,KAAK,QAAQ,KAAK,EAAE,UAAU,KAAK,GAAG,UAAU,EAAA,CAC3D,KAEgB,KAAK,EAAE,MAAM,cAAc;GAC3C,SAAS;GACT,kBAAkB,YAAY,OAAO,UAAU;EACjD,EAAE;CACJ;CAEA,MAAgB,eACd,aACA,MACA,KACwB;EACxB,MAAM,MAAM,aACV,cAAc,WAAW,GACzB,YACA,mBAAmB,IAAI,GACvB,uBACA,mBAAmB,GAAG,CACxB;EAEA,QAAO,MADoB,KAAK,KAAK,QAAQ,KAAK,YAAY,EAAA,CAC1C,KAAK;CAC3B;CAEA,MAAgB,kBACd,aACA,MACwB;EACxB,MAAM,MAAM,aACV,cAAc,WAAW,GACzB,YACA,mBAAmB,IAAI,GACvB,+BACF;EAEA,QAAO,MADqB,KAAK,KAAK,QAAQ,KAAK,aAAa,EAAA,CAC3C,KAAK,EAAE,EAAE,MAAM;CACtC;CAEA,MAAyB,YACvB,QACA,UACwB;EACxB,IAAI;GACF,OAAO,MAAM,MAAM,YAAY,QAAQ,QAAQ;EACjD,SAAS,KAAK;GACZ,IAAI,eAAeA,gBAAa,IAAI,UAAU,eAAe,KAAK;IAChE,OAAO,MACL;KACE,YAAY,OAAO;KACnB;KACA,aAAa,OAAO;IACtB,GACA,kDACF;IACA,OAAO;GACT;GACA,KAAK,oBAAoB,GAAG;EAC9B;CACF;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../lib/modules/datasource/gitlab-tags/index.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport {\n defaultRegistryUrl,\n getApiBaseUrl,\n getDepHost,\n getSourceUrl,\n} from '../../../util/gitlab/url.ts';\nimport { GitlabHttp } from '../../../util/http/gitlab.ts';\nimport { isNotFound } from '../../../util/http/status.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { joinUrlParts } from '../../../util/url.ts';\nimport { GitHostTagsDigestDatasource } from '../git-host-tags.ts';\nimport type { DigestConfig, GetReleasesConfig, GitHostTag } from '../types.ts';\nimport { GitlabCommit, GitlabCommits, GitlabTags } from './schema.ts';\n\nexport class GitlabTagsDatasource extends GitHostTagsDigestDatasource<GitlabHttp> {\n static readonly id = 'gitlab-tags';\n\n protected getSourceUrl(packageName: string, registryUrl?: string): string {\n return getSourceUrl(packageName, registryUrl);\n }\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'To get release timestamp we use the `created_at` field from the response.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined by using the `packageName` and `registryUrl`.';\n\n constructor() {\n super(GitlabTagsDatasource.id, new GitlabHttp(GitlabTagsDatasource.id));\n }\n\n override getDefaultRegistryUrls(_packageName: string): string[] {\n return [defaultRegistryUrl];\n }\n\n /** Strips the `/api/v4` suffix, so both spellings share a cache key. */\n protected override getRegistryUrl(registryUrl?: string): string {\n return getDepHost(registryUrl);\n }\n\n protected async fetchTags({\n registryUrl,\n packageName: repo,\n }: GetReleasesConfig): Promise<GitHostTag[]> {\n const apiBaseUrl = getApiBaseUrl(registryUrl);\n\n const urlEncodedRepo = encodeURIComponent(repo);\n\n // tag\n const url = joinUrlParts(\n apiBaseUrl,\n `projects`,\n urlEncodedRepo,\n `repository/tags?per_page=100`,\n );\n\n const gitlabTags = (\n await this.http.getJson(url, { paginate: true }, GitlabTags)\n ).body;\n\n return gitlabTags.map(({ name, commit }) => ({\n version: name,\n releaseTimestamp: asTimestamp(commit.created_at),\n }));\n }\n\n protected async fetchTagCommit(\n registryUrl: string | undefined,\n repo: string,\n tag: string,\n ): Promise<string | null> {\n const url = joinUrlParts(\n getApiBaseUrl(registryUrl),\n `projects`,\n encodeURIComponent(repo),\n `repository/commits/`,\n encodeURIComponent(tag),\n );\n const gitlabCommit = await this.http.getJson(url, GitlabCommit);\n return gitlabCommit.body.id;\n }\n\n protected async fetchLatestCommit(\n registryUrl: string | undefined,\n repo: string,\n ): Promise<string | null> {\n const url = joinUrlParts(\n getApiBaseUrl(registryUrl),\n `projects`,\n encodeURIComponent(repo),\n `repository/commits?per_page=1`,\n );\n const gitlabCommits = await this.http.getJson(url, GitlabCommits);\n return gitlabCommits.body[0]?.id ?? null;\n }\n\n protected override async fetchDigest(\n config: DigestConfig,\n newValue?: string,\n ): Promise<string | null> {\n try {\n return await super.fetchDigest(config, newValue);\n } catch (err) {\n if (isNotFound(err)) {\n logger.debug(\n {\n gitlabRepo: config.packageName,\n err,\n registryUrl: config.registryUrl,\n },\n 'Gitlab repo or ref not found when getting commit',\n );\n return null;\n }\n this.handleGenericErrors(err);\n }\n }\n}\n"],"mappings":";;;;;;;;;AAeA,IAAa,uBAAb,MAAa,6BAA6B,4BAAwC;CAChF,OAAgB,KAAK;CAErB,aAAuB,aAAqB,aAA8B;EACxE,OAAO,aAAa,aAAa,WAAW;CAC9C;CAEA,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,cAAc;EACZ,MAAM,qBAAqB,IAAI,IAAI,WAAW,qBAAqB,EAAE,CAAC;CACxE;CAEA,uBAAgC,cAAgC;EAC9D,OAAO,CAAC,kBAAkB;CAC5B;;CAGA,eAAkC,aAA8B;EAC9D,OAAO,WAAW,WAAW;CAC/B;CAEA,MAAgB,UAAU,EACxB,aACA,aAAa,QAC8B;EAC3C,MAAM,aAAa,cAAc,WAAW;EAK5C,MAAM,MAAM,aACV,YACA,YALqB,mBAAmB,IAM3B,GACb,8BACF;EAMA,QAHE,MAAM,KAAK,KAAK,QAAQ,KAAK,EAAE,UAAU,KAAK,GAAG,UAAU,EAAA,CAC3D,KAEgB,KAAK,EAAE,MAAM,cAAc;GAC3C,SAAS;GACT,kBAAkB,YAAY,OAAO,UAAU;EACjD,EAAE;CACJ;CAEA,MAAgB,eACd,aACA,MACA,KACwB;EACxB,MAAM,MAAM,aACV,cAAc,WAAW,GACzB,YACA,mBAAmB,IAAI,GACvB,uBACA,mBAAmB,GAAG,CACxB;EAEA,QAAO,MADoB,KAAK,KAAK,QAAQ,KAAK,YAAY,EAAA,CAC1C,KAAK;CAC3B;CAEA,MAAgB,kBACd,aACA,MACwB;EACxB,MAAM,MAAM,aACV,cAAc,WAAW,GACzB,YACA,mBAAmB,IAAI,GACvB,+BACF;EAEA,QAAO,MADqB,KAAK,KAAK,QAAQ,KAAK,aAAa,EAAA,CAC3C,KAAK,EAAE,EAAE,MAAM;CACtC;CAEA,MAAyB,YACvB,QACA,UACwB;EACxB,IAAI;GACF,OAAO,MAAM,MAAM,YAAY,QAAQ,QAAQ;EACjD,SAAS,KAAK;GACZ,IAAI,WAAW,GAAG,GAAG;IACnB,OAAO,MACL;KACE,YAAY,OAAO;KACnB;KACA,aAAa,OAAO;IACtB,GACA,kDACF;IACA,OAAO;GACT;GACA,KAAK,oBAAoB,GAAG;EAC9B;CACF;AACF"}
@@ -58,7 +58,7 @@ var BaseGoDatasource = class BaseGoDatasource {
58
58
  }
59
59
  if (goModule.startsWith("dev.azure.com/")) {
60
60
  const split = goModule.split("/");
61
- if (split.length > 4 && split[3] === "_git" || split.length > 3) {
61
+ if (split.length > 3) {
62
62
  const packageName = `https://dev.azure.com/${split[1]}/${split[2]}/_git/${(split[3] === "_git" ? split[4] : split[3]).replace(regEx(/\.git$/), "")}`;
63
63
  return {
64
64
  datasource: GitTagsDatasource.id,