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 { GlobalConfig } from "../../../config/global.js";
6
6
  import { sanitize } from "../../../util/sanitize.js";
7
7
  import { logger } from "../../../logger/index.js";
8
8
  import { ensureTrailingSlash } from "../../../util/url.js";
9
+ import { isServerError } from "../../../util/http/status.js";
9
10
  import { find } from "../../../util/host-rules.js";
10
11
  import { parseJson } from "../../../util/common.js";
11
12
  import { ExternalHostError } from "../../../types/errors/external-host-error.js";
@@ -109,7 +110,7 @@ async function getRawFile(fileName, repoName, branchOrTag) {
109
110
  throw new ExternalHostError(err, id);
110
111
  }
111
112
  if (err.code === "ECONNRESET" || err.code === "ETIMEDOUT") throw new ExternalHostError(err, id);
112
- if (err.statusCode && err.statusCode >= 500 && err.statusCode < 600) throw new ExternalHostError(err, id);
113
+ if (isServerError(err)) throw new ExternalHostError(err, id);
113
114
  throw err;
114
115
  }
115
116
  }
@@ -293,7 +294,10 @@ async function getBranchStatus(branchName, internalChecksAsSuccess) {
293
294
  }
294
295
  if (statuses.filter((status) => status.state === GitStatusState.Error || status.state === GitStatusState.Failed).length) return "red";
295
296
  if (statuses.filter((status) => status.state === GitStatusState.NotSet || status.state === GitStatusState.Pending).length) return "yellow";
296
- if (!internalChecksAsSuccess && statuses.every((status) => status.state === GitStatusState.Succeeded && status.context?.genre === "renovate")) {
297
+ if (!internalChecksAsSuccess && statuses.every((status) => {
298
+ const isInternal = status.context?.genre === "renovate";
299
+ return status.state === GitStatusState.Succeeded && isInternal;
300
+ })) {
297
301
  logger.debug("Successful checks are all internal renovate/ checks, so returning \"pending\" branch status");
298
302
  return "yellow";
299
303
  }
@@ -418,7 +422,7 @@ async function ensureComment({ number, topic, content }) {
418
422
  let commentNeedsUpdating = false;
419
423
  threads.forEach((thread) => {
420
424
  const firstCommentContent = thread.comments?.[0].content;
421
- if ((topic && firstCommentContent?.startsWith(header)) === true || !topic && firstCommentContent === body) {
425
+ if (topic ? firstCommentContent?.startsWith(header) === true : firstCommentContent === body) {
422
426
  threadIdFound = thread.id;
423
427
  commentIdFound = thread.comments?.[0].id;
424
428
  commentNeedsUpdating = firstCommentContent !== body;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["azureApi.getAuthenticatedUserId","azureApi.gitApi","hostRules.find","git.initRepo","azureHelper.getMergeMethod","azureHelper.getPolicyEvaluations","azureApi.coreApi","azureHelper.getAllProjectTeams"],"sources":["../../../../lib/modules/platform/azure/index.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport { isString } from '@sindresorhus/is';\nimport type { IGitApi } from 'azure-devops-node-api/GitApi.js';\nimport type {\n GitItem,\n GitPullRequest,\n GitPullRequestCommentThread,\n GitPullRequestSearchCriteria,\n GitStatus,\n GitVersionDescriptor,\n} from 'azure-devops-node-api/interfaces/GitInterfaces.js';\nimport {\n GitPullRequestMergeStrategy,\n GitStatusState,\n GitVersionType,\n PullRequestStatus,\n} from 'azure-devops-node-api/interfaces/GitInterfaces.js';\nimport type { PolicyEvaluationRecord } from 'azure-devops-node-api/interfaces/PolicyInterfaces.js';\nimport { PolicyEvaluationStatus } from 'azure-devops-node-api/interfaces/PolicyInterfaces.js';\nimport { getConfig } from '../../../config/defaults.ts';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n REPOSITORY_ARCHIVED,\n REPOSITORY_EMPTY,\n REPOSITORY_NOT_FOUND,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport * as git from '../../../util/git/index.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { getPrBodyStruct } from '../pr-body.ts';\nimport type {\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n EnsureIssueResult,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformPrOptions,\n PlatformResult,\n Pr,\n ReattemptPlatformAutomergeConfig,\n RepoConfigParams,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { getNewBranchName, repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { readOnlyIssueBody } from '../utils/read-only-issue-body.ts';\nimport * as azureApi from './azure-got-wrapper.ts';\nimport * as azureHelper from './azure-helper.ts';\nimport { IssueService } from './issue.ts';\nimport type { AzurePr, Config } from './types.ts';\nimport { AzurePrVote } from './types.ts';\nimport {\n getBranchNameWithoutRefsheadsPrefix,\n getGitStatusContextCombinedName,\n getGitStatusContextFromCombinedName,\n getRenovatePRFormat,\n getRepoByName,\n getStorageExtraCloneOpts,\n mapMergeStrategy,\n max4000Chars,\n} from './util.ts';\n\ninterface User {\n id: string;\n name: string;\n isRequired: boolean;\n}\n\ninterface GetRepoPullRequestsOptions {\n gitApi: IGitApi;\n searchCriteria: GitPullRequestSearchCriteria;\n skip: number;\n top: number;\n}\n\nlet config: Config = {} as any;\nlet issueService: IssueService;\nlet renovateUserId: string | undefined;\n\nconst defaults: {\n endpoint?: string;\n hostType: string;\n} = {\n hostType: 'azure',\n};\n\nfunction getRepoPullRequests({\n gitApi,\n searchCriteria,\n skip,\n top,\n}: GetRepoPullRequestsOptions): Promise<GitPullRequest[]> {\n const maxCommentLength = 0;\n return gitApi.getPullRequests(\n config.repoId,\n searchCriteria,\n config.project,\n maxCommentLength,\n skip,\n top,\n );\n}\n\nexport const id = 'azure';\n\nexport function initPlatform({\n endpoint,\n token,\n username,\n password,\n}: PlatformParams): Promise<PlatformResult> {\n if (!endpoint) {\n throw new Error('Init: You must configure an Azure DevOps endpoint');\n }\n if (!token && !(username && password)) {\n throw new Error(\n 'Init: You must configure an Azure DevOps token, or a username and password',\n );\n }\n // TODO: Add a connection check that endpoint/token combination are valid (#9593)\n const res = {\n endpoint: ensureTrailingSlash(endpoint),\n };\n defaults.endpoint = res.endpoint;\n azureApi.setEndpoint(res.endpoint);\n const credentials = token\n ? { token }\n : { username: username!, password: password! };\n return azureApi.getAuthenticatedUserId(credentials).then((userId) => {\n renovateUserId = userId;\n return res;\n });\n}\n\nexport async function getRepos(): Promise<string[]> {\n logger.debug('Autodiscovering Azure DevOps repositories');\n const azureApiGit = await azureApi.gitApi();\n const repos = await azureApiGit.getRepositories();\n return repos\n .filter((repo) => repo.isDisabled !== true)\n .map((repo) => `${repo.project?.name}/${repo.name}`);\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n try {\n const azureApiGit = await azureApi.gitApi();\n\n let repoId: string | undefined;\n if (repoName) {\n const repos = await azureApiGit.getRepositories();\n const repo = getRepoByName(repoName, repos);\n repoId = repo?.id;\n } else {\n repoId = config.repoId;\n }\n\n if (!repoId) {\n logger.debug('No repoId so cannot getRawFile');\n return null;\n }\n\n let item: GitItem | undefined;\n const versionDescriptor: GitVersionDescriptor = {\n version: branchOrTag,\n } satisfies GitVersionDescriptor;\n // Try to get file from repo with tag first, if not found, then try with branch #36835\n for (const versionType of [GitVersionType.Tag, GitVersionType.Branch]) {\n versionDescriptor.versionType = versionType;\n\n item = await azureApiGit.getItem(\n repoId, // repositoryId\n fileName, // path\n undefined, // project\n undefined, // scopePath\n undefined, // recursionLevel\n undefined, // includeContentMetadata\n undefined, // latestProcessedChange\n undefined, // download\n branchOrTag ? versionDescriptor : undefined, // versionDescriptor\n true, // includeContent\n );\n if (item) {\n break; // exit loop if item is found\n } else {\n logger.debug(\n `File: ${fileName} not found in ${repoName} with ${versionType}: ${branchOrTag}`,\n );\n }\n }\n return item?.content ?? null;\n } catch (err) /* v8 ignore next -- Azure API failure modes (service unavailable, malformed items) are not mocked in specs */ {\n if (\n err.message?.includes('<title>Azure DevOps Services Unavailable</title>')\n ) {\n logger.debug(\n 'Azure DevOps is currently unavailable when attempting to fetch file - throwing ExternalHostError',\n );\n throw new ExternalHostError(err, id);\n }\n if (err.code === 'ECONNRESET' || err.code === 'ETIMEDOUT') {\n throw new ExternalHostError(err, id);\n }\n if (err.statusCode && err.statusCode >= 500 && err.statusCode < 600) {\n throw new ExternalHostError(err, id);\n }\n throw err;\n }\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\nexport function applyRepoConfig({ azureWorkItemType }: RepoConfigParams): void {\n if (!azureWorkItemType || azureWorkItemType === config.workItemType) {\n return;\n }\n config.workItemType = azureWorkItemType;\n issueService = new IssueService(config);\n}\n\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n azureWorkItemType,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(\"${repository}\")`);\n config = {\n ignorePrAuthor: GlobalConfig.get('ignorePrAuthor'),\n repository,\n } as Config;\n const azureApiGit = await azureApi.gitApi();\n const repos = await azureApiGit.getRepositories();\n const repo = getRepoByName(repository, repos);\n if (!repo) {\n logger.error({ repos, repo }, 'Could not find repo in repo list');\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n logger.debug({ repositoryDetails: repo }, 'Repository details');\n if (repo.isDisabled) {\n logger.debug('Repository is disabled- throwing error to abort renovation');\n throw new Error(REPOSITORY_ARCHIVED);\n }\n /* v8 ignore next -- defensive: Azure omits defaultBranch only for empty repos, which abort earlier in specs */\n if (!repo.defaultBranch) {\n logger.debug('Repo is empty');\n throw new Error(REPOSITORY_EMPTY);\n }\n // TODO #22198\n config.repoId = repo.id!;\n\n config.project = repo.project!.name!;\n config.projectId = repo.project!.id!;\n config.workItemType = azureWorkItemType ?? getConfig().azureWorkItemType!;\n issueService = new IssueService(config);\n config.owner = '?owner?';\n logger.debug(`${repository} owner = ${config.owner}`);\n const defaultBranch = repo.defaultBranch.replace('refs/heads/', '');\n config.defaultBranch = defaultBranch;\n logger.debug(`${repository} default branch = ${defaultBranch}`);\n config.mergeMethods = {};\n config.repoForceRebase = false;\n\n const [projectName, repoName] = repository.split('/');\n const opts = hostRules.find({\n hostType: defaults.hostType,\n url: defaults.endpoint,\n });\n // TODO: types (#22198)\n const manualUrl = `${defaults.endpoint!}${encodeURIComponent(\n projectName,\n )}/_git/${encodeURIComponent(repoName)}`;\n const url = repo.remoteUrl ?? manualUrl;\n await git.initRepo({\n ...config,\n url,\n extraCloneOpts: getStorageExtraCloneOpts(opts),\n cloneSubmodules,\n cloneSubmodulesFilter,\n });\n const repoConfig: RepoResult = {\n defaultBranch,\n isFork: false,\n repoFingerprint: repoFingerprint(repo.id!, defaults.endpoint),\n };\n return repoConfig;\n}\n\nexport async function getPrList(): Promise<AzurePr[]> {\n logger.debug('getPrList()');\n if (!config.prList) {\n const azureApiGit = await azureApi.gitApi();\n\n let prs: GitPullRequest[] = [];\n let fetchedPrs: GitPullRequest[];\n let skip = 0;\n do {\n fetchedPrs = await getRepoPullRequests({\n gitApi: azureApiGit,\n searchCriteria: {\n status: PullRequestStatus.All,\n // fetch only prs directly created on the repo and not by forks\n sourceRepositoryId: config.repoId,\n ...(!config.ignorePrAuthor &&\n renovateUserId && { creatorId: renovateUserId }),\n },\n skip,\n top: 100,\n });\n prs = prs.concat(fetchedPrs);\n skip += 100;\n } while (fetchedPrs.length > 0);\n\n config.prList = prs.map(getRenovatePRFormat);\n logger.debug(`Retrieved Pull Requests count: ${config.prList.length}`);\n }\n return config.prList;\n}\n\nexport async function getPr(pullRequestId: number): Promise<Pr | null> {\n logger.debug(`getPr(${pullRequestId})`);\n if (!pullRequestId) {\n return null;\n }\n const azurePr = (await getPrList()).find(\n (item) => item.number === pullRequestId,\n );\n\n if (!azurePr) {\n return null;\n }\n\n const azureApiGit = await azureApi.gitApi();\n // the PR list returns descriptions truncated to 400 characters, so read the\n // full one for the body hash\n const { description } = await azureApiGit.getPullRequestById(\n pullRequestId,\n config.project,\n );\n azurePr.bodyStruct = getPrBodyStruct(description);\n\n const labels = await azureApiGit.getPullRequestLabels(\n config.repoId,\n pullRequestId,\n );\n\n azurePr.labels = labels\n .filter((label) => label.active)\n .map((label) => label.name)\n .filter(isString);\n return azurePr;\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n targetBranch,\n includeOtherAuthors,\n}: FindPRConfig): Promise<Pr | null> {\n let prsFiltered: Pr[] = [];\n try {\n if (includeOtherAuthors) {\n const azureApiGit = await azureApi.gitApi();\n const [pr] = await getRepoPullRequests({\n gitApi: azureApiGit,\n searchCriteria: {\n sourceRefName: getNewBranchName(branchName),\n sourceRepositoryId: config.repoId,\n status: PullRequestStatus.Active,\n ...(targetBranch && {\n targetRefName: getNewBranchName(targetBranch),\n }),\n },\n skip: 0,\n top: 1,\n });\n return pr ? getRenovatePRFormat(pr) : null;\n }\n\n const prs = await getPrList();\n\n prsFiltered = prs.filter(\n (item) => item.sourceRefName === getNewBranchName(branchName),\n );\n\n if (prTitle) {\n prsFiltered = prsFiltered.filter(\n (item) => item.title.toUpperCase() === prTitle.toUpperCase(),\n );\n }\n\n switch (state) {\n case 'all':\n // no more filter needed, we can go further...\n break;\n case '!open':\n prsFiltered = prsFiltered.filter((item) => item.state !== 'open');\n break;\n default:\n prsFiltered = prsFiltered.filter((item) => item.state === state);\n break;\n }\n } catch (err) {\n logger.error({ err }, 'findPr error');\n }\n if (prsFiltered.length === 0) {\n return null;\n }\n if (targetBranch && prsFiltered.length > 1) {\n const pr = prsFiltered.find((item) => item.targetBranch === targetBranch);\n if (pr) {\n return pr;\n }\n }\n return prsFiltered[0];\n}\n\nexport async function getBranchPr(\n branchName: string,\n targetBranch?: string,\n): Promise<Pr | null> {\n logger.debug(`getBranchPr(${branchName}, ${targetBranch})`);\n const existingPr = await findPr({\n branchName,\n state: 'open',\n targetBranch,\n });\n return existingPr ? getPr(existingPr.number) : null;\n}\n\nasync function getStatusCheck(branchName: string): Promise<GitStatus[]> {\n const azureApiGit = await azureApi.gitApi();\n const branch = await azureApiGit.getBranch(\n config.repoId,\n\n // TODO: fix undefined (#22198)\n getBranchNameWithoutRefsheadsPrefix(branchName)!,\n );\n // only grab the latest statuses, it will group any by context\n return azureApiGit.getStatuses(\n // TODO #22198\n branch.commit!.commitId!,\n config.repoId,\n undefined,\n undefined,\n undefined,\n true,\n );\n}\n\nconst azureToRenovateStatusMapping: Record<GitStatusState, BranchStatus> = {\n [GitStatusState.Succeeded]: 'green',\n [GitStatusState.NotApplicable]: 'green',\n [GitStatusState.NotSet]: 'yellow',\n [GitStatusState.Pending]: 'yellow',\n [GitStatusState.PartiallySucceeded]: 'yellow',\n [GitStatusState.Error]: 'red',\n [GitStatusState.Failed]: 'red',\n};\n\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n const res = await getStatusCheck(branchName);\n for (const check of res) {\n if (getGitStatusContextCombinedName(check.context) === context) {\n // TODO #22198\n return azureToRenovateStatusMapping[check.state!] ?? 'yellow';\n }\n }\n return null;\n}\n\nexport async function getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n const statuses = await getStatusCheck(branchName);\n logger.debug({ branch: branchName, statuses }, 'branch status check result');\n if (!statuses.length) {\n logger.debug('empty branch status check result = returning \"pending\"');\n return 'yellow';\n }\n const noOfFailures = statuses.filter(\n (status) =>\n status.state === GitStatusState.Error ||\n status.state === GitStatusState.Failed,\n ).length;\n if (noOfFailures) {\n return 'red';\n }\n const noOfPending = statuses.filter(\n (status) =>\n status.state === GitStatusState.NotSet ||\n status.state === GitStatusState.Pending,\n ).length;\n if (noOfPending) {\n return 'yellow';\n }\n if (\n !internalChecksAsSuccess &&\n statuses.every(\n (status) =>\n status.state === GitStatusState.Succeeded &&\n status.context?.genre === 'renovate',\n )\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n return 'green';\n}\n\nasync function getMergeStrategy(\n targetRefName: string,\n): Promise<GitPullRequestMergeStrategy> {\n return (\n config.mergeMethods[targetRefName] ??\n (config.mergeMethods[targetRefName] = await azureHelper.getMergeMethod(\n config.repoId,\n config.project,\n targetRefName,\n config.defaultBranch,\n ))\n );\n}\n\nasync function getPendingBlockingPolicyEvaluations(\n pullRequestId: number,\n): Promise<PolicyEvaluationRecord[]> {\n const artifactId = `vstfs:///CodeReview/CodeReviewId/${config.projectId}/${pullRequestId}`;\n const policyEvaluations = await azureHelper.getPolicyEvaluations(\n config.project,\n artifactId,\n );\n logger.debug(\n { pullRequestId, artifactId, policyEvaluations },\n 'Retrieved policy evaluations for PR',\n );\n return policyEvaluations.filter(\n (evaluation) =>\n evaluation.configuration?.isBlocking &&\n evaluation.status !== PolicyEvaluationStatus.Approved &&\n evaluation.status !== PolicyEvaluationStatus.NotApplicable,\n );\n}\n\nasync function setPlatformAutomerge(\n azureApiGit: IGitApi,\n pr: GitPullRequest,\n platformPrOptions: PlatformPrOptions,\n): Promise<GitPullRequest> {\n let mergeStrategy: GitPullRequestMergeStrategy;\n if (platformPrOptions.automergeStrategy === 'auto') {\n mergeStrategy = await getMergeStrategy(pr.targetRefName!);\n } else {\n mergeStrategy = mapMergeStrategy(platformPrOptions.automergeStrategy);\n }\n const prOptions: GitPullRequest = {\n autoCompleteSetBy: {\n // TODO #22198\n id: pr.createdBy!.id,\n },\n completionOptions: {\n mergeStrategy,\n deleteSourceBranch: true,\n mergeCommitMessage: pr.title,\n },\n };\n\n logger.debug(\n {\n prOptions,\n repoId: config.repoId,\n pullRequestId: pr.pullRequestId!,\n },\n // TODO #22198\n `Updating PR ${pr.pullRequestId!} to specify platformAutomerge settings`,\n );\n\n return await azureApiGit.updatePullRequest(\n prOptions,\n config.repoId,\n // TODO #22198\n pr.pullRequestId!,\n );\n}\n\nexport async function reattemptPlatformAutomerge({\n number,\n platformPrOptions,\n}: ReattemptPlatformAutomergeConfig): Promise<void> {\n try {\n const azureApiGit = await azureApi.gitApi();\n const pr = await azureApiGit.getPullRequestById(number, config.project);\n await setPlatformAutomerge(\n azureApiGit,\n pr,\n coerceObject(platformPrOptions),\n );\n\n logger.debug(`PR platform automerge re-attempted...prNo: ${number}`);\n } catch (err) {\n logger.warn({ err }, 'Error re-attempting PR platform automerge');\n }\n}\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle: title,\n prBody: body,\n labels,\n draftPR = false,\n platformPrOptions,\n}: CreatePRConfig): Promise<Pr> {\n const sourceRefName = getNewBranchName(sourceBranch);\n const targetRefName = getNewBranchName(targetBranch);\n const description = max4000Chars(sanitize(body));\n const azureApiGit = await azureApi.gitApi();\n const workItemRefs = [\n {\n id: platformPrOptions?.azureWorkItemId?.toString(),\n },\n ];\n let pr: GitPullRequest = await azureApiGit.createPullRequest(\n {\n sourceRefName,\n targetRefName,\n title,\n description,\n workItemRefs,\n isDraft: draftPR,\n },\n config.repoId,\n );\n if (platformPrOptions?.usePlatformAutomerge) {\n pr = await setPlatformAutomerge(azureApiGit, pr, platformPrOptions);\n }\n if (platformPrOptions?.autoApprove) {\n const approver = {\n reviewerUrl: pr.createdBy!.url,\n vote: AzurePrVote.Approved,\n isFlagged: false,\n isRequired: false,\n };\n\n logger.debug(\n {\n approver,\n\n repoId: config.repoId,\n // TODO #22198\n pullRequestId: pr.pullRequestId!,\n prCreatedBy: {\n id: pr.createdBy!.id!,\n },\n },\n // TODO #22198\n `Auto-approving PR ${pr.pullRequestId!}`,\n );\n\n await azureApiGit.createPullRequestReviewer(\n approver,\n config.repoId,\n // TODO #22198\n pr.pullRequestId!,\n pr.createdBy!.id!,\n );\n }\n await Promise.all(\n labels!.map((label) =>\n azureApiGit.createPullRequestLabel(\n {\n name: label,\n },\n config.repoId,\n // TODO #22198\n pr.pullRequestId!,\n ),\n ),\n );\n\n const result = getRenovatePRFormat(pr);\n if (config.prList) {\n config.prList.push(result);\n }\n return result;\n}\n\nexport async function updatePr({\n number: prNo,\n prTitle: title,\n prBody: body,\n state,\n platformPrOptions,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prNo}, ${title}, body)`);\n\n const azureApiGit = await azureApi.gitApi();\n const objToUpdate: GitPullRequest = {\n title,\n };\n\n if (targetBranch) {\n objToUpdate.targetRefName = getNewBranchName(targetBranch);\n }\n\n if (body) {\n objToUpdate.description = max4000Chars(sanitize(body));\n }\n\n if (state === 'open') {\n await azureApiGit.updatePullRequest(\n {\n status: PullRequestStatus.Active,\n },\n config.repoId,\n prNo,\n );\n } else if (state === 'closed') {\n objToUpdate.status = PullRequestStatus.Abandoned;\n }\n if (\n platformPrOptions?.autoApprove ||\n platformPrOptions?.usePlatformAutomerge\n ) {\n const pr = await azureApiGit.getPullRequestById(prNo, config.project);\n if (platformPrOptions.autoApprove) {\n await azureApiGit.createPullRequestReviewer(\n {\n reviewerUrl: pr.createdBy!.url,\n vote: AzurePrVote.Approved,\n isFlagged: false,\n isRequired: false,\n },\n config.repoId,\n // TODO #22198\n pr.pullRequestId!,\n pr.createdBy!.id!,\n );\n }\n // auto-complete keeps the merge commit message it was set with, so keep it in sync with the title\n // only when Renovate set auto-complete, which it does with the PR creator's id\n if (\n platformPrOptions.usePlatformAutomerge &&\n pr.autoCompleteSetBy?.id &&\n pr.autoCompleteSetBy.id === pr.createdBy?.id &&\n pr.completionOptions?.mergeCommitMessage !== title\n ) {\n objToUpdate.completionOptions = {\n ...pr.completionOptions,\n mergeCommitMessage: title,\n };\n }\n }\n\n const updatedPr = await azureApiGit.updatePullRequest(\n objToUpdate,\n config.repoId,\n prNo,\n );\n if (config.prList) {\n const prToCache = getRenovatePRFormat(updatedPr);\n // We need to update the cached entry for this PR\n const existingIndex = config.prList.findIndex(\n (item) => item.number === prNo,\n );\n /* v8 ignore next: should not happen */\n if (existingIndex === -1) {\n logger.warn({ prNo }, 'PR not found in cache');\n // Add to cache\n config.prList.push(prToCache);\n } else {\n // overwrite existing PR in cache\n config.prList[existingIndex] = prToCache;\n }\n }\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n logger.debug(`ensureComment(${number}, ${topic!}, content)`);\n const header = topic ? `### ${topic}\\n\\n` : '';\n const body = `${header}${sanitize(massageMarkdown(content))}`;\n const azureApiGit = await azureApi.gitApi();\n\n const threads = await azureApiGit.getThreads(config.repoId, number);\n let threadIdFound: number | undefined;\n let commentIdFound: number | undefined;\n let commentNeedsUpdating = false;\n threads.forEach((thread) => {\n const firstCommentContent = thread.comments?.[0].content;\n if (\n (topic && firstCommentContent?.startsWith(header)) === true ||\n (!topic && firstCommentContent === body)\n ) {\n threadIdFound = thread.id;\n commentIdFound = thread.comments?.[0].id;\n commentNeedsUpdating = firstCommentContent !== body;\n }\n });\n\n if (!threadIdFound) {\n await azureApiGit.createThread(\n {\n comments: [{ content: body, commentType: 1, parentCommentId: 0 }],\n status: 1,\n },\n config.repoId,\n number,\n );\n logger.info(\n { repository: config.repository, issueNo: number, topic },\n 'Comment added',\n );\n } else if (commentNeedsUpdating) {\n await azureApiGit.updateComment(\n {\n content: body,\n },\n config.repoId,\n number,\n threadIdFound,\n // TODO #22198\n commentIdFound!,\n );\n logger.debug(\n { repository: config.repository, issueNo: number, topic },\n 'Comment updated',\n );\n } else {\n logger.debug(\n { repository: config.repository, issueNo: number, topic },\n 'Comment is already up-to-date',\n );\n }\n\n return true;\n}\n\nexport async function ensureCommentRemoval(\n removeConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: issueNo } = removeConfig;\n const key =\n removeConfig.type === 'by-topic'\n ? removeConfig.topic\n : removeConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${issueNo} is removed`);\n\n const azureApiGit = await azureApi.gitApi();\n const threads = await azureApiGit.getThreads(config.repoId, issueNo);\n\n let threadIdFound: number | null | undefined = null;\n if (removeConfig.type === 'by-topic') {\n const thread = threads.find(\n (thread: GitPullRequestCommentThread): boolean =>\n !!thread.comments?.[0].content?.startsWith(\n `### ${removeConfig.topic}\\n\\n`,\n ),\n );\n threadIdFound = thread?.id;\n } else {\n const thread = threads.find(\n (thread: GitPullRequestCommentThread): boolean =>\n thread.comments?.[0].content?.trim() === removeConfig.content,\n );\n threadIdFound = thread?.id;\n }\n\n if (threadIdFound) {\n await azureApiGit.updateThread(\n {\n status: 4, // close\n },\n config.repoId,\n issueNo,\n threadIdFound,\n );\n }\n}\n\nconst renovateToAzureStatusMapping: Record<BranchStatus, GitStatusState> = {\n ['green']: GitStatusState.Succeeded,\n ['yellow']: GitStatusState.Pending,\n ['red']: GitStatusState.Failed,\n};\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n logger.debug(\n `setBranchStatus(${branchName}, ${context}, ${description}, ${state}, ${targetUrl!})`,\n );\n const azureApiGit = await azureApi.gitApi();\n const branch = await azureApiGit.getBranch(\n config.repoId,\n getBranchNameWithoutRefsheadsPrefix(branchName)!,\n );\n const statusToCreate: GitStatus = {\n description,\n context: getGitStatusContextFromCombinedName(context),\n state: renovateToAzureStatusMapping[state],\n targetUrl,\n };\n await azureApiGit.createCommitStatus(\n statusToCreate,\n // TODO #22198\n branch.commit!.commitId!,\n config.repoId,\n );\n logger.trace(`Created commit status of ${state} on branch ${branchName}`);\n}\n\nexport async function mergePr({\n branchName,\n id: pullRequestId,\n strategy,\n}: MergePRConfig): Promise<boolean> {\n logger.debug(`mergePr(${pullRequestId}, ${branchName!})`);\n\n const pendingPolicyEvaluations =\n await getPendingBlockingPolicyEvaluations(pullRequestId);\n if (pendingPolicyEvaluations.length) {\n logger.debug(\n {\n pullRequestId,\n pendingPolicies: pendingPolicyEvaluations.map((evaluation) => ({\n name: evaluation.configuration?.type?.displayName,\n status: PolicyEvaluationStatus[evaluation.status!],\n })),\n },\n 'Not completing PR because branch policies have not been satisfied yet',\n );\n return false;\n }\n\n const azureApiGit = await azureApi.gitApi();\n\n let pr = await azureApiGit.getPullRequestById(pullRequestId, config.project);\n\n const mergeStrategy =\n strategy === 'auto'\n ? await getMergeStrategy(pr.targetRefName!)\n : mapMergeStrategy(strategy);\n const objToUpdate: GitPullRequest = {\n status: PullRequestStatus.Completed,\n lastMergeSourceCommit: pr.lastMergeSourceCommit,\n completionOptions: {\n mergeStrategy,\n deleteSourceBranch: true,\n mergeCommitMessage: pr.title,\n },\n };\n\n logger.trace(\n `Updating PR ${pullRequestId} to status ${PullRequestStatus.Completed} (${\n PullRequestStatus[PullRequestStatus.Completed]\n }) with lastMergeSourceCommit ${\n // TODO: types (#22198)\n pr.lastMergeSourceCommit?.commitId\n } using mergeStrategy ${mergeStrategy} (${\n GitPullRequestMergeStrategy[mergeStrategy]\n })`,\n );\n\n try {\n const response = await azureApiGit.updatePullRequest(\n objToUpdate,\n config.repoId,\n pullRequestId,\n );\n\n let retries = 0;\n let isClosed = response.status === PullRequestStatus.Completed;\n while (!isClosed && retries < 5) {\n retries += 1;\n const sleepMs = retries * 1000;\n logger.trace(\n { pullRequestId, status: pr.status, retries },\n `Updated PR to closed status but change has not taken effect yet. Retrying...`,\n );\n\n await setTimeout(sleepMs);\n pr = await azureApiGit.getPullRequestById(pullRequestId, config.project);\n isClosed = pr.status === PullRequestStatus.Completed;\n }\n\n if (!isClosed) {\n logger.warn(\n {\n pullRequestId,\n status: pr.status,\n expectedPRStatus: PullRequestStatus[PullRequestStatus.Completed],\n actualPRStatus: PullRequestStatus[pr.status!],\n },\n 'Expected PR to have completed status. However, the PR has a different status',\n );\n }\n return true;\n } catch (err) {\n logger.debug({ err }, 'Failed to set the PR as completed.');\n return false;\n }\n}\n\nexport function massageMarkdown(input: string): string {\n // Remove any HTML we use\n return (\n smartTruncate(readOnlyIssueBody(input), maxBodyLength())\n .replace(\n 'you tick the rebase/retry checkbox',\n 'PR is renamed to start with \"rebase!\"',\n )\n .replace(\n 'checking the rebase/retry box above',\n 'renaming the PR to start with \"rebase!\"',\n )\n .replace(regEx(`\\n---\\n\\n.*?<!-- rebase-check -->.*?\\n`), '')\n .replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), '')\n // Replace GitHub-style PR links with Azure DevOps format\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](!')\n // Replace GitHub-style PR references (#123) with Azure DevOps format, needed for text linking config migration PR.\n // Only match a standalone reference (preceded by start, whitespace or `(`) so we don't corrupt\n // HTML entities like `&#8203;` or URL anchors like `CHANGELOG.md#4780`.\n .replace(regEx(/(?<lead>^|[\\s(])#(?<num>\\d+)/g), '$<lead>!$<num>')\n );\n}\n\nexport function maxBodyLength(): number {\n return 4000;\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n return await issueService.findIssue(title);\n}\n\nexport async function ensureIssue(\n issueConfig: EnsureIssueConfig,\n): Promise<EnsureIssueResult | null> {\n return await issueService.ensureIssue(issueConfig);\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n return await issueService.ensureIssueClosing(title);\n}\n\nexport async function getIssueList(titleFilter?: string): Promise<Issue[]> {\n return await issueService.getIssueList(titleFilter);\n}\n\nasync function getUserIds(users: string[]): Promise<User[]> {\n const azureApiGit = await azureApi.gitApi();\n const azureApiCore = await azureApi.coreApi();\n const repos = await azureApiGit.getRepositories();\n const repo = repos.find((c) => c.id === config.repoId)!;\n const requiredReviewerPrefix = 'required:';\n const validReviewers = new Set<string>();\n\n // TODO #22198\n const teams = await azureHelper.getAllProjectTeams(repo.project!.id!);\n const members = await Promise.all(\n teams.map(\n async (t) =>\n await azureApiCore.getTeamMembersWithExtendedProperties(\n // TODO #22198\n repo.project!.id!,\n t.id!,\n ),\n ),\n );\n\n const ids: { id: string; name: string; isRequired: boolean }[] = [];\n members.forEach((listMembers) => {\n listMembers.forEach((m) => {\n users.forEach((r) => {\n let reviewer = r;\n let isRequired = false;\n if (reviewer.startsWith(requiredReviewerPrefix)) {\n reviewer = reviewer.replace(requiredReviewerPrefix, '');\n isRequired = true;\n }\n if (\n (reviewer.toLowerCase() === m.identity?.displayName?.toLowerCase() ||\n reviewer.toLowerCase() === m.identity?.uniqueName?.toLowerCase()) &&\n ids.filter((c) => c.id === m.identity?.id).length === 0\n ) {\n // TODO #22198\n ids.push({\n id: m.identity.id!,\n name: reviewer,\n isRequired,\n });\n\n validReviewers.add(reviewer);\n }\n });\n });\n });\n\n teams.forEach((t) => {\n users.forEach((r) => {\n let reviewer = r;\n let isRequired = false;\n if (reviewer.startsWith(requiredReviewerPrefix)) {\n reviewer = reviewer.replace(requiredReviewerPrefix, '');\n isRequired = true;\n }\n // v8 ignore else -- TODO: add test #40625\n if (\n reviewer.toLowerCase() === t.name?.toLowerCase() &&\n ids.filter((c) => c.id === t.id).length === 0\n ) {\n // TODO #22198\n ids.push({ id: t.id!, name: reviewer, isRequired });\n\n validReviewers.add(reviewer);\n }\n });\n });\n\n for (const u of users) {\n const reviewer = u.replace(requiredReviewerPrefix, '');\n if (!validReviewers.has(reviewer)) {\n logger.once.info(\n `${reviewer} is neither an Azure DevOps Team nor a user associated with a Team`,\n );\n }\n }\n\n return ids;\n}\n\n/**\n *\n * @param {number} issueNo\n * @param {string[]} assignees\n */\nexport async function addAssignees(\n issueNo: number,\n assignees: string[],\n): Promise<void> {\n logger.trace(`addAssignees(${issueNo}, [${assignees.join(', ')}])`);\n const ids = await getUserIds(assignees);\n await ensureComment({\n number: issueNo,\n topic: 'Add Assignees',\n content: ids.map((a) => `@<${a.id}>`).join(', '),\n });\n}\n\n/**\n *\n * @param {number} prNo\n * @param {string[]} reviewers\n */\nexport async function addReviewers(\n prNo: number,\n reviewers: string[],\n): Promise<void> {\n logger.trace(`addReviewers(${prNo}, [${reviewers.join(', ')}])`);\n const azureApiGit = await azureApi.gitApi();\n\n const ids = await getUserIds(reviewers);\n\n await Promise.all(\n ids.map(async (obj) => {\n await azureApiGit.createPullRequestReviewer(\n {\n isRequired: obj.isRequired,\n },\n config.repoId,\n prNo,\n obj.id,\n );\n logger.debug(`Reviewer added: ${obj.name}`);\n }),\n );\n}\n\nexport async function deleteLabel(\n prNumber: number,\n label: string,\n): Promise<void> {\n logger.debug(`Deleting label ${label} from #${prNumber}`);\n const azureApiGit = await azureApi.gitApi();\n await azureApiGit.deletePullRequestLabels(config.repoId, prNumber, label);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["azureApi.getAuthenticatedUserId","azureApi.gitApi","hostRules.find","git.initRepo","azureHelper.getMergeMethod","azureHelper.getPolicyEvaluations","azureApi.coreApi","azureHelper.getAllProjectTeams"],"sources":["../../../../lib/modules/platform/azure/index.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport { isString } from '@sindresorhus/is';\nimport type { IGitApi } from 'azure-devops-node-api/GitApi.js';\nimport type {\n GitItem,\n GitPullRequest,\n GitPullRequestCommentThread,\n GitPullRequestSearchCriteria,\n GitStatus,\n GitVersionDescriptor,\n} from 'azure-devops-node-api/interfaces/GitInterfaces.js';\nimport {\n GitPullRequestMergeStrategy,\n GitStatusState,\n GitVersionType,\n PullRequestStatus,\n} from 'azure-devops-node-api/interfaces/GitInterfaces.js';\nimport type { PolicyEvaluationRecord } from 'azure-devops-node-api/interfaces/PolicyInterfaces.js';\nimport { PolicyEvaluationStatus } from 'azure-devops-node-api/interfaces/PolicyInterfaces.js';\nimport { getConfig } from '../../../config/defaults.ts';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n REPOSITORY_ARCHIVED,\n REPOSITORY_EMPTY,\n REPOSITORY_NOT_FOUND,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport * as git from '../../../util/git/index.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { isServerError } from '../../../util/http/status.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { getPrBodyStruct } from '../pr-body.ts';\nimport type {\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n EnsureIssueResult,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformPrOptions,\n PlatformResult,\n Pr,\n ReattemptPlatformAutomergeConfig,\n RepoConfigParams,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { getNewBranchName, repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport { readOnlyIssueBody } from '../utils/read-only-issue-body.ts';\nimport * as azureApi from './azure-got-wrapper.ts';\nimport * as azureHelper from './azure-helper.ts';\nimport { IssueService } from './issue.ts';\nimport type { AzurePr, Config } from './types.ts';\nimport { AzurePrVote } from './types.ts';\nimport {\n getBranchNameWithoutRefsheadsPrefix,\n getGitStatusContextCombinedName,\n getGitStatusContextFromCombinedName,\n getRenovatePRFormat,\n getRepoByName,\n getStorageExtraCloneOpts,\n mapMergeStrategy,\n max4000Chars,\n} from './util.ts';\n\ninterface User {\n id: string;\n name: string;\n isRequired: boolean;\n}\n\ninterface GetRepoPullRequestsOptions {\n gitApi: IGitApi;\n searchCriteria: GitPullRequestSearchCriteria;\n skip: number;\n top: number;\n}\n\nlet config: Config = {} as any;\nlet issueService: IssueService;\nlet renovateUserId: string | undefined;\n\nconst defaults: {\n endpoint?: string;\n hostType: string;\n} = {\n hostType: 'azure',\n};\n\nfunction getRepoPullRequests({\n gitApi,\n searchCriteria,\n skip,\n top,\n}: GetRepoPullRequestsOptions): Promise<GitPullRequest[]> {\n const maxCommentLength = 0;\n return gitApi.getPullRequests(\n config.repoId,\n searchCriteria,\n config.project,\n maxCommentLength,\n skip,\n top,\n );\n}\n\nexport const id = 'azure';\n\nexport function initPlatform({\n endpoint,\n token,\n username,\n password,\n}: PlatformParams): Promise<PlatformResult> {\n if (!endpoint) {\n throw new Error('Init: You must configure an Azure DevOps endpoint');\n }\n if (!token && !(username && password)) {\n throw new Error(\n 'Init: You must configure an Azure DevOps token, or a username and password',\n );\n }\n // TODO: Add a connection check that endpoint/token combination are valid (#9593)\n const res = {\n endpoint: ensureTrailingSlash(endpoint),\n };\n defaults.endpoint = res.endpoint;\n azureApi.setEndpoint(res.endpoint);\n const credentials = token\n ? { token }\n : { username: username!, password: password! };\n return azureApi.getAuthenticatedUserId(credentials).then((userId) => {\n renovateUserId = userId;\n return res;\n });\n}\n\nexport async function getRepos(): Promise<string[]> {\n logger.debug('Autodiscovering Azure DevOps repositories');\n const azureApiGit = await azureApi.gitApi();\n const repos = await azureApiGit.getRepositories();\n return repos\n .filter((repo) => repo.isDisabled !== true)\n .map((repo) => `${repo.project?.name}/${repo.name}`);\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n try {\n const azureApiGit = await azureApi.gitApi();\n\n let repoId: string | undefined;\n if (repoName) {\n const repos = await azureApiGit.getRepositories();\n const repo = getRepoByName(repoName, repos);\n repoId = repo?.id;\n } else {\n repoId = config.repoId;\n }\n\n if (!repoId) {\n logger.debug('No repoId so cannot getRawFile');\n return null;\n }\n\n let item: GitItem | undefined;\n const versionDescriptor: GitVersionDescriptor = {\n version: branchOrTag,\n } satisfies GitVersionDescriptor;\n // Try to get file from repo with tag first, if not found, then try with branch #36835\n for (const versionType of [GitVersionType.Tag, GitVersionType.Branch]) {\n versionDescriptor.versionType = versionType;\n\n item = await azureApiGit.getItem(\n repoId, // repositoryId\n fileName, // path\n undefined, // project\n undefined, // scopePath\n undefined, // recursionLevel\n undefined, // includeContentMetadata\n undefined, // latestProcessedChange\n undefined, // download\n branchOrTag ? versionDescriptor : undefined, // versionDescriptor\n true, // includeContent\n );\n if (item) {\n break; // exit loop if item is found\n } else {\n logger.debug(\n `File: ${fileName} not found in ${repoName} with ${versionType}: ${branchOrTag}`,\n );\n }\n }\n return item?.content ?? null;\n } catch (err) /* v8 ignore next -- Azure API failure modes (service unavailable, malformed items) are not mocked in specs */ {\n if (\n err.message?.includes('<title>Azure DevOps Services Unavailable</title>')\n ) {\n logger.debug(\n 'Azure DevOps is currently unavailable when attempting to fetch file - throwing ExternalHostError',\n );\n throw new ExternalHostError(err, id);\n }\n if (err.code === 'ECONNRESET' || err.code === 'ETIMEDOUT') {\n throw new ExternalHostError(err, id);\n }\n if (isServerError(err)) {\n throw new ExternalHostError(err, id);\n }\n throw err;\n }\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\nexport function applyRepoConfig({ azureWorkItemType }: RepoConfigParams): void {\n if (!azureWorkItemType || azureWorkItemType === config.workItemType) {\n return;\n }\n config.workItemType = azureWorkItemType;\n issueService = new IssueService(config);\n}\n\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n azureWorkItemType,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(\"${repository}\")`);\n config = {\n ignorePrAuthor: GlobalConfig.get('ignorePrAuthor'),\n repository,\n } as Config;\n const azureApiGit = await azureApi.gitApi();\n const repos = await azureApiGit.getRepositories();\n const repo = getRepoByName(repository, repos);\n if (!repo) {\n logger.error({ repos, repo }, 'Could not find repo in repo list');\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n logger.debug({ repositoryDetails: repo }, 'Repository details');\n if (repo.isDisabled) {\n logger.debug('Repository is disabled- throwing error to abort renovation');\n throw new Error(REPOSITORY_ARCHIVED);\n }\n /* v8 ignore next -- defensive: Azure omits defaultBranch only for empty repos, which abort earlier in specs */\n if (!repo.defaultBranch) {\n logger.debug('Repo is empty');\n throw new Error(REPOSITORY_EMPTY);\n }\n // TODO #22198\n config.repoId = repo.id!;\n\n config.project = repo.project!.name!;\n config.projectId = repo.project!.id!;\n config.workItemType = azureWorkItemType ?? getConfig().azureWorkItemType!;\n issueService = new IssueService(config);\n config.owner = '?owner?';\n logger.debug(`${repository} owner = ${config.owner}`);\n const defaultBranch = repo.defaultBranch.replace('refs/heads/', '');\n config.defaultBranch = defaultBranch;\n logger.debug(`${repository} default branch = ${defaultBranch}`);\n config.mergeMethods = {};\n config.repoForceRebase = false;\n\n const [projectName, repoName] = repository.split('/');\n const opts = hostRules.find({\n hostType: defaults.hostType,\n url: defaults.endpoint,\n });\n // TODO: types (#22198)\n const manualUrl = `${defaults.endpoint!}${encodeURIComponent(\n projectName,\n )}/_git/${encodeURIComponent(repoName)}`;\n const url = repo.remoteUrl ?? manualUrl;\n await git.initRepo({\n ...config,\n url,\n extraCloneOpts: getStorageExtraCloneOpts(opts),\n cloneSubmodules,\n cloneSubmodulesFilter,\n });\n const repoConfig: RepoResult = {\n defaultBranch,\n isFork: false,\n repoFingerprint: repoFingerprint(repo.id!, defaults.endpoint),\n };\n return repoConfig;\n}\n\nexport async function getPrList(): Promise<AzurePr[]> {\n logger.debug('getPrList()');\n if (!config.prList) {\n const azureApiGit = await azureApi.gitApi();\n\n let prs: GitPullRequest[] = [];\n let fetchedPrs: GitPullRequest[];\n let skip = 0;\n do {\n fetchedPrs = await getRepoPullRequests({\n gitApi: azureApiGit,\n searchCriteria: {\n status: PullRequestStatus.All,\n // fetch only prs directly created on the repo and not by forks\n sourceRepositoryId: config.repoId,\n ...(!config.ignorePrAuthor &&\n renovateUserId && { creatorId: renovateUserId }),\n },\n skip,\n top: 100,\n });\n prs = prs.concat(fetchedPrs);\n skip += 100;\n } while (fetchedPrs.length > 0);\n\n config.prList = prs.map(getRenovatePRFormat);\n logger.debug(`Retrieved Pull Requests count: ${config.prList.length}`);\n }\n return config.prList;\n}\n\nexport async function getPr(pullRequestId: number): Promise<Pr | null> {\n logger.debug(`getPr(${pullRequestId})`);\n if (!pullRequestId) {\n return null;\n }\n const azurePr = (await getPrList()).find(\n (item) => item.number === pullRequestId,\n );\n\n if (!azurePr) {\n return null;\n }\n\n const azureApiGit = await azureApi.gitApi();\n // the PR list returns descriptions truncated to 400 characters, so read the\n // full one for the body hash\n const { description } = await azureApiGit.getPullRequestById(\n pullRequestId,\n config.project,\n );\n azurePr.bodyStruct = getPrBodyStruct(description);\n\n const labels = await azureApiGit.getPullRequestLabels(\n config.repoId,\n pullRequestId,\n );\n\n azurePr.labels = labels\n .filter((label) => label.active)\n .map((label) => label.name)\n .filter(isString);\n return azurePr;\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n targetBranch,\n includeOtherAuthors,\n}: FindPRConfig): Promise<Pr | null> {\n let prsFiltered: Pr[] = [];\n try {\n if (includeOtherAuthors) {\n const azureApiGit = await azureApi.gitApi();\n const [pr] = await getRepoPullRequests({\n gitApi: azureApiGit,\n searchCriteria: {\n sourceRefName: getNewBranchName(branchName),\n sourceRepositoryId: config.repoId,\n status: PullRequestStatus.Active,\n ...(targetBranch && {\n targetRefName: getNewBranchName(targetBranch),\n }),\n },\n skip: 0,\n top: 1,\n });\n return pr ? getRenovatePRFormat(pr) : null;\n }\n\n const prs = await getPrList();\n\n prsFiltered = prs.filter(\n (item) => item.sourceRefName === getNewBranchName(branchName),\n );\n\n if (prTitle) {\n prsFiltered = prsFiltered.filter(\n (item) => item.title.toUpperCase() === prTitle.toUpperCase(),\n );\n }\n\n switch (state) {\n case 'all':\n // no more filter needed, we can go further...\n break;\n case '!open':\n prsFiltered = prsFiltered.filter((item) => item.state !== 'open');\n break;\n default:\n prsFiltered = prsFiltered.filter((item) => item.state === state);\n break;\n }\n } catch (err) {\n logger.error({ err }, 'findPr error');\n }\n if (prsFiltered.length === 0) {\n return null;\n }\n if (targetBranch && prsFiltered.length > 1) {\n const pr = prsFiltered.find((item) => item.targetBranch === targetBranch);\n if (pr) {\n return pr;\n }\n }\n return prsFiltered[0];\n}\n\nexport async function getBranchPr(\n branchName: string,\n targetBranch?: string,\n): Promise<Pr | null> {\n logger.debug(`getBranchPr(${branchName}, ${targetBranch})`);\n const existingPr = await findPr({\n branchName,\n state: 'open',\n targetBranch,\n });\n return existingPr ? getPr(existingPr.number) : null;\n}\n\nasync function getStatusCheck(branchName: string): Promise<GitStatus[]> {\n const azureApiGit = await azureApi.gitApi();\n const branch = await azureApiGit.getBranch(\n config.repoId,\n\n // TODO: fix undefined (#22198)\n getBranchNameWithoutRefsheadsPrefix(branchName)!,\n );\n // only grab the latest statuses, it will group any by context\n return azureApiGit.getStatuses(\n // TODO #22198\n branch.commit!.commitId!,\n config.repoId,\n undefined,\n undefined,\n undefined,\n true,\n );\n}\n\nconst azureToRenovateStatusMapping: Record<GitStatusState, BranchStatus> = {\n [GitStatusState.Succeeded]: 'green',\n [GitStatusState.NotApplicable]: 'green',\n [GitStatusState.NotSet]: 'yellow',\n [GitStatusState.Pending]: 'yellow',\n [GitStatusState.PartiallySucceeded]: 'yellow',\n [GitStatusState.Error]: 'red',\n [GitStatusState.Failed]: 'red',\n};\n\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n const res = await getStatusCheck(branchName);\n for (const check of res) {\n if (getGitStatusContextCombinedName(check.context) === context) {\n // TODO #22198\n return azureToRenovateStatusMapping[check.state!] ?? 'yellow';\n }\n }\n return null;\n}\n\nexport async function getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n const statuses = await getStatusCheck(branchName);\n logger.debug({ branch: branchName, statuses }, 'branch status check result');\n if (!statuses.length) {\n logger.debug('empty branch status check result = returning \"pending\"');\n return 'yellow';\n }\n const noOfFailures = statuses.filter(\n (status) =>\n status.state === GitStatusState.Error ||\n status.state === GitStatusState.Failed,\n ).length;\n if (noOfFailures) {\n return 'red';\n }\n const noOfPending = statuses.filter(\n (status) =>\n status.state === GitStatusState.NotSet ||\n status.state === GitStatusState.Pending,\n ).length;\n if (noOfPending) {\n return 'yellow';\n }\n if (\n !internalChecksAsSuccess &&\n statuses.every((status) => {\n const isInternal = status.context?.genre === 'renovate';\n return status.state === GitStatusState.Succeeded && isInternal;\n })\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n return 'green';\n}\n\nasync function getMergeStrategy(\n targetRefName: string,\n): Promise<GitPullRequestMergeStrategy> {\n return (\n config.mergeMethods[targetRefName] ??\n (config.mergeMethods[targetRefName] = await azureHelper.getMergeMethod(\n config.repoId,\n config.project,\n targetRefName,\n config.defaultBranch,\n ))\n );\n}\n\nasync function getPendingBlockingPolicyEvaluations(\n pullRequestId: number,\n): Promise<PolicyEvaluationRecord[]> {\n const artifactId = `vstfs:///CodeReview/CodeReviewId/${config.projectId}/${pullRequestId}`;\n const policyEvaluations = await azureHelper.getPolicyEvaluations(\n config.project,\n artifactId,\n );\n logger.debug(\n { pullRequestId, artifactId, policyEvaluations },\n 'Retrieved policy evaluations for PR',\n );\n return policyEvaluations.filter(\n (evaluation) =>\n evaluation.configuration?.isBlocking &&\n evaluation.status !== PolicyEvaluationStatus.Approved &&\n evaluation.status !== PolicyEvaluationStatus.NotApplicable,\n );\n}\n\nasync function setPlatformAutomerge(\n azureApiGit: IGitApi,\n pr: GitPullRequest,\n platformPrOptions: PlatformPrOptions,\n): Promise<GitPullRequest> {\n let mergeStrategy: GitPullRequestMergeStrategy;\n if (platformPrOptions.automergeStrategy === 'auto') {\n mergeStrategy = await getMergeStrategy(pr.targetRefName!);\n } else {\n mergeStrategy = mapMergeStrategy(platformPrOptions.automergeStrategy);\n }\n const prOptions: GitPullRequest = {\n autoCompleteSetBy: {\n // TODO #22198\n id: pr.createdBy!.id,\n },\n completionOptions: {\n mergeStrategy,\n deleteSourceBranch: true,\n mergeCommitMessage: pr.title,\n },\n };\n\n logger.debug(\n {\n prOptions,\n repoId: config.repoId,\n pullRequestId: pr.pullRequestId!,\n },\n // TODO #22198\n `Updating PR ${pr.pullRequestId!} to specify platformAutomerge settings`,\n );\n\n return await azureApiGit.updatePullRequest(\n prOptions,\n config.repoId,\n // TODO #22198\n pr.pullRequestId!,\n );\n}\n\nexport async function reattemptPlatformAutomerge({\n number,\n platformPrOptions,\n}: ReattemptPlatformAutomergeConfig): Promise<void> {\n try {\n const azureApiGit = await azureApi.gitApi();\n const pr = await azureApiGit.getPullRequestById(number, config.project);\n await setPlatformAutomerge(\n azureApiGit,\n pr,\n coerceObject(platformPrOptions),\n );\n\n logger.debug(`PR platform automerge re-attempted...prNo: ${number}`);\n } catch (err) {\n logger.warn({ err }, 'Error re-attempting PR platform automerge');\n }\n}\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle: title,\n prBody: body,\n labels,\n draftPR = false,\n platformPrOptions,\n}: CreatePRConfig): Promise<Pr> {\n const sourceRefName = getNewBranchName(sourceBranch);\n const targetRefName = getNewBranchName(targetBranch);\n const description = max4000Chars(sanitize(body));\n const azureApiGit = await azureApi.gitApi();\n const workItemRefs = [\n {\n id: platformPrOptions?.azureWorkItemId?.toString(),\n },\n ];\n let pr: GitPullRequest = await azureApiGit.createPullRequest(\n {\n sourceRefName,\n targetRefName,\n title,\n description,\n workItemRefs,\n isDraft: draftPR,\n },\n config.repoId,\n );\n if (platformPrOptions?.usePlatformAutomerge) {\n pr = await setPlatformAutomerge(azureApiGit, pr, platformPrOptions);\n }\n if (platformPrOptions?.autoApprove) {\n const approver = {\n reviewerUrl: pr.createdBy!.url,\n vote: AzurePrVote.Approved,\n isFlagged: false,\n isRequired: false,\n };\n\n logger.debug(\n {\n approver,\n\n repoId: config.repoId,\n // TODO #22198\n pullRequestId: pr.pullRequestId!,\n prCreatedBy: {\n id: pr.createdBy!.id!,\n },\n },\n // TODO #22198\n `Auto-approving PR ${pr.pullRequestId!}`,\n );\n\n await azureApiGit.createPullRequestReviewer(\n approver,\n config.repoId,\n // TODO #22198\n pr.pullRequestId!,\n pr.createdBy!.id!,\n );\n }\n await Promise.all(\n labels!.map((label) =>\n azureApiGit.createPullRequestLabel(\n {\n name: label,\n },\n config.repoId,\n // TODO #22198\n pr.pullRequestId!,\n ),\n ),\n );\n\n const result = getRenovatePRFormat(pr);\n if (config.prList) {\n config.prList.push(result);\n }\n return result;\n}\n\nexport async function updatePr({\n number: prNo,\n prTitle: title,\n prBody: body,\n state,\n platformPrOptions,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prNo}, ${title}, body)`);\n\n const azureApiGit = await azureApi.gitApi();\n const objToUpdate: GitPullRequest = {\n title,\n };\n\n if (targetBranch) {\n objToUpdate.targetRefName = getNewBranchName(targetBranch);\n }\n\n if (body) {\n objToUpdate.description = max4000Chars(sanitize(body));\n }\n\n if (state === 'open') {\n await azureApiGit.updatePullRequest(\n {\n status: PullRequestStatus.Active,\n },\n config.repoId,\n prNo,\n );\n } else if (state === 'closed') {\n objToUpdate.status = PullRequestStatus.Abandoned;\n }\n if (\n platformPrOptions?.autoApprove ||\n platformPrOptions?.usePlatformAutomerge\n ) {\n const pr = await azureApiGit.getPullRequestById(prNo, config.project);\n if (platformPrOptions.autoApprove) {\n await azureApiGit.createPullRequestReviewer(\n {\n reviewerUrl: pr.createdBy!.url,\n vote: AzurePrVote.Approved,\n isFlagged: false,\n isRequired: false,\n },\n config.repoId,\n // TODO #22198\n pr.pullRequestId!,\n pr.createdBy!.id!,\n );\n }\n // auto-complete keeps the merge commit message it was set with, so keep it in sync with the title\n // only when Renovate set auto-complete, which it does with the PR creator's id\n if (\n platformPrOptions.usePlatformAutomerge &&\n pr.autoCompleteSetBy?.id &&\n pr.autoCompleteSetBy.id === pr.createdBy?.id &&\n pr.completionOptions?.mergeCommitMessage !== title\n ) {\n objToUpdate.completionOptions = {\n ...pr.completionOptions,\n mergeCommitMessage: title,\n };\n }\n }\n\n const updatedPr = await azureApiGit.updatePullRequest(\n objToUpdate,\n config.repoId,\n prNo,\n );\n if (config.prList) {\n const prToCache = getRenovatePRFormat(updatedPr);\n // We need to update the cached entry for this PR\n const existingIndex = config.prList.findIndex(\n (item) => item.number === prNo,\n );\n /* v8 ignore next: should not happen */\n if (existingIndex === -1) {\n logger.warn({ prNo }, 'PR not found in cache');\n // Add to cache\n config.prList.push(prToCache);\n } else {\n // overwrite existing PR in cache\n config.prList[existingIndex] = prToCache;\n }\n }\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n logger.debug(`ensureComment(${number}, ${topic!}, content)`);\n const header = topic ? `### ${topic}\\n\\n` : '';\n const body = `${header}${sanitize(massageMarkdown(content))}`;\n const azureApiGit = await azureApi.gitApi();\n\n const threads = await azureApiGit.getThreads(config.repoId, number);\n let threadIdFound: number | undefined;\n let commentIdFound: number | undefined;\n let commentNeedsUpdating = false;\n threads.forEach((thread) => {\n const firstCommentContent = thread.comments?.[0].content;\n const isMatchingComment = topic\n ? firstCommentContent?.startsWith(header) === true\n : firstCommentContent === body;\n if (isMatchingComment) {\n threadIdFound = thread.id;\n commentIdFound = thread.comments?.[0].id;\n commentNeedsUpdating = firstCommentContent !== body;\n }\n });\n\n if (!threadIdFound) {\n await azureApiGit.createThread(\n {\n comments: [{ content: body, commentType: 1, parentCommentId: 0 }],\n status: 1,\n },\n config.repoId,\n number,\n );\n logger.info(\n { repository: config.repository, issueNo: number, topic },\n 'Comment added',\n );\n } else if (commentNeedsUpdating) {\n await azureApiGit.updateComment(\n {\n content: body,\n },\n config.repoId,\n number,\n threadIdFound,\n // TODO #22198\n commentIdFound!,\n );\n logger.debug(\n { repository: config.repository, issueNo: number, topic },\n 'Comment updated',\n );\n } else {\n logger.debug(\n { repository: config.repository, issueNo: number, topic },\n 'Comment is already up-to-date',\n );\n }\n\n return true;\n}\n\nexport async function ensureCommentRemoval(\n removeConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: issueNo } = removeConfig;\n const key =\n removeConfig.type === 'by-topic'\n ? removeConfig.topic\n : removeConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${issueNo} is removed`);\n\n const azureApiGit = await azureApi.gitApi();\n const threads = await azureApiGit.getThreads(config.repoId, issueNo);\n\n let threadIdFound: number | null | undefined = null;\n if (removeConfig.type === 'by-topic') {\n const thread = threads.find(\n (thread: GitPullRequestCommentThread): boolean =>\n !!thread.comments?.[0].content?.startsWith(\n `### ${removeConfig.topic}\\n\\n`,\n ),\n );\n threadIdFound = thread?.id;\n } else {\n const thread = threads.find(\n (thread: GitPullRequestCommentThread): boolean =>\n thread.comments?.[0].content?.trim() === removeConfig.content,\n );\n threadIdFound = thread?.id;\n }\n\n if (threadIdFound) {\n await azureApiGit.updateThread(\n {\n status: 4, // close\n },\n config.repoId,\n issueNo,\n threadIdFound,\n );\n }\n}\n\nconst renovateToAzureStatusMapping: Record<BranchStatus, GitStatusState> = {\n ['green']: GitStatusState.Succeeded,\n ['yellow']: GitStatusState.Pending,\n ['red']: GitStatusState.Failed,\n};\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n logger.debug(\n `setBranchStatus(${branchName}, ${context}, ${description}, ${state}, ${targetUrl!})`,\n );\n const azureApiGit = await azureApi.gitApi();\n const branch = await azureApiGit.getBranch(\n config.repoId,\n getBranchNameWithoutRefsheadsPrefix(branchName)!,\n );\n const statusToCreate: GitStatus = {\n description,\n context: getGitStatusContextFromCombinedName(context),\n state: renovateToAzureStatusMapping[state],\n targetUrl,\n };\n await azureApiGit.createCommitStatus(\n statusToCreate,\n // TODO #22198\n branch.commit!.commitId!,\n config.repoId,\n );\n logger.trace(`Created commit status of ${state} on branch ${branchName}`);\n}\n\nexport async function mergePr({\n branchName,\n id: pullRequestId,\n strategy,\n}: MergePRConfig): Promise<boolean> {\n logger.debug(`mergePr(${pullRequestId}, ${branchName!})`);\n\n const pendingPolicyEvaluations =\n await getPendingBlockingPolicyEvaluations(pullRequestId);\n if (pendingPolicyEvaluations.length) {\n logger.debug(\n {\n pullRequestId,\n pendingPolicies: pendingPolicyEvaluations.map((evaluation) => ({\n name: evaluation.configuration?.type?.displayName,\n status: PolicyEvaluationStatus[evaluation.status!],\n })),\n },\n 'Not completing PR because branch policies have not been satisfied yet',\n );\n return false;\n }\n\n const azureApiGit = await azureApi.gitApi();\n\n let pr = await azureApiGit.getPullRequestById(pullRequestId, config.project);\n\n const mergeStrategy =\n strategy === 'auto'\n ? await getMergeStrategy(pr.targetRefName!)\n : mapMergeStrategy(strategy);\n const objToUpdate: GitPullRequest = {\n status: PullRequestStatus.Completed,\n lastMergeSourceCommit: pr.lastMergeSourceCommit,\n completionOptions: {\n mergeStrategy,\n deleteSourceBranch: true,\n mergeCommitMessage: pr.title,\n },\n };\n\n logger.trace(\n `Updating PR ${pullRequestId} to status ${PullRequestStatus.Completed} (${\n PullRequestStatus[PullRequestStatus.Completed]\n }) with lastMergeSourceCommit ${\n // TODO: types (#22198)\n pr.lastMergeSourceCommit?.commitId\n } using mergeStrategy ${mergeStrategy} (${\n GitPullRequestMergeStrategy[mergeStrategy]\n })`,\n );\n\n try {\n const response = await azureApiGit.updatePullRequest(\n objToUpdate,\n config.repoId,\n pullRequestId,\n );\n\n let retries = 0;\n let isClosed = response.status === PullRequestStatus.Completed;\n while (!isClosed && retries < 5) {\n retries += 1;\n const sleepMs = retries * 1000;\n logger.trace(\n { pullRequestId, status: pr.status, retries },\n `Updated PR to closed status but change has not taken effect yet. Retrying...`,\n );\n\n await setTimeout(sleepMs);\n pr = await azureApiGit.getPullRequestById(pullRequestId, config.project);\n isClosed = pr.status === PullRequestStatus.Completed;\n }\n\n if (!isClosed) {\n logger.warn(\n {\n pullRequestId,\n status: pr.status,\n expectedPRStatus: PullRequestStatus[PullRequestStatus.Completed],\n actualPRStatus: PullRequestStatus[pr.status!],\n },\n 'Expected PR to have completed status. However, the PR has a different status',\n );\n }\n return true;\n } catch (err) {\n logger.debug({ err }, 'Failed to set the PR as completed.');\n return false;\n }\n}\n\nexport function massageMarkdown(input: string): string {\n // Remove any HTML we use\n return (\n smartTruncate(readOnlyIssueBody(input), maxBodyLength())\n .replace(\n 'you tick the rebase/retry checkbox',\n 'PR is renamed to start with \"rebase!\"',\n )\n .replace(\n 'checking the rebase/retry box above',\n 'renaming the PR to start with \"rebase!\"',\n )\n .replace(regEx(`\\n---\\n\\n.*?<!-- rebase-check -->.*?\\n`), '')\n .replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), '')\n // Replace GitHub-style PR links with Azure DevOps format\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](!')\n // Replace GitHub-style PR references (#123) with Azure DevOps format, needed for text linking config migration PR.\n // Only match a standalone reference (preceded by start, whitespace or `(`) so we don't corrupt\n // HTML entities like `&#8203;` or URL anchors like `CHANGELOG.md#4780`.\n .replace(regEx(/(?<lead>^|[\\s(])#(?<num>\\d+)/g), '$<lead>!$<num>')\n );\n}\n\nexport function maxBodyLength(): number {\n return 4000;\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n return await issueService.findIssue(title);\n}\n\nexport async function ensureIssue(\n issueConfig: EnsureIssueConfig,\n): Promise<EnsureIssueResult | null> {\n return await issueService.ensureIssue(issueConfig);\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n return await issueService.ensureIssueClosing(title);\n}\n\nexport async function getIssueList(titleFilter?: string): Promise<Issue[]> {\n return await issueService.getIssueList(titleFilter);\n}\n\nasync function getUserIds(users: string[]): Promise<User[]> {\n const azureApiGit = await azureApi.gitApi();\n const azureApiCore = await azureApi.coreApi();\n const repos = await azureApiGit.getRepositories();\n const repo = repos.find((c) => c.id === config.repoId)!;\n const requiredReviewerPrefix = 'required:';\n const validReviewers = new Set<string>();\n\n // TODO #22198\n const teams = await azureHelper.getAllProjectTeams(repo.project!.id!);\n const members = await Promise.all(\n teams.map(\n async (t) =>\n await azureApiCore.getTeamMembersWithExtendedProperties(\n // TODO #22198\n repo.project!.id!,\n t.id!,\n ),\n ),\n );\n\n const ids: { id: string; name: string; isRequired: boolean }[] = [];\n members.forEach((listMembers) => {\n listMembers.forEach((m) => {\n users.forEach((r) => {\n let reviewer = r;\n let isRequired = false;\n if (reviewer.startsWith(requiredReviewerPrefix)) {\n reviewer = reviewer.replace(requiredReviewerPrefix, '');\n isRequired = true;\n }\n const isMatchingIdentity =\n reviewer.toLowerCase() === m.identity?.displayName?.toLowerCase() ||\n reviewer.toLowerCase() === m.identity?.uniqueName?.toLowerCase();\n if (\n isMatchingIdentity &&\n ids.filter((c) => c.id === m.identity?.id).length === 0\n ) {\n // TODO #22198\n ids.push({\n id: m.identity!.id!,\n name: reviewer,\n isRequired,\n });\n\n validReviewers.add(reviewer);\n }\n });\n });\n });\n\n teams.forEach((t) => {\n users.forEach((r) => {\n let reviewer = r;\n let isRequired = false;\n if (reviewer.startsWith(requiredReviewerPrefix)) {\n reviewer = reviewer.replace(requiredReviewerPrefix, '');\n isRequired = true;\n }\n // v8 ignore else -- TODO: add test #40625\n if (\n reviewer.toLowerCase() === t.name?.toLowerCase() &&\n ids.filter((c) => c.id === t.id).length === 0\n ) {\n // TODO #22198\n ids.push({ id: t.id!, name: reviewer, isRequired });\n\n validReviewers.add(reviewer);\n }\n });\n });\n\n for (const u of users) {\n const reviewer = u.replace(requiredReviewerPrefix, '');\n if (!validReviewers.has(reviewer)) {\n logger.once.info(\n `${reviewer} is neither an Azure DevOps Team nor a user associated with a Team`,\n );\n }\n }\n\n return ids;\n}\n\n/**\n *\n * @param {number} issueNo\n * @param {string[]} assignees\n */\nexport async function addAssignees(\n issueNo: number,\n assignees: string[],\n): Promise<void> {\n logger.trace(`addAssignees(${issueNo}, [${assignees.join(', ')}])`);\n const ids = await getUserIds(assignees);\n await ensureComment({\n number: issueNo,\n topic: 'Add Assignees',\n content: ids.map((a) => `@<${a.id}>`).join(', '),\n });\n}\n\n/**\n *\n * @param {number} prNo\n * @param {string[]} reviewers\n */\nexport async function addReviewers(\n prNo: number,\n reviewers: string[],\n): Promise<void> {\n logger.trace(`addReviewers(${prNo}, [${reviewers.join(', ')}])`);\n const azureApiGit = await azureApi.gitApi();\n\n const ids = await getUserIds(reviewers);\n\n await Promise.all(\n ids.map(async (obj) => {\n await azureApiGit.createPullRequestReviewer(\n {\n isRequired: obj.isRequired,\n },\n config.repoId,\n prNo,\n obj.id,\n );\n logger.debug(`Reviewer added: ${obj.name}`);\n }),\n );\n}\n\nexport async function deleteLabel(\n prNumber: number,\n label: string,\n): Promise<void> {\n logger.debug(`Deleting label ${label} from #${prNumber}`);\n const azureApiGit = await azureApi.gitApi();\n await azureApiGit.deletePullRequestLabels(config.repoId, prNumber, label);\n}\n"],"mappings":"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"}
@@ -6,6 +6,7 @@ import { UUIDRegex, matchRegexOrGlobList } from "../../../util/string-match.js";
6
6
  import { sanitize } from "../../../util/sanitize.js";
7
7
  import { logger } from "../../../logger/index.js";
8
8
  import { parseUrl } from "../../../util/url.js";
9
+ import { isBadRequest, isForbidden, isNotFound } from "../../../util/http/status.js";
9
10
  import { find } from "../../../util/host-rules.js";
10
11
  import { getInheritedOrGlobal, parseJson } from "../../../util/common.js";
11
12
  import { BitbucketHttp, setBaseUrl } from "../../../util/http/bitbucket.js";
@@ -84,7 +85,7 @@ async function initPlatform({ endpoint, username, password, token }) {
84
85
  const { uuid } = (await bitbucketHttp.getJsonUnchecked("/2.0/user", options)).body;
85
86
  renovateUserUuid = uuid;
86
87
  } catch (err) {
87
- if (err.statusCode === 403 && err.body?.error?.detail?.required?.includes("account")) logger.warn(`Bitbucket: missing 'account' scope for password`);
88
+ if (isForbidden(err) && err.body?.error?.detail?.required?.includes("account")) logger.warn(`Bitbucket: missing 'account' scope for password`);
88
89
  else logger.debug({ err }, "Unknown error fetching Bitbucket user identity");
89
90
  }
90
91
  const platformConfig = { endpoint: endpoint ?? BITBUCKET_PROD_ENDPOINT };
@@ -159,7 +160,7 @@ async function initRepo({ repository, cloneSubmodules, cloneSubmodulesFilter })
159
160
  };
160
161
  logger.debug(`${repository} owner = ${config.owner}`);
161
162
  } catch (err) /* v8 ignore next -- initRepo error mapping (404 to not-found) is not mocked in specs */ {
162
- if (err.statusCode === 404) throw new Error(REPOSITORY_NOT_FOUND);
163
+ if (isNotFound(err)) throw new Error(REPOSITORY_NOT_FOUND);
163
164
  logger.debug({ err }, "Unknown Bitbucket initRepo error");
164
165
  throw err;
165
166
  }
@@ -210,7 +211,10 @@ async function findPr({ branchName, prTitle, state = "all", includeOtherAuthors
210
211
  }
211
212
  return prInfo(prs[0]);
212
213
  }
213
- const pr = (await getPrList()).find((p) => p.sourceBranch === branchName && (!prTitle || p.title.toUpperCase() === prTitle.toUpperCase()) && matchesState(p.state, state));
214
+ const pr = (await getPrList()).find((p) => {
215
+ if (p.sourceBranch !== branchName || !matchesState(p.state, state)) return false;
216
+ return !prTitle || p.title.toUpperCase() === prTitle.toUpperCase();
217
+ });
214
218
  if (!pr) return null;
215
219
  logger.debug(`Found PR #${pr.number}`);
216
220
  /**
@@ -280,7 +284,10 @@ async function getBranchStatus(branchName, internalChecksAsSuccess) {
280
284
  }
281
285
  if (statuses.filter((status) => status.state === "FAILED" || status.state === "STOPPED").length) return "red";
282
286
  if (statuses.filter((status) => status.state === "INPROGRESS").length) return "yellow";
283
- if (!internalChecksAsSuccess && statuses.every((status) => status.state === "SUCCESSFUL" && status.key?.startsWith("renovate/"))) {
287
+ if (!internalChecksAsSuccess && statuses.every((status) => {
288
+ const isInternal = status.key?.startsWith("renovate/");
289
+ return status.state === "SUCCESSFUL" && isInternal;
290
+ })) {
284
291
  logger.debug("Successful checks are all internal renovate/ checks, so returning \"pending\" branch status");
285
292
  return "yellow";
286
293
  }
@@ -422,7 +429,7 @@ function ensureCommentRemoval(deleteConfig) {
422
429
  return ensureCommentRemoval$1(config, deleteConfig);
423
430
  }
424
431
  async function sanitizeReviewers(reviewers, err) {
425
- if (err.statusCode === 400 && err.body?.error?.fields?.reviewers) {
432
+ if (isBadRequest(err) && err.body?.error?.fields?.reviewers) {
426
433
  const sanitizedReviewers = [];
427
434
  const MSG_AUTHOR_AND_REVIEWER = "is the author and cannot be included as a reviewer.";
428
435
  const MSG_MALFORMED_REVIEWERS_LIST = "Malformed reviewers list";
@@ -447,7 +454,7 @@ async function isAccountMemberOfWorkspace(reviewer, repository) {
447
454
  await bitbucketHttp.get(`/2.0/workspaces/${workspace}/members/${reviewer.uuid}`, { cacheProvider: aggressiveRepoCacheProvider });
448
455
  return true;
449
456
  } catch (err) {
450
- if (err.statusCode === 404) {
457
+ if (isNotFound(err)) {
451
458
  logger.debug({ err }, `User ${reviewer.display_name} is not a member of the workspace ${workspace}. Will be removed from the PR`);
452
459
  return false;
453
460
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["promises.map","hostRules.find","git.getUrl","git.initRepo","utils.prInfo","reopenComments","comments.reopenComments","comments.REOPEN_PR_COMMENT_KEYWORD","utils.buildStates","comments.ensureComment","comments.ensureCommentRemoval"],"sources":["../../../../lib/modules/platform/bitbucket/index.ts"],"sourcesContent":["import { isNonEmptyArray, isNonEmptyString } from '@sindresorhus/is';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { REPOSITORY_NOT_FOUND } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { getInheritedOrGlobal, parseJson } from '../../../util/common.ts';\nimport * as git from '../../../util/git/index.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport type { BitbucketHttpOptions } from '../../../util/http/bitbucket.ts';\nimport { BitbucketHttp, setBaseUrl } from '../../../util/http/bitbucket.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport {\n aggressiveRepoCacheProvider,\n repoCacheProvider,\n} from '../../../util/http/cache/repository-http-cache-provider.ts';\nimport type { HttpOptions } from '../../../util/http/types.ts';\nimport * as promises from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { UUIDRegex, matchRegexOrGlobList } from '../../../util/string-match.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n EnsureIssueResult,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformResult,\n Pr,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport * as comments from './comments.ts';\nimport { getRepoFile } from './files.ts';\nimport { BitbucketPrCache } from './pr-cache.ts';\nimport {\n RepoInfo,\n Repositories,\n UnresolvedPrTasks,\n WorkspaceAccesses,\n} from './schema.ts';\nimport type {\n Account,\n BitbucketStatus,\n BranchResponse,\n Config,\n EffectiveReviewer,\n PagedResult,\n PrResponse,\n RepoBranchingModel,\n} from './types.ts';\nimport * as utils from './utils.ts';\nimport { mergeBodyTransformer } from './utils.ts';\n\nexport const id = 'bitbucket';\n\nconst bitbucketHttp = new BitbucketHttp();\n\nconst BITBUCKET_PROD_ENDPOINT = 'https://api.bitbucket.org/';\n\nlet config: Config = {} as any;\n\nexport function resetPlatform(): void {\n config = {} as any;\n renovateUserUuid = null;\n}\n\nconst defaults = { endpoint: BITBUCKET_PROD_ENDPOINT };\n\nconst pathSeparator = '/';\n\nlet renovateUserUuid: string | null = null;\n\nexport async function initPlatform({\n endpoint,\n username,\n password,\n token,\n}: PlatformParams): Promise<PlatformResult> {\n if (!(username && password) && !token) {\n throw new Error(\n 'Init: You must configure either a Bitbucket token or username and password',\n );\n }\n if (endpoint && endpoint !== BITBUCKET_PROD_ENDPOINT) {\n logger.warn(\n { endpoint, defaultEndpoint: BITBUCKET_PROD_ENDPOINT },\n 'Init: Bitbucket Cloud endpoint should generally be the default but is being configured to a different value. Did you mean to use Bitbucket Server?',\n );\n defaults.endpoint = endpoint;\n }\n setBaseUrl(defaults.endpoint);\n renovateUserUuid = null;\n const options: HttpOptions = { memCache: false };\n if (token) {\n options.token = token;\n } else {\n options.username = username;\n options.password = password;\n }\n try {\n const { uuid } = (\n await bitbucketHttp.getJsonUnchecked<Account>('/2.0/user', options)\n ).body;\n renovateUserUuid = uuid;\n } catch (err) {\n if (\n err.statusCode === 403 &&\n err.body?.error?.detail?.required?.includes('account')\n ) {\n logger.warn(`Bitbucket: missing 'account' scope for password`);\n } else {\n logger.debug({ err }, 'Unknown error fetching Bitbucket user identity');\n }\n }\n // TODO: Add a connection check that endpoint/username/password combination are valid (#9594)\n const platformConfig: PlatformResult = {\n endpoint: endpoint ?? BITBUCKET_PROD_ENDPOINT,\n };\n return Promise.resolve(platformConfig);\n}\n\n// Get all repositories that the user has access to\nexport async function getRepos(config: AutodiscoverConfig): Promise<string[]> {\n logger.debug('Autodiscovering Bitbucket Cloud repositories');\n try {\n // Determine which workspaces to query.\n // If the caller supplied explicit namespaces use them directly;\n // otherwise discover all workspaces the authenticated user belongs to.\n // The old cross-workspace endpoint GET /2.0/repositories?role=contributor\n // was removed by Bitbucket on 2026-03-31 (CHANGE-2770).\n let workspaceSlugs: string[];\n const autodiscoverNamespaces = config.namespaces;\n if (isNonEmptyArray(autodiscoverNamespaces)) {\n logger.debug(\n { autodiscoverNamespaces },\n 'Using configured namespaces as Bitbucket workspaces',\n );\n workspaceSlugs = autodiscoverNamespaces;\n } else {\n logger.debug('Fetching Bitbucket workspaces for the current user');\n const { body: slugs } = await bitbucketHttp.getJson(\n '/2.0/user/workspaces',\n { paginate: true },\n WorkspaceAccesses,\n );\n workspaceSlugs = slugs;\n logger.debug(\n { workspaceSlugs },\n `Found ${workspaceSlugs.length} Bitbucket workspace(s)`,\n );\n }\n\n // Fetch repositories for every workspace in parallel (concurrency-limited).\n const repoArrays = await promises.map(workspaceSlugs, (workspace) =>\n bitbucketHttp\n .getJson(\n `/2.0/repositories/${workspace}`,\n { paginate: true },\n Repositories,\n )\n .then(({ body }) => body),\n );\n\n let repos = repoArrays.flat();\n\n // if autodiscoverProjects is configured, filter the repos list\n const autodiscoverProjects = config.projects;\n if (isNonEmptyArray(autodiscoverProjects)) {\n logger.debug(\n { autodiscoverProjects: config.projects },\n 'Applying autodiscoverProjects filter',\n );\n repos = repos.filter(\n (repo) =>\n repo.projectName &&\n matchRegexOrGlobList(repo.projectName, autodiscoverProjects),\n );\n }\n\n return repos.map(({ owner, name }) => `${owner}/${name}`);\n } catch (err) /* v8 ignore next -- defensive: repo listing failures are logged and rethrown, not simulated in specs */ {\n logger.error({ err }, `bitbucket getRepos error`);\n throw err;\n }\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const repo = repoName ?? config.repository;\n\n let finalBranchOrTag = branchOrTag;\n if (branchOrTag?.includes(pathSeparator)) {\n // Branch name contains slash, so we have to replace branch name with SHA1 of the head commit; otherwise the API will not work.\n finalBranchOrTag = await getBranchCommit(branchOrTag);\n }\n\n return await getRepoFile(bitbucketHttp, repo, fileName, finalBranchOrTag, {\n cacheProvider: repoCacheProvider,\n });\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n // TODO #22198\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\n// Initialize bitbucket by getting base branch and SHA\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(\"${repository}\")`);\n const opts = hostRules.find({\n hostType: 'bitbucket',\n url: defaults.endpoint,\n });\n config = {\n repository,\n ignorePrAuthor: GlobalConfig.get('ignorePrAuthor'),\n } as Config;\n let info: RepoInfo;\n let mainBranch: string;\n try {\n const { body: repoInfo } = await bitbucketHttp.getJson(\n `/2.0/repositories/${repository}`,\n RepoInfo,\n );\n info = repoInfo;\n\n mainBranch = info.mainbranch;\n\n if (getInheritedOrGlobal('bbUseDevelopmentBranch')) {\n logger.debug(\n \"bbUseDevelopmentBranch is true - Checking BitBucket's development branch\",\n );\n const developmentBranch = (\n await bitbucketHttp.getJsonUnchecked<RepoBranchingModel>(\n `/2.0/repositories/${repository}/effective-branching-model`,\n )\n ).body.development?.name;\n\n if (developmentBranch) {\n mainBranch = developmentBranch;\n logger.debug(\n `${developmentBranch} is BitBucket's development branch - using it as default branch`,\n );\n }\n }\n\n config.defaultBranch = mainBranch;\n\n config = {\n ...config,\n owner: info.owner,\n mergeMethod: info.mergeMethod,\n is_private: info.is_private,\n };\n\n logger.debug(`${repository} owner = ${config.owner}`);\n } catch (err) /* v8 ignore next -- initRepo error mapping (404 to not-found) is not mocked in specs */ {\n if (err.statusCode === 404) {\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n logger.debug({ err }, 'Unknown Bitbucket initRepo error');\n throw err;\n }\n\n const parsedEndpoint = parseUrl(defaults.endpoint);\n // v8 ignore if: endpoint is a constant\n if (!parsedEndpoint) {\n throw new Error(`Invalid Bitbucket endpoint: ${defaults.endpoint}`);\n }\n const { hostname } = parsedEndpoint;\n\n // Converts API hostnames to their respective HTTP git hosts:\n // `api.bitbucket.org` to `bitbucket.org`\n // `api-staging.<host>` to `staging.<host>`\n // TODO #22198\n const hostnameWithoutApiPrefix =\n regEx(/api[.|-](?<host>.+)/).exec(hostname)?.groups?.host;\n\n let auth = '';\n if (opts.token) {\n auth = `x-token-auth:${opts.token}`;\n } else if (opts.password?.startsWith('ATAT')) {\n auth = `x-bitbucket-api-token-auth:${opts.password}`;\n } else {\n auth = `${opts.username!}:${opts.password!}`;\n }\n\n const url = git.getUrl({\n protocol: 'https',\n auth,\n hostname: hostnameWithoutApiPrefix,\n repository,\n });\n\n await git.initRepo({\n ...config,\n url,\n cloneSubmodules,\n cloneSubmodulesFilter,\n });\n const repoConfig: RepoResult = {\n defaultBranch: mainBranch,\n isFork: info.isFork,\n repoFingerprint: repoFingerprint(info.uuid, defaults.endpoint),\n };\n return repoConfig;\n}\n\n/* v8 ignore next -- covered only through findPr callers, never invoked directly in specs */\nfunction matchesState(state: string, desiredState: string): boolean {\n if (desiredState === 'all') {\n return true;\n }\n if (desiredState.startsWith('!')) {\n return state !== desiredState.substring(1);\n }\n return state === desiredState;\n}\n\nexport async function getPrList(): Promise<Pr[]> {\n logger.trace('getPrList()');\n return await BitbucketPrCache.getPrs(\n bitbucketHttp,\n config.repository,\n renovateUserUuid,\n );\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n includeOtherAuthors,\n}: FindPRConfig): Promise<Pr | null> {\n logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`);\n\n if (includeOtherAuthors) {\n // PR might have been created by anyone, so don't use the cached Renovate PR list\n const prs = (\n await bitbucketHttp.getJsonUnchecked<PagedResult<PrResponse>>(\n `/2.0/repositories/${config.repository}/pullrequests?q=source.branch.name=\"${branchName}\"&state=open`,\n { cacheProvider: memCacheProvider },\n )\n ).body.values;\n\n if (prs.length === 0) {\n logger.debug(`No PR found for branch ${branchName}`);\n return null;\n }\n\n return utils.prInfo(prs[0]);\n }\n\n const prList = await getPrList();\n const pr = prList.find(\n (p) =>\n p.sourceBranch === branchName &&\n (!prTitle || p.title.toUpperCase() === prTitle.toUpperCase()) &&\n matchesState(p.state, state),\n );\n\n if (!pr) {\n return null;\n }\n logger.debug(`Found PR #${pr.number}`);\n\n /**\n * Bitbucket doesn't support renaming or reopening declined PRs.\n * Instead, we have to use comment-driven signals.\n */\n if (pr.state === 'closed') {\n const reopenComments = await comments.reopenComments(config, pr.number);\n\n if (isNonEmptyArray(reopenComments)) {\n if (config.is_private) {\n // Only workspace members could have commented on a private repository\n logger.debug(\n `Found '${comments.REOPEN_PR_COMMENT_KEYWORD}' comment from workspace member. Renovate will reopen PR ${pr.number} as a new PR`,\n );\n return null;\n }\n\n for (const comment of reopenComments) {\n if (await isAccountMemberOfWorkspace(comment.user, config.repository)) {\n logger.debug(\n `Found '${comments.REOPEN_PR_COMMENT_KEYWORD}' comment from workspace member. Renovate will reopen PR ${pr.number} as a new PR`,\n );\n return null;\n }\n }\n }\n }\n\n return pr;\n}\n\n// Gets details for a PR\nexport async function getPr(prNo: number): Promise<Pr | null> {\n const pr = (\n await bitbucketHttp.getJsonUnchecked<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n )\n ).body;\n\n /* v8 ignore next -- defensive: the PR endpoint returns a body or throws, never an empty body */\n if (!pr) {\n return null;\n }\n\n const res: Pr = {\n ...utils.prInfo(pr),\n };\n\n if (isNonEmptyArray(pr.reviewers)) {\n res.reviewers = pr.reviewers\n .map(({ uuid }) => uuid)\n .filter(isNonEmptyString);\n }\n\n return res;\n}\n\nfunction escapeHash(input: string): string {\n return input?.replace(regEx(/#/g), '%23');\n}\n\n// Return the commit SHA for a branch\nasync function getBranchCommit(\n branchName: string,\n): Promise<string | undefined> {\n try {\n const branch = (\n await bitbucketHttp.getJsonUnchecked<BranchResponse>(\n `/2.0/repositories/${config.repository}/refs/branches/${escapeHash(\n branchName,\n )}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n )\n ).body;\n return branch.target.hash;\n } catch (err) /* v8 ignore next -- defensive: missing branch is logged and mapped to undefined, not mocked in specs */ {\n logger.debug({ err }, `getBranchCommit('${branchName}') failed'`);\n return undefined;\n }\n}\n\n// Returns the Pull Request for a branch. Null if not exists.\nexport async function getBranchPr(branchName: string): Promise<Pr | null> {\n logger.debug(`getBranchPr(${branchName})`);\n const existingPr = await findPr({\n branchName,\n state: 'open',\n });\n return existingPr ? getPr(existingPr.number) : null;\n}\n\nasync function getStatus(\n branchName: string,\n memCache = true,\n): Promise<BitbucketStatus[]> {\n const sha = await getBranchCommit(branchName);\n const opts: BitbucketHttpOptions = { paginate: true };\n /* v8 ignore next: temporary code */\n if (memCache) {\n opts.cacheProvider = aggressiveRepoCacheProvider;\n } else {\n opts.memCache = false;\n }\n return (\n await bitbucketHttp.getJsonUnchecked<PagedResult<BitbucketStatus>>(\n `/2.0/repositories/${config.repository}/commit/${sha!}/statuses`,\n opts,\n )\n ).body.values;\n}\n// Returns the combined status for a branch.\nexport async function getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n const statuses = await getStatus(branchName);\n logger.debug({ branch: branchName, statuses }, 'branch status check result');\n if (!statuses.length) {\n logger.debug('empty branch status check result = returning \"pending\"');\n return 'yellow';\n }\n const noOfFailures = statuses.filter(\n (status: { state: string }) =>\n status.state === 'FAILED' || status.state === 'STOPPED',\n ).length;\n if (noOfFailures) {\n return 'red';\n }\n const noOfPending = statuses.filter(\n (status: { state: string }) => status.state === 'INPROGRESS',\n ).length;\n if (noOfPending) {\n return 'yellow';\n }\n if (\n !internalChecksAsSuccess &&\n statuses.every(\n (status) =>\n status.state === 'SUCCESSFUL' && status.key?.startsWith('renovate/'),\n )\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n return 'green';\n}\n\nconst bbToRenovateStatusMapping: Record<string, BranchStatus> = {\n SUCCESSFUL: 'green',\n INPROGRESS: 'yellow',\n FAILED: 'red',\n};\n\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n const statuses = await getStatus(branchName);\n const bbState = statuses.find((status) => status.key === context)?.state;\n // TODO #22198\n return bbToRenovateStatusMapping[bbState!] || null;\n}\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n const sha = await getBranchCommit(branchName);\n\n // TargetUrl can not be empty so default to bitbucket\n /* v8 ignore next -- specs always pass a targetUrl, fallback exists for direct API constraints */\n const url = targetUrl ?? 'https://bitbucket.org';\n\n const body = {\n name: context,\n state: utils.buildStates[state],\n key: context,\n description,\n url,\n };\n\n await bitbucketHttp.postJson(\n `/2.0/repositories/${config.repository}/commit/${sha}/statuses/build`,\n { body },\n );\n\n // invalidate status cache\n const branchStatusesUrl = bitbucketHttp\n .resolveUrl(`/2.0/repositories/${config.repository}/commit/${sha}/statuses`)\n .toString();\n aggressiveRepoCacheProvider.markSynced('get', branchStatusesUrl, false);\n}\n\n/**\n * Remove or transform markdown into Bitbucket supported syntax.\n *\n * See https://bitbucket.org/tutorials/markdowndemo/src for supported markdown syntax\n */\nexport function massageMarkdown(input: string): string {\n let massaged = smartTruncate(input, maxBodyLength())\n .replace(\n 'you tick the rebase/retry checkbox',\n 'by renaming this PR to start with \"rebase!\"',\n )\n .replace(\n 'checking the rebase/retry box above',\n 'renaming the PR to start with \"rebase!\"',\n )\n .replace(\n regEx(\n /<details>\\n(?:<summary>View abandoned dependencies.*<\\/summary>\\n\\n)(?<body>[\\s\\S]*?)<\\/details>/,\n ),\n '$<body>',\n )\n .replace(regEx(`\\n---\\n\\n.*?<!-- rebase-check -->.*?\\n`), '')\n .replace(regEx(/\\]\\(\\.\\.\\/issues\\//g), '](../../issues/')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](../../pull-requests/')\n .replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), '');\n\n massaged = massageDetailSummaryHtmlToNestedLists(massaged);\n\n return massageCodeblockMarkdown(massaged);\n}\n\n/**\n * Massage codeblocks indentation to ensure correct rendering in Bitbucket.\n */\nfunction massageCodeblockMarkdown(body: string): string {\n const codeBlockRegex = regEx(\n /^(?<indent>[ \\t]*)```(?<lang>\\w*)[^\\n]*\\n(?<code>[\\s\\S]*?)\\n[ \\t]*```/gm,\n );\n let codeMatch;\n let result = body;\n\n while ((codeMatch = codeBlockRegex.exec(body)) !== null) {\n const { indent, lang, code } = codeMatch.groups!;\n const indentLength = indent.length;\n const lines = code.split('\\n');\n const cleanedLines = lines.map((line) =>\n // Remove `indentLength` characters from the start of each line\n line.slice(indentLength),\n );\n\n const cleaned = cleanedLines.join('\\n');\n const replacement = `\\`\\`\\`${lang}\\n${cleaned}\\n\\`\\`\\``;\n\n result = result.replace(codeMatch[0], replacement);\n }\n\n return result;\n}\n\n/**\n * Massage collapsible html sections into nested unordered lists.\n *\n * Bitbucket doesn't currently support collapsible syntax; https://jira.atlassian.com/browse/BCLOUD-20231\n */\nfunction massageDetailSummaryHtmlToNestedLists(body: string): string {\n let depth = 0;\n // Parse detail parts to calculate correct list depth\n const detailsParts = body.split('<details>').map((raw) => {\n const partDepth = depth;\n\n depth += 1;\n const countClosingDetailsTags = raw.split('</details>').length - 1;\n depth = Math.max(0, depth - countClosingDetailsTags);\n\n return { raw, partDepth };\n });\n\n // Reassemble parts while replacing collapsible html elements with markdown list\n return detailsParts\n .map(({ raw, partDepth }) => {\n let t = raw;\n\n if (partDepth === 0) {\n return t;\n }\n\n const partIndentation = '\\t'.repeat(partDepth - 1);\n const nestedListItemIndentation = '\\t'.repeat(partDepth);\n\n const rawContainsBlockquote = raw.includes('<blockquote>');\n\n t = t.replace(regEx(/<\\/?summary>/g), partDepth === 1 ? '**' : '`');\n\n if (partDepth > 1) {\n t = t.replace(\n regEx(/^(?<prefix>[ \\t]*- [`[])/gm),\n `${nestedListItemIndentation}$<prefix>`,\n );\n }\n\n let result = partIndentation;\n if (rawContainsBlockquote || partDepth > 1) {\n result += ' - ';\n }\n result += t;\n\n return result;\n })\n .join('')\n .replace(regEx(/<\\/?(?:summary|details|blockquote)>/g), '');\n}\n\nexport function maxBodyLength(): number {\n return 250000;\n}\n\nfunction logIssuesRemoved(): void {\n logger.once.debug(\n 'Bitbucket Cloud has removed its issue tracker, so Renovate features which rely on issues, like the Dependency Dashboard, do not work. See https://developer.atlassian.com/cloud/bitbucket/changelog/#CHANGE-3071',\n );\n}\n\nexport function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n logIssuesRemoved();\n return Promise.resolve(null);\n}\n\nexport function ensureIssue({\n title,\n}: EnsureIssueConfig): Promise<EnsureIssueResult | null> {\n logger.once.warn({ title }, 'Cannot ensure issue');\n logIssuesRemoved();\n return Promise.resolve(null);\n}\n\nexport function getIssueList(): Promise<Issue[]> {\n logger.debug(`getIssueList()`);\n logIssuesRemoved();\n return Promise.resolve([]);\n}\n\nexport function ensureIssueClosing(title: string): Promise<void> {\n logger.debug(`ensureIssueClosing(${title})`);\n logIssuesRemoved();\n return Promise.resolve();\n}\n\nexport function addAssignees(\n _prNr: number,\n _assignees: string[],\n): Promise<void> {\n // Bitbucket supports \"participants\" and \"reviewers\" so does not seem to have the concept of \"assignee\"\n logger.warn('Cannot add assignees');\n return Promise.resolve();\n}\n\nexport async function addReviewers(\n prId: number,\n reviewers: string[],\n): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${prId}`);\n\n // TODO #22198\n const { title } = (await getPr(prId))!;\n\n const body = {\n title,\n reviewers: reviewers.map((username: string) => {\n const isUUID =\n username.startsWith('{') &&\n username.endsWith('}') &&\n UUIDRegex.test(username.slice(1, -1));\n const key = isUUID ? 'uuid' : 'username';\n return {\n [key]: username,\n };\n }),\n };\n\n await bitbucketHttp.putJson(\n `/2.0/repositories/${config.repository}/pullrequests/${prId}`,\n {\n body,\n },\n );\n}\n\n/* v8 ignore next -- stub: Bitbucket Cloud has no PR labels, callers never reach this */\nexport function deleteLabel(): never {\n throw new Error('deleteLabel not implemented');\n}\n\nexport function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n // https://developer.atlassian.com/bitbucket/api/2/reference/search?q=pullrequest+comment\n return comments.ensureComment({\n config,\n number,\n topic,\n content: sanitize(content),\n });\n}\n\nexport function ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n return comments.ensureCommentRemoval(config, deleteConfig);\n}\n\nasync function sanitizeReviewers(\n reviewers: Account[],\n err: any,\n): Promise<Account[] | undefined> {\n if (err.statusCode === 400 && err.body?.error?.fields?.reviewers) {\n const sanitizedReviewers: Account[] = [];\n\n const MSG_AUTHOR_AND_REVIEWER =\n 'is the author and cannot be included as a reviewer.';\n const MSG_MALFORMED_REVIEWERS_LIST = 'Malformed reviewers list';\n const MSG_NOT_WORKSPACE_MEMBER =\n 'is not a member of this workspace and cannot be added to this pull request';\n\n for (const msg of err.body.error.fields.reviewers) {\n // Bitbucket returns a 400 if any of the PR reviewer accounts are now inactive (ie: disabled/suspended)\n if (msg === MSG_MALFORMED_REVIEWERS_LIST) {\n logger.debug(\n { err },\n 'PR contains reviewers that may be either inactive or no longer a member of this workspace. Will try setting only active reviewers',\n );\n\n // Validate that each previous PR reviewer account is still active\n for (const reviewer of reviewers) {\n const reviewerUser = (\n await bitbucketHttp.getJsonUnchecked<Account>(\n `/2.0/users/${reviewer.uuid}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n )\n ).body;\n\n // There are cases where an active user may still not be a member of a workspace\n if (\n reviewerUser.account_status === 'active' &&\n (await isAccountMemberOfWorkspace(reviewer, config.repository))\n ) {\n sanitizedReviewers.push(reviewer);\n }\n }\n // Bitbucket returns a 400 if any of the PR reviewer accounts are no longer members of this workspace\n } else if (msg.endsWith(MSG_NOT_WORKSPACE_MEMBER)) {\n logger.debug(\n { err },\n 'PR contains reviewer accounts which are no longer member of this workspace. Will try setting only member reviewers',\n );\n\n // Validate that each previous PR reviewer account is still a member of this workspace\n for (const reviewer of reviewers) {\n if (await isAccountMemberOfWorkspace(reviewer, config.repository)) {\n sanitizedReviewers.push(reviewer);\n }\n }\n } else if (msg.endsWith(MSG_AUTHOR_AND_REVIEWER)) {\n logger.debug(\n { err },\n 'PR contains reviewer accounts which are also the author. Will try setting only non-author reviewers',\n );\n const author = msg.replace(MSG_AUTHOR_AND_REVIEWER, '').trim();\n for (const reviewer of reviewers) {\n if (reviewer.display_name !== author) {\n sanitizedReviewers.push(reviewer);\n }\n }\n } else {\n return undefined;\n }\n }\n\n return sanitizedReviewers;\n }\n\n return undefined;\n}\n\nasync function isAccountMemberOfWorkspace(\n reviewer: Account,\n repository: string,\n): Promise<boolean> {\n const workspace = repository.split('/')[0];\n\n try {\n await bitbucketHttp.get(\n `/2.0/workspaces/${workspace}/members/${reviewer.uuid}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n );\n\n return true;\n } catch (err) {\n // HTTP 404: User cannot be found, or the user is not a member of this workspace.\n if (err.statusCode === 404) {\n logger.debug(\n { err },\n `User ${reviewer.display_name} is not a member of the workspace ${workspace}. Will be removed from the PR`,\n );\n\n return false;\n }\n throw err;\n }\n}\n\n// Creates PR and returns PR number\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle: title,\n prBody: description,\n draftPR = false,\n platformPrOptions,\n}: CreatePRConfig): Promise<Pr> {\n // labels is not supported in Bitbucket: https://bitbucket.org/site/master/issues/11976/ability-to-add-labels-to-pull-requests-bb\n\n const base = targetBranch;\n\n logger.debug({ repository: config.repository, title, base }, 'Creating PR');\n\n let reviewers: Account[] = [];\n\n if (platformPrOptions?.bbUseDefaultReviewers) {\n const reviewersResponse = (\n await bitbucketHttp.getJsonUnchecked<PagedResult<EffectiveReviewer>>(\n `/2.0/repositories/${config.repository}/effective-default-reviewers`,\n {\n paginate: true,\n cacheProvider: aggressiveRepoCacheProvider,\n },\n )\n ).body;\n reviewers = reviewersResponse.values.map((reviewer: EffectiveReviewer) => ({\n uuid: reviewer.user.uuid,\n display_name: reviewer.user.display_name,\n }));\n }\n\n const body = {\n title,\n description: sanitize(description),\n source: {\n branch: {\n name: sourceBranch,\n },\n },\n destination: {\n branch: {\n name: base,\n },\n },\n close_source_branch: true,\n reviewers,\n draft: draftPR,\n };\n\n try {\n const prRes = (\n await bitbucketHttp.postJson<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests`,\n {\n body,\n },\n )\n ).body;\n const pr = utils.prInfo(prRes);\n await BitbucketPrCache.setPr(\n bitbucketHttp,\n config.repository,\n renovateUserUuid,\n pr,\n );\n if (platformPrOptions?.bbAutoResolvePrTasks) {\n await autoResolvePrTasks(pr);\n }\n return pr;\n } catch (err) /* v8 ignore next -- reviewer-sanitizing retry path depends on API error shapes not mocked in specs */ {\n // Try sanitizing reviewers\n const sanitizedReviewers = await sanitizeReviewers(reviewers, err);\n\n if (sanitizedReviewers === undefined) {\n logger.warn({ err }, 'Error creating pull request');\n throw err;\n } else {\n const prRes = (\n await bitbucketHttp.postJson<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests`,\n {\n body: {\n ...body,\n reviewers: sanitizedReviewers,\n },\n },\n )\n ).body;\n const pr = utils.prInfo(prRes);\n await BitbucketPrCache.setPr(\n bitbucketHttp,\n config.repository,\n renovateUserUuid,\n pr,\n );\n if (platformPrOptions?.bbAutoResolvePrTasks) {\n await autoResolvePrTasks(pr);\n }\n return pr;\n }\n }\n}\n\nasync function autoResolvePrTasks(pr: Pr): Promise<void> {\n logger.debug(`Auto resolve PR tasks in #${pr.number}`);\n try {\n const unResolvedTasks = (\n await bitbucketHttp.getJson(\n `/2.0/repositories/${config.repository}/pullrequests/${pr.number}/tasks`,\n { paginate: true, pagelen: 100 },\n UnresolvedPrTasks,\n )\n ).body;\n\n logger.trace(\n {\n prId: pr.number,\n listTaskRes: unResolvedTasks,\n },\n 'List PR tasks',\n );\n\n for (const task of unResolvedTasks) {\n const res = await bitbucketHttp.putJson(\n `/2.0/repositories/${config.repository}/pullrequests/${pr.number}/tasks/${task.id}`,\n {\n body: {\n state: 'RESOLVED',\n content: {\n raw: task.content.raw,\n },\n },\n },\n );\n logger.trace(\n {\n prId: pr.number,\n updateTaskResponse: res,\n },\n 'Put PR tasks - mark resolved',\n );\n }\n } catch (err) {\n logger.warn({ prId: pr.number, err }, 'Error resolving PR tasks');\n }\n}\n\nexport async function updatePr({\n number: prNo,\n prTitle: title,\n prBody: description,\n state,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prNo}, ${title}, body)`);\n // Updating a PR in Bitbucket will clear the reviewers if reviewers is not present\n const pr = (\n await bitbucketHttp.getJsonUnchecked<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}`,\n )\n ).body;\n\n let updatedPrRes: PrResponse;\n try {\n const body: any = {\n title,\n description: sanitize(description),\n reviewers: pr.reviewers,\n };\n if (targetBranch) {\n body.destination = {\n branch: {\n name: targetBranch,\n },\n };\n }\n\n updatedPrRes = (\n await bitbucketHttp.putJson<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}`,\n { body },\n )\n ).body;\n } catch (err) {\n // Try sanitizing reviewers\n const sanitizedReviewers = await sanitizeReviewers(pr.reviewers, err);\n\n if (sanitizedReviewers === undefined) {\n throw err;\n } else {\n updatedPrRes = (\n await bitbucketHttp.putJson<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}`,\n {\n body: {\n title,\n description: sanitize(description),\n reviewers: sanitizedReviewers,\n },\n },\n )\n ).body;\n }\n }\n\n if (state === 'closed' && pr) {\n await bitbucketHttp.postJson(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}/decline`,\n );\n }\n\n // update pr cache\n await BitbucketPrCache.setPr(\n bitbucketHttp,\n config.repository,\n renovateUserUuid,\n utils.prInfo({ ...updatedPrRes, ...(state && { state }) }),\n );\n}\n\nexport async function mergePr({\n branchName,\n id: prNo,\n strategy: mergeStrategy,\n}: MergePRConfig): Promise<boolean> {\n logger.debug(`mergePr(${prNo}, ${branchName}, ${mergeStrategy})`);\n\n // Bitbucket Cloud does not support a rebase-alike; https://jira.atlassian.com/browse/BCLOUD-16610\n if (mergeStrategy === 'rebase') {\n logger.warn('Bitbucket Cloud does not support a \"rebase\" strategy.');\n return false;\n }\n\n try {\n await bitbucketHttp.postJson(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}/merge`,\n {\n body: mergeBodyTransformer(mergeStrategy),\n },\n );\n logger.debug('Automerging succeeded');\n } catch (err) /* v8 ignore next -- defensive: merge failures are logged and mapped to false, not simulated in specs */ {\n logger.debug({ err }, `PR merge error`);\n logger.info({ pr: prNo }, 'PR automerge failed');\n return false;\n }\n return true;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["promises.map","hostRules.find","git.getUrl","git.initRepo","utils.prInfo","reopenComments","comments.reopenComments","comments.REOPEN_PR_COMMENT_KEYWORD","utils.buildStates","comments.ensureComment","comments.ensureCommentRemoval"],"sources":["../../../../lib/modules/platform/bitbucket/index.ts"],"sourcesContent":["import { isNonEmptyArray, isNonEmptyString } from '@sindresorhus/is';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { REPOSITORY_NOT_FOUND } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { getInheritedOrGlobal, parseJson } from '../../../util/common.ts';\nimport * as git from '../../../util/git/index.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport type { BitbucketHttpOptions } from '../../../util/http/bitbucket.ts';\nimport { BitbucketHttp, setBaseUrl } from '../../../util/http/bitbucket.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport {\n aggressiveRepoCacheProvider,\n repoCacheProvider,\n} from '../../../util/http/cache/repository-http-cache-provider.ts';\nimport {\n isBadRequest,\n isForbidden,\n isNotFound,\n} from '../../../util/http/status.ts';\nimport type { HttpOptions } from '../../../util/http/types.ts';\nimport * as promises from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { UUIDRegex, matchRegexOrGlobList } from '../../../util/string-match.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n EnsureIssueResult,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformResult,\n Pr,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport * as comments from './comments.ts';\nimport { getRepoFile } from './files.ts';\nimport { BitbucketPrCache } from './pr-cache.ts';\nimport {\n RepoInfo,\n Repositories,\n UnresolvedPrTasks,\n WorkspaceAccesses,\n} from './schema.ts';\nimport type {\n Account,\n BitbucketStatus,\n BranchResponse,\n Config,\n EffectiveReviewer,\n PagedResult,\n PrResponse,\n RepoBranchingModel,\n} from './types.ts';\nimport * as utils from './utils.ts';\nimport { mergeBodyTransformer } from './utils.ts';\n\nexport const id = 'bitbucket';\n\nconst bitbucketHttp = new BitbucketHttp();\n\nconst BITBUCKET_PROD_ENDPOINT = 'https://api.bitbucket.org/';\n\nlet config: Config = {} as any;\n\nexport function resetPlatform(): void {\n config = {} as any;\n renovateUserUuid = null;\n}\n\nconst defaults = { endpoint: BITBUCKET_PROD_ENDPOINT };\n\nconst pathSeparator = '/';\n\nlet renovateUserUuid: string | null = null;\n\nexport async function initPlatform({\n endpoint,\n username,\n password,\n token,\n}: PlatformParams): Promise<PlatformResult> {\n if (!(username && password) && !token) {\n throw new Error(\n 'Init: You must configure either a Bitbucket token or username and password',\n );\n }\n if (endpoint && endpoint !== BITBUCKET_PROD_ENDPOINT) {\n logger.warn(\n { endpoint, defaultEndpoint: BITBUCKET_PROD_ENDPOINT },\n 'Init: Bitbucket Cloud endpoint should generally be the default but is being configured to a different value. Did you mean to use Bitbucket Server?',\n );\n defaults.endpoint = endpoint;\n }\n setBaseUrl(defaults.endpoint);\n renovateUserUuid = null;\n const options: HttpOptions = { memCache: false };\n if (token) {\n options.token = token;\n } else {\n options.username = username;\n options.password = password;\n }\n try {\n const { uuid } = (\n await bitbucketHttp.getJsonUnchecked<Account>('/2.0/user', options)\n ).body;\n renovateUserUuid = uuid;\n } catch (err) {\n if (\n isForbidden(err) &&\n err.body?.error?.detail?.required?.includes('account')\n ) {\n logger.warn(`Bitbucket: missing 'account' scope for password`);\n } else {\n logger.debug({ err }, 'Unknown error fetching Bitbucket user identity');\n }\n }\n // TODO: Add a connection check that endpoint/username/password combination are valid (#9594)\n const platformConfig: PlatformResult = {\n endpoint: endpoint ?? BITBUCKET_PROD_ENDPOINT,\n };\n return Promise.resolve(platformConfig);\n}\n\n// Get all repositories that the user has access to\nexport async function getRepos(config: AutodiscoverConfig): Promise<string[]> {\n logger.debug('Autodiscovering Bitbucket Cloud repositories');\n try {\n // Determine which workspaces to query.\n // If the caller supplied explicit namespaces use them directly;\n // otherwise discover all workspaces the authenticated user belongs to.\n // The old cross-workspace endpoint GET /2.0/repositories?role=contributor\n // was removed by Bitbucket on 2026-03-31 (CHANGE-2770).\n let workspaceSlugs: string[];\n const autodiscoverNamespaces = config.namespaces;\n if (isNonEmptyArray(autodiscoverNamespaces)) {\n logger.debug(\n { autodiscoverNamespaces },\n 'Using configured namespaces as Bitbucket workspaces',\n );\n workspaceSlugs = autodiscoverNamespaces;\n } else {\n logger.debug('Fetching Bitbucket workspaces for the current user');\n const { body: slugs } = await bitbucketHttp.getJson(\n '/2.0/user/workspaces',\n { paginate: true },\n WorkspaceAccesses,\n );\n workspaceSlugs = slugs;\n logger.debug(\n { workspaceSlugs },\n `Found ${workspaceSlugs.length} Bitbucket workspace(s)`,\n );\n }\n\n // Fetch repositories for every workspace in parallel (concurrency-limited).\n const repoArrays = await promises.map(workspaceSlugs, (workspace) =>\n bitbucketHttp\n .getJson(\n `/2.0/repositories/${workspace}`,\n { paginate: true },\n Repositories,\n )\n .then(({ body }) => body),\n );\n\n let repos = repoArrays.flat();\n\n // if autodiscoverProjects is configured, filter the repos list\n const autodiscoverProjects = config.projects;\n if (isNonEmptyArray(autodiscoverProjects)) {\n logger.debug(\n { autodiscoverProjects: config.projects },\n 'Applying autodiscoverProjects filter',\n );\n repos = repos.filter(\n (repo) =>\n repo.projectName &&\n matchRegexOrGlobList(repo.projectName, autodiscoverProjects),\n );\n }\n\n return repos.map(({ owner, name }) => `${owner}/${name}`);\n } catch (err) /* v8 ignore next -- defensive: repo listing failures are logged and rethrown, not simulated in specs */ {\n logger.error({ err }, `bitbucket getRepos error`);\n throw err;\n }\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const repo = repoName ?? config.repository;\n\n let finalBranchOrTag = branchOrTag;\n if (branchOrTag?.includes(pathSeparator)) {\n // Branch name contains slash, so we have to replace branch name with SHA1 of the head commit; otherwise the API will not work.\n finalBranchOrTag = await getBranchCommit(branchOrTag);\n }\n\n return await getRepoFile(bitbucketHttp, repo, fileName, finalBranchOrTag, {\n cacheProvider: repoCacheProvider,\n });\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n // TODO #22198\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\n// Initialize bitbucket by getting base branch and SHA\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(\"${repository}\")`);\n const opts = hostRules.find({\n hostType: 'bitbucket',\n url: defaults.endpoint,\n });\n config = {\n repository,\n ignorePrAuthor: GlobalConfig.get('ignorePrAuthor'),\n } as Config;\n let info: RepoInfo;\n let mainBranch: string;\n try {\n const { body: repoInfo } = await bitbucketHttp.getJson(\n `/2.0/repositories/${repository}`,\n RepoInfo,\n );\n info = repoInfo;\n\n mainBranch = info.mainbranch;\n\n if (getInheritedOrGlobal('bbUseDevelopmentBranch')) {\n logger.debug(\n \"bbUseDevelopmentBranch is true - Checking BitBucket's development branch\",\n );\n const developmentBranch = (\n await bitbucketHttp.getJsonUnchecked<RepoBranchingModel>(\n `/2.0/repositories/${repository}/effective-branching-model`,\n )\n ).body.development?.name;\n\n if (developmentBranch) {\n mainBranch = developmentBranch;\n logger.debug(\n `${developmentBranch} is BitBucket's development branch - using it as default branch`,\n );\n }\n }\n\n config.defaultBranch = mainBranch;\n\n config = {\n ...config,\n owner: info.owner,\n mergeMethod: info.mergeMethod,\n is_private: info.is_private,\n };\n\n logger.debug(`${repository} owner = ${config.owner}`);\n } catch (err) /* v8 ignore next -- initRepo error mapping (404 to not-found) is not mocked in specs */ {\n if (isNotFound(err)) {\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n logger.debug({ err }, 'Unknown Bitbucket initRepo error');\n throw err;\n }\n\n const parsedEndpoint = parseUrl(defaults.endpoint);\n // v8 ignore if: endpoint is a constant\n if (!parsedEndpoint) {\n throw new Error(`Invalid Bitbucket endpoint: ${defaults.endpoint}`);\n }\n const { hostname } = parsedEndpoint;\n\n // Converts API hostnames to their respective HTTP git hosts:\n // `api.bitbucket.org` to `bitbucket.org`\n // `api-staging.<host>` to `staging.<host>`\n // TODO #22198\n const hostnameWithoutApiPrefix =\n regEx(/api[.|-](?<host>.+)/).exec(hostname)?.groups?.host;\n\n let auth = '';\n if (opts.token) {\n auth = `x-token-auth:${opts.token}`;\n } else if (opts.password?.startsWith('ATAT')) {\n auth = `x-bitbucket-api-token-auth:${opts.password}`;\n } else {\n auth = `${opts.username!}:${opts.password!}`;\n }\n\n const url = git.getUrl({\n protocol: 'https',\n auth,\n hostname: hostnameWithoutApiPrefix,\n repository,\n });\n\n await git.initRepo({\n ...config,\n url,\n cloneSubmodules,\n cloneSubmodulesFilter,\n });\n const repoConfig: RepoResult = {\n defaultBranch: mainBranch,\n isFork: info.isFork,\n repoFingerprint: repoFingerprint(info.uuid, defaults.endpoint),\n };\n return repoConfig;\n}\n\n/* v8 ignore next -- covered only through findPr callers, never invoked directly in specs */\nfunction matchesState(state: string, desiredState: string): boolean {\n if (desiredState === 'all') {\n return true;\n }\n if (desiredState.startsWith('!')) {\n return state !== desiredState.substring(1);\n }\n return state === desiredState;\n}\n\nexport async function getPrList(): Promise<Pr[]> {\n logger.trace('getPrList()');\n return await BitbucketPrCache.getPrs(\n bitbucketHttp,\n config.repository,\n renovateUserUuid,\n );\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n includeOtherAuthors,\n}: FindPRConfig): Promise<Pr | null> {\n logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`);\n\n if (includeOtherAuthors) {\n // PR might have been created by anyone, so don't use the cached Renovate PR list\n const prs = (\n await bitbucketHttp.getJsonUnchecked<PagedResult<PrResponse>>(\n `/2.0/repositories/${config.repository}/pullrequests?q=source.branch.name=\"${branchName}\"&state=open`,\n { cacheProvider: memCacheProvider },\n )\n ).body.values;\n\n if (prs.length === 0) {\n logger.debug(`No PR found for branch ${branchName}`);\n return null;\n }\n\n return utils.prInfo(prs[0]);\n }\n\n const prList = await getPrList();\n const pr = prList.find((p) => {\n if (p.sourceBranch !== branchName || !matchesState(p.state, state)) {\n return false;\n }\n return !prTitle || p.title.toUpperCase() === prTitle.toUpperCase();\n });\n\n if (!pr) {\n return null;\n }\n logger.debug(`Found PR #${pr.number}`);\n\n /**\n * Bitbucket doesn't support renaming or reopening declined PRs.\n * Instead, we have to use comment-driven signals.\n */\n if (pr.state === 'closed') {\n const reopenComments = await comments.reopenComments(config, pr.number);\n\n if (isNonEmptyArray(reopenComments)) {\n if (config.is_private) {\n // Only workspace members could have commented on a private repository\n logger.debug(\n `Found '${comments.REOPEN_PR_COMMENT_KEYWORD}' comment from workspace member. Renovate will reopen PR ${pr.number} as a new PR`,\n );\n return null;\n }\n\n for (const comment of reopenComments) {\n if (await isAccountMemberOfWorkspace(comment.user, config.repository)) {\n logger.debug(\n `Found '${comments.REOPEN_PR_COMMENT_KEYWORD}' comment from workspace member. Renovate will reopen PR ${pr.number} as a new PR`,\n );\n return null;\n }\n }\n }\n }\n\n return pr;\n}\n\n// Gets details for a PR\nexport async function getPr(prNo: number): Promise<Pr | null> {\n const pr = (\n await bitbucketHttp.getJsonUnchecked<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n )\n ).body;\n\n /* v8 ignore next -- defensive: the PR endpoint returns a body or throws, never an empty body */\n if (!pr) {\n return null;\n }\n\n const res: Pr = {\n ...utils.prInfo(pr),\n };\n\n if (isNonEmptyArray(pr.reviewers)) {\n res.reviewers = pr.reviewers\n .map(({ uuid }) => uuid)\n .filter(isNonEmptyString);\n }\n\n return res;\n}\n\nfunction escapeHash(input: string): string {\n return input?.replace(regEx(/#/g), '%23');\n}\n\n// Return the commit SHA for a branch\nasync function getBranchCommit(\n branchName: string,\n): Promise<string | undefined> {\n try {\n const branch = (\n await bitbucketHttp.getJsonUnchecked<BranchResponse>(\n `/2.0/repositories/${config.repository}/refs/branches/${escapeHash(\n branchName,\n )}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n )\n ).body;\n return branch.target.hash;\n } catch (err) /* v8 ignore next -- defensive: missing branch is logged and mapped to undefined, not mocked in specs */ {\n logger.debug({ err }, `getBranchCommit('${branchName}') failed'`);\n return undefined;\n }\n}\n\n// Returns the Pull Request for a branch. Null if not exists.\nexport async function getBranchPr(branchName: string): Promise<Pr | null> {\n logger.debug(`getBranchPr(${branchName})`);\n const existingPr = await findPr({\n branchName,\n state: 'open',\n });\n return existingPr ? getPr(existingPr.number) : null;\n}\n\nasync function getStatus(\n branchName: string,\n memCache = true,\n): Promise<BitbucketStatus[]> {\n const sha = await getBranchCommit(branchName);\n const opts: BitbucketHttpOptions = { paginate: true };\n /* v8 ignore next: temporary code */\n if (memCache) {\n opts.cacheProvider = aggressiveRepoCacheProvider;\n } else {\n opts.memCache = false;\n }\n return (\n await bitbucketHttp.getJsonUnchecked<PagedResult<BitbucketStatus>>(\n `/2.0/repositories/${config.repository}/commit/${sha!}/statuses`,\n opts,\n )\n ).body.values;\n}\n// Returns the combined status for a branch.\nexport async function getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n const statuses = await getStatus(branchName);\n logger.debug({ branch: branchName, statuses }, 'branch status check result');\n if (!statuses.length) {\n logger.debug('empty branch status check result = returning \"pending\"');\n return 'yellow';\n }\n const noOfFailures = statuses.filter(\n (status: { state: string }) =>\n status.state === 'FAILED' || status.state === 'STOPPED',\n ).length;\n if (noOfFailures) {\n return 'red';\n }\n const noOfPending = statuses.filter(\n (status: { state: string }) => status.state === 'INPROGRESS',\n ).length;\n if (noOfPending) {\n return 'yellow';\n }\n if (\n !internalChecksAsSuccess &&\n statuses.every((status) => {\n const isInternal = status.key?.startsWith('renovate/');\n return status.state === 'SUCCESSFUL' && isInternal;\n })\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n return 'green';\n}\n\nconst bbToRenovateStatusMapping: Record<string, BranchStatus> = {\n SUCCESSFUL: 'green',\n INPROGRESS: 'yellow',\n FAILED: 'red',\n};\n\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n const statuses = await getStatus(branchName);\n const bbState = statuses.find((status) => status.key === context)?.state;\n // TODO #22198\n return bbToRenovateStatusMapping[bbState!] || null;\n}\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n const sha = await getBranchCommit(branchName);\n\n // TargetUrl can not be empty so default to bitbucket\n /* v8 ignore next -- specs always pass a targetUrl, fallback exists for direct API constraints */\n const url = targetUrl ?? 'https://bitbucket.org';\n\n const body = {\n name: context,\n state: utils.buildStates[state],\n key: context,\n description,\n url,\n };\n\n await bitbucketHttp.postJson(\n `/2.0/repositories/${config.repository}/commit/${sha}/statuses/build`,\n { body },\n );\n\n // invalidate status cache\n const branchStatusesUrl = bitbucketHttp\n .resolveUrl(`/2.0/repositories/${config.repository}/commit/${sha}/statuses`)\n .toString();\n aggressiveRepoCacheProvider.markSynced('get', branchStatusesUrl, false);\n}\n\n/**\n * Remove or transform markdown into Bitbucket supported syntax.\n *\n * See https://bitbucket.org/tutorials/markdowndemo/src for supported markdown syntax\n */\nexport function massageMarkdown(input: string): string {\n let massaged = smartTruncate(input, maxBodyLength())\n .replace(\n 'you tick the rebase/retry checkbox',\n 'by renaming this PR to start with \"rebase!\"',\n )\n .replace(\n 'checking the rebase/retry box above',\n 'renaming the PR to start with \"rebase!\"',\n )\n .replace(\n regEx(\n /<details>\\n(?:<summary>View abandoned dependencies.*<\\/summary>\\n\\n)(?<body>[\\s\\S]*?)<\\/details>/,\n ),\n '$<body>',\n )\n .replace(regEx(`\\n---\\n\\n.*?<!-- rebase-check -->.*?\\n`), '')\n .replace(regEx(/\\]\\(\\.\\.\\/issues\\//g), '](../../issues/')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](../../pull-requests/')\n .replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), '');\n\n massaged = massageDetailSummaryHtmlToNestedLists(massaged);\n\n return massageCodeblockMarkdown(massaged);\n}\n\n/**\n * Massage codeblocks indentation to ensure correct rendering in Bitbucket.\n */\nfunction massageCodeblockMarkdown(body: string): string {\n const codeBlockRegex = regEx(\n /^(?<indent>[ \\t]*)```(?<lang>\\w*)[^\\n]*\\n(?<code>[\\s\\S]*?)\\n[ \\t]*```/gm,\n );\n let codeMatch;\n let result = body;\n\n while ((codeMatch = codeBlockRegex.exec(body)) !== null) {\n const { indent, lang, code } = codeMatch.groups!;\n const indentLength = indent.length;\n const lines = code.split('\\n');\n const cleanedLines = lines.map((line) =>\n // Remove `indentLength` characters from the start of each line\n line.slice(indentLength),\n );\n\n const cleaned = cleanedLines.join('\\n');\n const replacement = `\\`\\`\\`${lang}\\n${cleaned}\\n\\`\\`\\``;\n\n result = result.replace(codeMatch[0], replacement);\n }\n\n return result;\n}\n\n/**\n * Massage collapsible html sections into nested unordered lists.\n *\n * Bitbucket doesn't currently support collapsible syntax; https://jira.atlassian.com/browse/BCLOUD-20231\n */\nfunction massageDetailSummaryHtmlToNestedLists(body: string): string {\n let depth = 0;\n // Parse detail parts to calculate correct list depth\n const detailsParts = body.split('<details>').map((raw) => {\n const partDepth = depth;\n\n depth += 1;\n const countClosingDetailsTags = raw.split('</details>').length - 1;\n depth = Math.max(0, depth - countClosingDetailsTags);\n\n return { raw, partDepth };\n });\n\n // Reassemble parts while replacing collapsible html elements with markdown list\n return detailsParts\n .map(({ raw, partDepth }) => {\n let t = raw;\n\n if (partDepth === 0) {\n return t;\n }\n\n const partIndentation = '\\t'.repeat(partDepth - 1);\n const nestedListItemIndentation = '\\t'.repeat(partDepth);\n\n const rawContainsBlockquote = raw.includes('<blockquote>');\n\n t = t.replace(regEx(/<\\/?summary>/g), partDepth === 1 ? '**' : '`');\n\n if (partDepth > 1) {\n t = t.replace(\n regEx(/^(?<prefix>[ \\t]*- [`[])/gm),\n `${nestedListItemIndentation}$<prefix>`,\n );\n }\n\n let result = partIndentation;\n if (rawContainsBlockquote || partDepth > 1) {\n result += ' - ';\n }\n result += t;\n\n return result;\n })\n .join('')\n .replace(regEx(/<\\/?(?:summary|details|blockquote)>/g), '');\n}\n\nexport function maxBodyLength(): number {\n return 250000;\n}\n\nfunction logIssuesRemoved(): void {\n logger.once.debug(\n 'Bitbucket Cloud has removed its issue tracker, so Renovate features which rely on issues, like the Dependency Dashboard, do not work. See https://developer.atlassian.com/cloud/bitbucket/changelog/#CHANGE-3071',\n );\n}\n\nexport function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n logIssuesRemoved();\n return Promise.resolve(null);\n}\n\nexport function ensureIssue({\n title,\n}: EnsureIssueConfig): Promise<EnsureIssueResult | null> {\n logger.once.warn({ title }, 'Cannot ensure issue');\n logIssuesRemoved();\n return Promise.resolve(null);\n}\n\nexport function getIssueList(): Promise<Issue[]> {\n logger.debug(`getIssueList()`);\n logIssuesRemoved();\n return Promise.resolve([]);\n}\n\nexport function ensureIssueClosing(title: string): Promise<void> {\n logger.debug(`ensureIssueClosing(${title})`);\n logIssuesRemoved();\n return Promise.resolve();\n}\n\nexport function addAssignees(\n _prNr: number,\n _assignees: string[],\n): Promise<void> {\n // Bitbucket supports \"participants\" and \"reviewers\" so does not seem to have the concept of \"assignee\"\n logger.warn('Cannot add assignees');\n return Promise.resolve();\n}\n\nexport async function addReviewers(\n prId: number,\n reviewers: string[],\n): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${prId}`);\n\n // TODO #22198\n const { title } = (await getPr(prId))!;\n\n const body = {\n title,\n reviewers: reviewers.map((username: string) => {\n const isUUID =\n username.startsWith('{') &&\n username.endsWith('}') &&\n UUIDRegex.test(username.slice(1, -1));\n const key = isUUID ? 'uuid' : 'username';\n return {\n [key]: username,\n };\n }),\n };\n\n await bitbucketHttp.putJson(\n `/2.0/repositories/${config.repository}/pullrequests/${prId}`,\n {\n body,\n },\n );\n}\n\n/* v8 ignore next -- stub: Bitbucket Cloud has no PR labels, callers never reach this */\nexport function deleteLabel(): never {\n throw new Error('deleteLabel not implemented');\n}\n\nexport function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n // https://developer.atlassian.com/bitbucket/api/2/reference/search?q=pullrequest+comment\n return comments.ensureComment({\n config,\n number,\n topic,\n content: sanitize(content),\n });\n}\n\nexport function ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n return comments.ensureCommentRemoval(config, deleteConfig);\n}\n\nasync function sanitizeReviewers(\n reviewers: Account[],\n err: any,\n): Promise<Account[] | undefined> {\n if (isBadRequest(err) && err.body?.error?.fields?.reviewers) {\n const sanitizedReviewers: Account[] = [];\n\n const MSG_AUTHOR_AND_REVIEWER =\n 'is the author and cannot be included as a reviewer.';\n const MSG_MALFORMED_REVIEWERS_LIST = 'Malformed reviewers list';\n const MSG_NOT_WORKSPACE_MEMBER =\n 'is not a member of this workspace and cannot be added to this pull request';\n\n for (const msg of err.body.error.fields.reviewers) {\n // Bitbucket returns a 400 if any of the PR reviewer accounts are now inactive (ie: disabled/suspended)\n if (msg === MSG_MALFORMED_REVIEWERS_LIST) {\n logger.debug(\n { err },\n 'PR contains reviewers that may be either inactive or no longer a member of this workspace. Will try setting only active reviewers',\n );\n\n // Validate that each previous PR reviewer account is still active\n for (const reviewer of reviewers) {\n const reviewerUser = (\n await bitbucketHttp.getJsonUnchecked<Account>(\n `/2.0/users/${reviewer.uuid}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n )\n ).body;\n\n // There are cases where an active user may still not be a member of a workspace\n if (\n reviewerUser.account_status === 'active' &&\n (await isAccountMemberOfWorkspace(reviewer, config.repository))\n ) {\n sanitizedReviewers.push(reviewer);\n }\n }\n // Bitbucket returns a 400 if any of the PR reviewer accounts are no longer members of this workspace\n } else if (msg.endsWith(MSG_NOT_WORKSPACE_MEMBER)) {\n logger.debug(\n { err },\n 'PR contains reviewer accounts which are no longer member of this workspace. Will try setting only member reviewers',\n );\n\n // Validate that each previous PR reviewer account is still a member of this workspace\n for (const reviewer of reviewers) {\n if (await isAccountMemberOfWorkspace(reviewer, config.repository)) {\n sanitizedReviewers.push(reviewer);\n }\n }\n } else if (msg.endsWith(MSG_AUTHOR_AND_REVIEWER)) {\n logger.debug(\n { err },\n 'PR contains reviewer accounts which are also the author. Will try setting only non-author reviewers',\n );\n const author = msg.replace(MSG_AUTHOR_AND_REVIEWER, '').trim();\n for (const reviewer of reviewers) {\n if (reviewer.display_name !== author) {\n sanitizedReviewers.push(reviewer);\n }\n }\n } else {\n return undefined;\n }\n }\n\n return sanitizedReviewers;\n }\n\n return undefined;\n}\n\nasync function isAccountMemberOfWorkspace(\n reviewer: Account,\n repository: string,\n): Promise<boolean> {\n const workspace = repository.split('/')[0];\n\n try {\n await bitbucketHttp.get(\n `/2.0/workspaces/${workspace}/members/${reviewer.uuid}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n );\n\n return true;\n } catch (err) {\n // HTTP 404: User cannot be found, or the user is not a member of this workspace.\n if (isNotFound(err)) {\n logger.debug(\n { err },\n `User ${reviewer.display_name} is not a member of the workspace ${workspace}. Will be removed from the PR`,\n );\n\n return false;\n }\n throw err;\n }\n}\n\n// Creates PR and returns PR number\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle: title,\n prBody: description,\n draftPR = false,\n platformPrOptions,\n}: CreatePRConfig): Promise<Pr> {\n // labels is not supported in Bitbucket: https://bitbucket.org/site/master/issues/11976/ability-to-add-labels-to-pull-requests-bb\n\n const base = targetBranch;\n\n logger.debug({ repository: config.repository, title, base }, 'Creating PR');\n\n let reviewers: Account[] = [];\n\n if (platformPrOptions?.bbUseDefaultReviewers) {\n const reviewersResponse = (\n await bitbucketHttp.getJsonUnchecked<PagedResult<EffectiveReviewer>>(\n `/2.0/repositories/${config.repository}/effective-default-reviewers`,\n {\n paginate: true,\n cacheProvider: aggressiveRepoCacheProvider,\n },\n )\n ).body;\n reviewers = reviewersResponse.values.map((reviewer: EffectiveReviewer) => ({\n uuid: reviewer.user.uuid,\n display_name: reviewer.user.display_name,\n }));\n }\n\n const body = {\n title,\n description: sanitize(description),\n source: {\n branch: {\n name: sourceBranch,\n },\n },\n destination: {\n branch: {\n name: base,\n },\n },\n close_source_branch: true,\n reviewers,\n draft: draftPR,\n };\n\n try {\n const prRes = (\n await bitbucketHttp.postJson<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests`,\n {\n body,\n },\n )\n ).body;\n const pr = utils.prInfo(prRes);\n await BitbucketPrCache.setPr(\n bitbucketHttp,\n config.repository,\n renovateUserUuid,\n pr,\n );\n if (platformPrOptions?.bbAutoResolvePrTasks) {\n await autoResolvePrTasks(pr);\n }\n return pr;\n } catch (err) /* v8 ignore next -- reviewer-sanitizing retry path depends on API error shapes not mocked in specs */ {\n // Try sanitizing reviewers\n const sanitizedReviewers = await sanitizeReviewers(reviewers, err);\n\n if (sanitizedReviewers === undefined) {\n logger.warn({ err }, 'Error creating pull request');\n throw err;\n } else {\n const prRes = (\n await bitbucketHttp.postJson<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests`,\n {\n body: {\n ...body,\n reviewers: sanitizedReviewers,\n },\n },\n )\n ).body;\n const pr = utils.prInfo(prRes);\n await BitbucketPrCache.setPr(\n bitbucketHttp,\n config.repository,\n renovateUserUuid,\n pr,\n );\n if (platformPrOptions?.bbAutoResolvePrTasks) {\n await autoResolvePrTasks(pr);\n }\n return pr;\n }\n }\n}\n\nasync function autoResolvePrTasks(pr: Pr): Promise<void> {\n logger.debug(`Auto resolve PR tasks in #${pr.number}`);\n try {\n const unResolvedTasks = (\n await bitbucketHttp.getJson(\n `/2.0/repositories/${config.repository}/pullrequests/${pr.number}/tasks`,\n { paginate: true, pagelen: 100 },\n UnresolvedPrTasks,\n )\n ).body;\n\n logger.trace(\n {\n prId: pr.number,\n listTaskRes: unResolvedTasks,\n },\n 'List PR tasks',\n );\n\n for (const task of unResolvedTasks) {\n const res = await bitbucketHttp.putJson(\n `/2.0/repositories/${config.repository}/pullrequests/${pr.number}/tasks/${task.id}`,\n {\n body: {\n state: 'RESOLVED',\n content: {\n raw: task.content.raw,\n },\n },\n },\n );\n logger.trace(\n {\n prId: pr.number,\n updateTaskResponse: res,\n },\n 'Put PR tasks - mark resolved',\n );\n }\n } catch (err) {\n logger.warn({ prId: pr.number, err }, 'Error resolving PR tasks');\n }\n}\n\nexport async function updatePr({\n number: prNo,\n prTitle: title,\n prBody: description,\n state,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prNo}, ${title}, body)`);\n // Updating a PR in Bitbucket will clear the reviewers if reviewers is not present\n const pr = (\n await bitbucketHttp.getJsonUnchecked<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}`,\n )\n ).body;\n\n let updatedPrRes: PrResponse;\n try {\n const body: any = {\n title,\n description: sanitize(description),\n reviewers: pr.reviewers,\n };\n if (targetBranch) {\n body.destination = {\n branch: {\n name: targetBranch,\n },\n };\n }\n\n updatedPrRes = (\n await bitbucketHttp.putJson<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}`,\n { body },\n )\n ).body;\n } catch (err) {\n // Try sanitizing reviewers\n const sanitizedReviewers = await sanitizeReviewers(pr.reviewers, err);\n\n if (sanitizedReviewers === undefined) {\n throw err;\n } else {\n updatedPrRes = (\n await bitbucketHttp.putJson<PrResponse>(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}`,\n {\n body: {\n title,\n description: sanitize(description),\n reviewers: sanitizedReviewers,\n },\n },\n )\n ).body;\n }\n }\n\n if (state === 'closed' && pr) {\n await bitbucketHttp.postJson(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}/decline`,\n );\n }\n\n // update pr cache\n await BitbucketPrCache.setPr(\n bitbucketHttp,\n config.repository,\n renovateUserUuid,\n utils.prInfo({ ...updatedPrRes, ...(state && { state }) }),\n );\n}\n\nexport async function mergePr({\n branchName,\n id: prNo,\n strategy: mergeStrategy,\n}: MergePRConfig): Promise<boolean> {\n logger.debug(`mergePr(${prNo}, ${branchName}, ${mergeStrategy})`);\n\n // Bitbucket Cloud does not support a rebase-alike; https://jira.atlassian.com/browse/BCLOUD-16610\n if (mergeStrategy === 'rebase') {\n logger.warn('Bitbucket Cloud does not support a \"rebase\" strategy.');\n return false;\n }\n\n try {\n await bitbucketHttp.postJson(\n `/2.0/repositories/${config.repository}/pullrequests/${prNo}/merge`,\n {\n body: mergeBodyTransformer(mergeStrategy),\n },\n );\n logger.debug('Automerging succeeded');\n } catch (err) /* v8 ignore next -- defensive: merge failures are logged and mapped to false, not simulated in specs */ {\n logger.debug({ err }, `PR merge error`);\n logger.info({ pr: prNo }, 'PR automerge failed');\n return false;\n }\n return true;\n}\n"],"mappings":"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"}