renovate 43.263.0 → 43.263.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/dist/config/app-strings.js +1 -1
  2. package/dist/config/app-strings.js.map +1 -1
  3. package/dist/config/decrypt/bcpgp.js +7 -4
  4. package/dist/config/decrypt/bcpgp.js.map +1 -1
  5. package/dist/config/migration.js +4 -6
  6. package/dist/config/migration.js.map +1 -1
  7. package/dist/config/options/index.js +1 -1
  8. package/dist/config/options/index.js.map +1 -1
  9. package/dist/config/validation-helpers/match-base-branches.js +4 -6
  10. package/dist/config/validation-helpers/match-base-branches.js.map +1 -1
  11. package/dist/config/validation-helpers/regex-glob-matchers.js +4 -6
  12. package/dist/config/validation-helpers/regex-glob-matchers.js.map +1 -1
  13. package/dist/config/validation-helpers/utils.js +2 -4
  14. package/dist/config/validation-helpers/utils.js.map +1 -1
  15. package/dist/config/validation.js +4 -6
  16. package/dist/config/validation.js.map +1 -1
  17. package/dist/config-validator.js +1 -3
  18. package/dist/config-validator.js.map +1 -1
  19. package/dist/global-config-option-defaults.generated.js +1 -1
  20. package/dist/global-config-option-defaults.generated.js.map +1 -1
  21. package/dist/modules/datasource/artifactory/index.js +6 -8
  22. package/dist/modules/datasource/artifactory/index.js.map +1 -1
  23. package/dist/modules/datasource/aws-machine-image/index.js +1 -2
  24. package/dist/modules/datasource/aws-machine-image/index.js.map +1 -1
  25. package/dist/modules/datasource/azure-pipelines-tasks/index.js +2 -3
  26. package/dist/modules/datasource/azure-pipelines-tasks/index.js.map +1 -1
  27. package/dist/modules/datasource/conda/index.js +1 -3
  28. package/dist/modules/datasource/conda/index.js.map +1 -1
  29. package/dist/modules/datasource/dart-version/index.js +1 -2
  30. package/dist/modules/datasource/dart-version/index.js.map +1 -1
  31. package/dist/modules/datasource/datasource.js +1 -3
  32. package/dist/modules/datasource/datasource.js.map +1 -1
  33. package/dist/modules/datasource/devbox/index.js +1 -3
  34. package/dist/modules/datasource/devbox/index.js.map +1 -1
  35. package/dist/modules/datasource/docker/ecr.js +2 -1
  36. package/dist/modules/datasource/docker/ecr.js.map +1 -1
  37. package/dist/modules/datasource/docker/index.js +1 -1
  38. package/dist/modules/datasource/docker/index.js.map +1 -1
  39. package/dist/modules/datasource/galaxy-collection/index.js +1 -1
  40. package/dist/modules/datasource/galaxy-collection/index.js.map +1 -1
  41. package/dist/modules/datasource/go/releases-goproxy.js +2 -2
  42. package/dist/modules/datasource/go/releases-goproxy.js.map +1 -1
  43. package/dist/modules/datasource/java-version/index.js +1 -3
  44. package/dist/modules/datasource/java-version/index.js.map +1 -1
  45. package/dist/modules/datasource/maven/util.js +2 -1
  46. package/dist/modules/datasource/maven/util.js.map +1 -1
  47. package/dist/modules/datasource/nuget/common.js +6 -4
  48. package/dist/modules/datasource/nuget/common.js.map +1 -1
  49. package/dist/modules/datasource/util.js +3 -2
  50. package/dist/modules/datasource/util.js.map +1 -1
  51. package/dist/modules/manager/azure-pipelines/extract.js +1 -1
  52. package/dist/modules/manager/azure-pipelines/extract.js.map +1 -1
  53. package/dist/modules/manager/bazel/extract.js +1 -3
  54. package/dist/modules/manager/bazel/extract.js.map +1 -1
  55. package/dist/modules/manager/bazel/parser.js +1 -1
  56. package/dist/modules/manager/bazel/parser.js.map +1 -1
  57. package/dist/modules/manager/buildpacks/extract.js +1 -1
  58. package/dist/modules/manager/buildpacks/extract.js.map +1 -1
  59. package/dist/modules/manager/bundler/common.js +23 -25
  60. package/dist/modules/manager/bundler/common.js.map +1 -1
  61. package/dist/modules/manager/bundler/extract.js +2 -6
  62. package/dist/modules/manager/bundler/extract.js.map +1 -1
  63. package/dist/modules/manager/cargo/extract.js +4 -6
  64. package/dist/modules/manager/cargo/extract.js.map +1 -1
  65. package/dist/modules/manager/dockerfile/extract.js +3 -3
  66. package/dist/modules/manager/dockerfile/extract.js.map +1 -1
  67. package/dist/modules/manager/fingerprint.generated.js +13 -13
  68. package/dist/modules/manager/fingerprint.generated.js.map +1 -1
  69. package/dist/modules/manager/flux/extract.js +2 -1
  70. package/dist/modules/manager/flux/extract.js.map +1 -1
  71. package/dist/modules/manager/github-actions/parse.js +1 -1
  72. package/dist/modules/manager/github-actions/parse.js.map +1 -1
  73. package/dist/modules/manager/gradle/extract/catalog.js +4 -3
  74. package/dist/modules/manager/gradle/extract/catalog.js.map +1 -1
  75. package/dist/modules/manager/gradle/extract.js +2 -2
  76. package/dist/modules/manager/gradle/extract.js.map +1 -1
  77. package/dist/modules/manager/gradle/parser/common.js +1 -1
  78. package/dist/modules/manager/gradle/parser/common.js.map +1 -1
  79. package/dist/modules/manager/gradle/parser/handlers.js +1 -1
  80. package/dist/modules/manager/gradle/parser/handlers.js.map +1 -1
  81. package/dist/modules/manager/helm-values/extract.js.map +1 -1
  82. package/dist/modules/manager/helmfile/extract.js +1 -1
  83. package/dist/modules/manager/helmfile/extract.js.map +1 -1
  84. package/dist/modules/manager/maven/extract.js.map +1 -1
  85. package/dist/modules/manager/maven/update.js +2 -1
  86. package/dist/modules/manager/maven/update.js.map +1 -1
  87. package/dist/modules/manager/mise/utils.js +5 -7
  88. package/dist/modules/manager/mise/utils.js.map +1 -1
  89. package/dist/modules/manager/mix/extract.js +3 -6
  90. package/dist/modules/manager/mix/extract.js.map +1 -1
  91. package/dist/modules/manager/npm/extract/common/overrides.js +1 -1
  92. package/dist/modules/manager/npm/extract/common/overrides.js.map +1 -1
  93. package/dist/modules/manager/npm/extract/yarn.js +1 -1
  94. package/dist/modules/manager/npm/extract/yarn.js.map +1 -1
  95. package/dist/modules/manager/npm/npmrc.js +1 -3
  96. package/dist/modules/manager/npm/npmrc.js.map +1 -1
  97. package/dist/modules/manager/npm/update/dependency/common.js +2 -3
  98. package/dist/modules/manager/npm/update/dependency/common.js.map +1 -1
  99. package/dist/modules/manager/npm/update/dependency/index.js +1 -1
  100. package/dist/modules/manager/npm/update/dependency/index.js.map +1 -1
  101. package/dist/modules/manager/npm/update/dependency/pnpm.js +1 -1
  102. package/dist/modules/manager/npm/update/dependency/pnpm.js.map +1 -1
  103. package/dist/modules/manager/npm/update/dependency/yarn.js +1 -1
  104. package/dist/modules/manager/npm/update/dependency/yarn.js.map +1 -1
  105. package/dist/modules/manager/osgi/extract.js +1 -1
  106. package/dist/modules/manager/osgi/extract.js.map +1 -1
  107. package/dist/modules/manager/pep621/processors/uv.js +1 -1
  108. package/dist/modules/manager/pep621/processors/uv.js.map +1 -1
  109. package/dist/modules/manager/pep621/schema.js.map +1 -1
  110. package/dist/modules/manager/pip_setup/extract.js +1 -1
  111. package/dist/modules/manager/pip_setup/extract.js.map +1 -1
  112. package/dist/modules/manager/pipenv/artifacts.js.map +1 -1
  113. package/dist/modules/manager/poetry/schema.js +2 -2
  114. package/dist/modules/manager/poetry/schema.js.map +1 -1
  115. package/dist/modules/manager/pub/artifacts.js +4 -6
  116. package/dist/modules/manager/pub/artifacts.js.map +1 -1
  117. package/dist/modules/manager/pub/utils.js +2 -2
  118. package/dist/modules/manager/pub/utils.js.map +1 -1
  119. package/dist/modules/manager/puppet/common.js +4 -6
  120. package/dist/modules/manager/puppet/common.js.map +1 -1
  121. package/dist/modules/manager/sbt/extract.js +1 -1
  122. package/dist/modules/manager/sbt/extract.js.map +1 -1
  123. package/dist/modules/manager/sbt/util.js +4 -2
  124. package/dist/modules/manager/sbt/util.js.map +1 -1
  125. package/dist/modules/manager/terraform/lockfile/util.js +1 -1
  126. package/dist/modules/manager/terraform/lockfile/util.js.map +1 -1
  127. package/dist/modules/platform/azure/index.js +15 -19
  128. package/dist/modules/platform/azure/index.js.map +1 -1
  129. package/dist/modules/platform/azure/issue.js +67 -17
  130. package/dist/modules/platform/azure/issue.js.map +1 -1
  131. package/dist/modules/platform/bitbucket/index.js +1 -3
  132. package/dist/modules/platform/bitbucket/index.js.map +1 -1
  133. package/dist/modules/platform/forgejo/index.js +5 -3
  134. package/dist/modules/platform/forgejo/index.js.map +1 -1
  135. package/dist/modules/platform/forgejo/utils.js +1 -1
  136. package/dist/modules/platform/forgejo/utils.js.map +1 -1
  137. package/dist/modules/platform/gerrit/scm.js +5 -7
  138. package/dist/modules/platform/gerrit/scm.js.map +1 -1
  139. package/dist/modules/platform/gitea/index.js +5 -3
  140. package/dist/modules/platform/gitea/index.js.map +1 -1
  141. package/dist/modules/platform/gitea/utils.js +1 -1
  142. package/dist/modules/platform/gitea/utils.js.map +1 -1
  143. package/dist/modules/platform/github/index.js +5 -7
  144. package/dist/modules/platform/github/index.js.map +1 -1
  145. package/dist/modules/platform/github/pr.js +1 -1
  146. package/dist/modules/platform/github/pr.js.map +1 -1
  147. package/dist/modules/platform/gitlab/index.js +2 -1
  148. package/dist/modules/platform/gitlab/index.js.map +1 -1
  149. package/dist/modules/platform/utils/pr-body.js +2 -1
  150. package/dist/modules/platform/utils/pr-body.js.map +1 -1
  151. package/dist/modules/versioning/apk/index.js +3 -3
  152. package/dist/modules/versioning/apk/index.js.map +1 -1
  153. package/dist/modules/versioning/composer/index.js +4 -7
  154. package/dist/modules/versioning/composer/index.js.map +1 -1
  155. package/dist/modules/versioning/conan/common.js +4 -6
  156. package/dist/modules/versioning/conan/common.js.map +1 -1
  157. package/dist/modules/versioning/conan/index.js +1 -3
  158. package/dist/modules/versioning/conan/index.js.map +1 -1
  159. package/dist/modules/versioning/conan/range.js +4 -5
  160. package/dist/modules/versioning/conan/range.js.map +1 -1
  161. package/dist/modules/versioning/conda/index.js +1 -1
  162. package/dist/modules/versioning/conda/index.js.map +1 -1
  163. package/dist/modules/versioning/gradle/index.js +7 -3
  164. package/dist/modules/versioning/gradle/index.js.map +1 -1
  165. package/dist/modules/versioning/hermit/index.js +2 -2
  166. package/dist/modules/versioning/hermit/index.js.map +1 -1
  167. package/dist/modules/versioning/ivy/index.js +1 -1
  168. package/dist/modules/versioning/ivy/index.js.map +1 -1
  169. package/dist/modules/versioning/maven/compare.js +4 -6
  170. package/dist/modules/versioning/maven/compare.js.map +1 -1
  171. package/dist/modules/versioning/npm/range.js +5 -7
  172. package/dist/modules/versioning/npm/range.js.map +1 -1
  173. package/dist/modules/versioning/nuget/version.js +6 -6
  174. package/dist/modules/versioning/nuget/version.js.map +1 -1
  175. package/dist/modules/versioning/pep440/index.js +1 -1
  176. package/dist/modules/versioning/pep440/index.js.map +1 -1
  177. package/dist/modules/versioning/pep440/range.js +2 -6
  178. package/dist/modules/versioning/pep440/range.js.map +1 -1
  179. package/dist/modules/versioning/poetry/index.js +1 -1
  180. package/dist/modules/versioning/poetry/index.js.map +1 -1
  181. package/dist/modules/versioning/pvp/index.js +2 -2
  182. package/dist/modules/versioning/pvp/index.js.map +1 -1
  183. package/dist/modules/versioning/rpm/index.js +4 -3
  184. package/dist/modules/versioning/rpm/index.js.map +1 -1
  185. package/dist/modules/versioning/ruby/range.js +2 -2
  186. package/dist/modules/versioning/ruby/range.js.map +1 -1
  187. package/dist/modules/versioning/ruby/strategies/bump.js +1 -1
  188. package/dist/modules/versioning/ruby/strategies/bump.js.map +1 -1
  189. package/dist/modules/versioning/ruby/strategies/replace.js +13 -12
  190. package/dist/modules/versioning/ruby/strategies/replace.js.map +1 -1
  191. package/dist/modules/versioning/ruby/version.js +1 -1
  192. package/dist/modules/versioning/ruby/version.js.map +1 -1
  193. package/dist/modules/versioning/rust-release-channel/index.js +1 -1
  194. package/dist/modules/versioning/rust-release-channel/index.js.map +1 -1
  195. package/dist/modules/versioning/rust-release-channel/util.js +4 -4
  196. package/dist/modules/versioning/rust-release-channel/util.js.map +1 -1
  197. package/dist/util/common.js +1 -3
  198. package/dist/util/common.js.map +1 -1
  199. package/dist/util/exec/common.js +4 -6
  200. package/dist/util/exec/common.js.map +1 -1
  201. package/dist/util/exec/containerbase.js +1 -3
  202. package/dist/util/exec/containerbase.js.map +1 -1
  203. package/dist/util/git/instrument.js +3 -3
  204. package/dist/util/git/instrument.js.map +1 -1
  205. package/dist/util/github/graphql/datasource-fetcher.js +5 -4
  206. package/dist/util/github/graphql/datasource-fetcher.js.map +1 -1
  207. package/dist/util/http/cache/package-http-cache-provider.js.map +1 -1
  208. package/dist/util/http/github.js +3 -2
  209. package/dist/util/http/github.js.map +1 -1
  210. package/dist/util/http/http.d.ts +1 -1
  211. package/dist/util/http/http.js.map +1 -1
  212. package/dist/util/result.d.ts +8 -8
  213. package/dist/util/result.js +1 -1
  214. package/dist/util/result.js.map +1 -1
  215. package/dist/util/url.js +2 -2
  216. package/dist/util/url.js.map +1 -1
  217. package/dist/workers/global/config/parse/cli.js +18 -20
  218. package/dist/workers/global/config/parse/cli.js.map +1 -1
  219. package/dist/workers/global/config/parse/env.js +3 -5
  220. package/dist/workers/global/config/parse/env.js.map +1 -1
  221. package/dist/workers/repository/config-migration/branch/index.js +3 -5
  222. package/dist/workers/repository/config-migration/branch/index.js.map +1 -1
  223. package/dist/workers/repository/init/merge.js +2 -3
  224. package/dist/workers/repository/init/merge.js.map +1 -1
  225. package/dist/workers/repository/onboarding/branch/check.js +7 -9
  226. package/dist/workers/repository/onboarding/branch/check.js.map +1 -1
  227. package/dist/workers/repository/onboarding/branch/index.js +4 -8
  228. package/dist/workers/repository/onboarding/branch/index.js.map +1 -1
  229. package/dist/workers/repository/onboarding/branch/onboarding-branch-cache.js +2 -2
  230. package/dist/workers/repository/onboarding/branch/onboarding-branch-cache.js.map +1 -1
  231. package/dist/workers/repository/process/extract-update.js.map +1 -1
  232. package/dist/workers/repository/process/fetch.js.map +1 -1
  233. package/dist/workers/repository/process/libyear.js +1 -3
  234. package/dist/workers/repository/process/libyear.js.map +1 -1
  235. package/dist/workers/repository/process/lookup/filter-checks.js +9 -11
  236. package/dist/workers/repository/process/lookup/filter-checks.js.map +1 -1
  237. package/dist/workers/repository/process/lookup/index.js +5 -8
  238. package/dist/workers/repository/process/lookup/index.js.map +1 -1
  239. package/dist/workers/repository/process/vulnerabilities.js +3 -3
  240. package/dist/workers/repository/process/vulnerabilities.js.map +1 -1
  241. package/dist/workers/repository/reconfigure/index.js +3 -5
  242. package/dist/workers/repository/reconfigure/index.js.map +1 -1
  243. package/dist/workers/repository/update/branch/bump-versions.js +1 -1
  244. package/dist/workers/repository/update/branch/bump-versions.js.map +1 -1
  245. package/dist/workers/repository/update/branch/get-updated.js +3 -5
  246. package/dist/workers/repository/update/branch/get-updated.js.map +1 -1
  247. package/dist/workers/repository/update/pr/body/updates-table.js +1 -3
  248. package/dist/workers/repository/update/pr/body/updates-table.js.map +1 -1
  249. package/dist/workers/repository/update/pr/changelog/common.js +1 -1
  250. package/dist/workers/repository/update/pr/changelog/common.js.map +1 -1
  251. package/dist/workers/repository/update/pr/index.js +6 -7
  252. package/dist/workers/repository/update/pr/index.js.map +1 -1
  253. package/dist/workers/repository/updates/flatten.js +1 -1
  254. package/dist/workers/repository/updates/flatten.js.map +1 -1
  255. package/dist/workers/repository/updates/generate.js +1 -1
  256. package/dist/workers/repository/updates/generate.js.map +1 -1
  257. package/package.json +2 -2
  258. package/renovate-schema.json +2 -2
@@ -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 { readOnlyIssueBody } from '../utils/read-only-issue-body.ts';\nimport * as comments from './comments.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 `Init: Bitbucket Cloud endpoint should generally be ${BITBUCKET_PROD_ENDPOINT} 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 */ {\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 // See: https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/src/%7Bcommit%7D/%7Bpath%7D\n const repo = repoName ?? config.repository;\n const path = fileName;\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 const url = `/2.0/repositories/${repo}/src/${finalBranchOrTag ?? `HEAD`}/${path}`;\n const res = await bitbucketHttp.getText(url, {\n cacheProvider: repoCacheProvider,\n });\n return res.body;\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 // Fetch Bitbucket development branch\n const developmentBranch = (\n await bitbucketHttp.getJsonUnchecked<RepoBranchingModel>(\n `/2.0/repositories/${repository}/branching-model`,\n )\n ).body.development?.branch?.name;\n\n if (developmentBranch) {\n mainBranch = developmentBranch;\n }\n }\n\n config.defaultBranch = mainBranch;\n\n config = {\n ...config,\n owner: info.owner,\n mergeMethod: info.mergeMethod,\n has_issues: info.has_issues,\n is_private: info.is_private,\n };\n\n logger.debug(`${repository} owner = ${config.owner}`);\n } catch (err) /* v8 ignore next */ {\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 = regEx(/api[.|-](.+)/).exec(hostname)?.[1];\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 */\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 */\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\nconst escapeHash = (input: string): string =>\n input?.replace(regEx(/#/g), '%23');\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 */ {\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 */\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\ninterface BbIssue {\n id: number;\n title: string;\n kind: string;\n content?: { raw: string };\n}\n\nasync function findOpenIssues(title: string): Promise<BbIssue[]> {\n try {\n const filters = [\n `title=${JSON.stringify(title)}`,\n '(state = \"new\" OR state = \"open\")',\n ];\n if (renovateUserUuid) {\n filters.push(`reporter.uuid=\"${renovateUserUuid}\"`);\n }\n const filter = encodeURIComponent(filters.join(' AND '));\n // v8 ignore next -- TODO: add test #40625\n return (\n (\n await bitbucketHttp.getJsonUnchecked<{ values: BbIssue[] }>(\n `/2.0/repositories/${config.repository}/issues?q=${filter}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n )\n ).body.values || []\n );\n } catch (err) /* v8 ignore next */ {\n logger.warn({ err }, 'Error finding issues');\n return [];\n }\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n\n /* v8 ignore next */\n if (!config.has_issues) {\n logger.debug('Issues are disabled - cannot findIssue');\n return null;\n }\n const issues = await findOpenIssues(title);\n if (!issues.length) {\n return null;\n }\n const [issue] = issues;\n return {\n number: issue.id,\n body: issue.content?.raw,\n };\n}\n\nasync function closeIssue(issueNumber: number): Promise<void> {\n await bitbucketHttp.putJson(\n `/2.0/repositories/${config.repository}/issues/${issueNumber}`,\n {\n body: { state: 'closed' },\n },\n );\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 */\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)([\\s\\S]*?)<\\/details>/,\n ),\n '$2',\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(/^([ \\t]*- [`[])/gm),\n `${nestedListItemIndentation}$1`,\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(/<\\/?(summary|details|blockquote)>/g, '');\n}\n\nexport function maxBodyLength(): number {\n return 250000;\n}\n\nexport async function ensureIssue({\n title,\n reuseTitle,\n body,\n}: EnsureIssueConfig): Promise<EnsureIssueResult | null> {\n logger.debug(`ensureIssue()`);\n /* v8 ignore next */\n if (!config.has_issues) {\n logger.debug('Issues are disabled - cannot ensureIssue');\n logger.debug(`Failed to ensure Issue with title:${title}`);\n return null;\n }\n try {\n let issues = await findOpenIssues(title);\n const description = massageMarkdown(sanitize(body));\n const issueKind = 'task';\n\n if (!issues.length && reuseTitle) {\n issues = await findOpenIssues(reuseTitle);\n }\n if (issues.length) {\n // Close any duplicates\n for (const issue of issues.slice(1)) {\n await closeIssue(issue.id);\n }\n const [issue] = issues;\n\n if (\n issue.title !== title ||\n String(issue.content?.raw).trim() !== description.trim() ||\n issue.kind !== issueKind\n ) {\n logger.debug('Issue updated');\n await bitbucketHttp.putJson(\n `/2.0/repositories/${config.repository}/issues/${issue.id}`,\n {\n body: {\n kind: issueKind,\n content: {\n raw: readOnlyIssueBody(description),\n markup: 'markdown',\n },\n },\n },\n );\n return 'updated';\n }\n } else {\n logger.info('Issue created');\n await bitbucketHttp.postJson(\n `/2.0/repositories/${config.repository}/issues`,\n {\n body: {\n title,\n kind: issueKind,\n content: {\n raw: readOnlyIssueBody(description),\n markup: 'markdown',\n },\n },\n },\n );\n return 'created';\n }\n } catch (err) /* v8 ignore next */ {\n if (err.message.startsWith('Repository has no issue tracker.')) {\n logger.debug(`Issues are disabled, so could not create issue: ${title}`);\n } else {\n logger.warn({ err }, 'Could not ensure issue');\n }\n }\n return null;\n}\n\n/* v8 ignore next */\nexport async function getIssueList(): Promise<Issue[]> {\n logger.debug(`getIssueList()`);\n\n if (!config.has_issues) {\n logger.debug('Issues are disabled - cannot getIssueList');\n return [];\n }\n try {\n const filters = ['(state = \"new\" OR state = \"open\")'];\n if (renovateUserUuid) {\n filters.push(`reporter.uuid=\"${renovateUserUuid}\"`);\n }\n const filter = encodeURIComponent(filters.join(' AND '));\n const url = `/2.0/repositories/${config.repository}/issues?q=${filter}`;\n const res = await bitbucketHttp.getJsonUnchecked<{ values: Issue[] }>(url, {\n cacheProvider: repoCacheProvider,\n });\n return res.body.values || [];\n } catch (err) {\n logger.warn({ err }, 'Error finding issues');\n return [];\n }\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n /* v8 ignore next */\n if (!config.has_issues) {\n logger.debug('Issues are disabled - cannot ensureIssueClosing');\n return;\n }\n const issues = await findOpenIssues(title);\n for (const issue of issues) {\n await closeIssue(issue.id);\n }\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 */\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 if (reviewerUser.account_status === 'active') {\n // There are cases where an active user may still not be a member of a workspace\n if (await isAccountMemberOfWorkspace(reviewer, config.repository)) {\n sanitizedReviewers.push(reviewer);\n }\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 */ {\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 */ {\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 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 { readOnlyIssueBody } from '../utils/read-only-issue-body.ts';\nimport * as comments from './comments.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 `Init: Bitbucket Cloud endpoint should generally be ${BITBUCKET_PROD_ENDPOINT} 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 */ {\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 // See: https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/src/%7Bcommit%7D/%7Bpath%7D\n const repo = repoName ?? config.repository;\n const path = fileName;\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 const url = `/2.0/repositories/${repo}/src/${finalBranchOrTag ?? `HEAD`}/${path}`;\n const res = await bitbucketHttp.getText(url, {\n cacheProvider: repoCacheProvider,\n });\n return res.body;\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 // Fetch Bitbucket development branch\n const developmentBranch = (\n await bitbucketHttp.getJsonUnchecked<RepoBranchingModel>(\n `/2.0/repositories/${repository}/branching-model`,\n )\n ).body.development?.branch?.name;\n\n if (developmentBranch) {\n mainBranch = developmentBranch;\n }\n }\n\n config.defaultBranch = mainBranch;\n\n config = {\n ...config,\n owner: info.owner,\n mergeMethod: info.mergeMethod,\n has_issues: info.has_issues,\n is_private: info.is_private,\n };\n\n logger.debug(`${repository} owner = ${config.owner}`);\n } catch (err) /* v8 ignore next */ {\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 = regEx(/api[.|-](.+)/).exec(hostname)?.[1];\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 */\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 */\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\nconst escapeHash = (input: string): string =>\n input?.replace(regEx(/#/g), '%23');\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 */ {\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 */\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\ninterface BbIssue {\n id: number;\n title: string;\n kind: string;\n content?: { raw: string };\n}\n\nasync function findOpenIssues(title: string): Promise<BbIssue[]> {\n try {\n const filters = [\n `title=${JSON.stringify(title)}`,\n '(state = \"new\" OR state = \"open\")',\n ];\n if (renovateUserUuid) {\n filters.push(`reporter.uuid=\"${renovateUserUuid}\"`);\n }\n const filter = encodeURIComponent(filters.join(' AND '));\n // v8 ignore next -- TODO: add test #40625\n return (\n (\n await bitbucketHttp.getJsonUnchecked<{ values: BbIssue[] }>(\n `/2.0/repositories/${config.repository}/issues?q=${filter}`,\n { cacheProvider: aggressiveRepoCacheProvider },\n )\n ).body.values || []\n );\n } catch (err) /* v8 ignore next */ {\n logger.warn({ err }, 'Error finding issues');\n return [];\n }\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n\n /* v8 ignore next */\n if (!config.has_issues) {\n logger.debug('Issues are disabled - cannot findIssue');\n return null;\n }\n const issues = await findOpenIssues(title);\n if (!issues.length) {\n return null;\n }\n const [issue] = issues;\n return {\n number: issue.id,\n body: issue.content?.raw,\n };\n}\n\nasync function closeIssue(issueNumber: number): Promise<void> {\n await bitbucketHttp.putJson(\n `/2.0/repositories/${config.repository}/issues/${issueNumber}`,\n {\n body: { state: 'closed' },\n },\n );\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 */\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)([\\s\\S]*?)<\\/details>/,\n ),\n '$2',\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(/^([ \\t]*- [`[])/gm),\n `${nestedListItemIndentation}$1`,\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(/<\\/?(summary|details|blockquote)>/g, '');\n}\n\nexport function maxBodyLength(): number {\n return 250000;\n}\n\nexport async function ensureIssue({\n title,\n reuseTitle,\n body,\n}: EnsureIssueConfig): Promise<EnsureIssueResult | null> {\n logger.debug(`ensureIssue()`);\n /* v8 ignore next */\n if (!config.has_issues) {\n logger.debug('Issues are disabled - cannot ensureIssue');\n logger.debug(`Failed to ensure Issue with title:${title}`);\n return null;\n }\n try {\n let issues = await findOpenIssues(title);\n const description = massageMarkdown(sanitize(body));\n const issueKind = 'task';\n\n if (!issues.length && reuseTitle) {\n issues = await findOpenIssues(reuseTitle);\n }\n if (issues.length) {\n // Close any duplicates\n for (const issue of issues.slice(1)) {\n await closeIssue(issue.id);\n }\n const [issue] = issues;\n\n if (\n issue.title !== title ||\n String(issue.content?.raw).trim() !== description.trim() ||\n issue.kind !== issueKind\n ) {\n logger.debug('Issue updated');\n await bitbucketHttp.putJson(\n `/2.0/repositories/${config.repository}/issues/${issue.id}`,\n {\n body: {\n kind: issueKind,\n content: {\n raw: readOnlyIssueBody(description),\n markup: 'markdown',\n },\n },\n },\n );\n return 'updated';\n }\n } else {\n logger.info('Issue created');\n await bitbucketHttp.postJson(\n `/2.0/repositories/${config.repository}/issues`,\n {\n body: {\n title,\n kind: issueKind,\n content: {\n raw: readOnlyIssueBody(description),\n markup: 'markdown',\n },\n },\n },\n );\n return 'created';\n }\n } catch (err) /* v8 ignore next */ {\n if (err.message.startsWith('Repository has no issue tracker.')) {\n logger.debug(`Issues are disabled, so could not create issue: ${title}`);\n } else {\n logger.warn({ err }, 'Could not ensure issue');\n }\n }\n return null;\n}\n\n/* v8 ignore next */\nexport async function getIssueList(): Promise<Issue[]> {\n logger.debug(`getIssueList()`);\n\n if (!config.has_issues) {\n logger.debug('Issues are disabled - cannot getIssueList');\n return [];\n }\n try {\n const filters = ['(state = \"new\" OR state = \"open\")'];\n if (renovateUserUuid) {\n filters.push(`reporter.uuid=\"${renovateUserUuid}\"`);\n }\n const filter = encodeURIComponent(filters.join(' AND '));\n const url = `/2.0/repositories/${config.repository}/issues?q=${filter}`;\n const res = await bitbucketHttp.getJsonUnchecked<{ values: Issue[] }>(url, {\n cacheProvider: repoCacheProvider,\n });\n return res.body.values || [];\n } catch (err) {\n logger.warn({ err }, 'Error finding issues');\n return [];\n }\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n /* v8 ignore next */\n if (!config.has_issues) {\n logger.debug('Issues are disabled - cannot ensureIssueClosing');\n return;\n }\n const issues = await findOpenIssues(title);\n for (const issue of issues) {\n await closeIssue(issue.id);\n }\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 */\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 */ {\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 */ {\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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"}
@@ -238,12 +238,14 @@ const platform = {
238
238
  order: config.order
239
239
  };
240
240
  }), fetchRepositories)).flat());
241
- } else if (config?.namespaces) {
241
+ }
242
+ if (config?.namespaces) {
242
243
  logger.debug({ namespaces: config.namespaces }, "Auto-discovering by organization");
243
244
  return deduplicateArray((await map(config.namespaces, async (organization) => {
244
245
  return (await orgListRepos(organization)).filter((r) => !r.mirror && !r.archived).map((r) => r.full_name);
245
246
  })).flat());
246
- } else return await fetchRepositories({
247
+ }
248
+ return await fetchRepositories({
247
249
  sort: config?.sort,
248
250
  order: config?.order
249
251
  });
@@ -463,7 +465,7 @@ const platform = {
463
465
  return null;
464
466
  }
465
467
  if (shouldReOpen) logger.debug("Reopening previously closed Issue");
466
- activeIssue = issues[issues.length - 1];
468
+ activeIssue = issues.at(-1);
467
469
  }
468
470
  for (const issue of issues) if (issue.state === "open" && issue.number !== activeIssue.number) {
469
471
  logger.warn({ issueNo: issue.number }, "Closing duplicate issue");
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["helper\n .getRepoLabels","helper\n .getOrgLabels","helper.searchRepos","helper.getCurrentUser","helper.getVersion","helper.getRepoContents","helper.getRepo","helper.isOrg","git.initRepo","helper.orgListRepos","git.getBranchCommit","helper.createCommitStatus","helper.renovateToForgejoStatusMapping","helper.getCombinedCommitStatus","helper.forgejoToRenovateStatusMapping","helper.getPR","helper.getPRByBranch","helper.createPR","helper.mergePR","helper.updatePR","helper\n .searchIssues","helper.getIssue","helper.closeIssue","helper.updateIssue","helper.updateIssueLabels","helper.createIssue","helper.unassignLabel","helper.getComments","helper.createComment","helper.updateComment","helper.deleteComment","helper.requestPrReviewers"],"sources":["../../../../lib/modules/platform/forgejo/index.ts"],"sourcesContent":["import { isNumber, isString } from '@sindresorhus/is';\nimport semver from 'semver';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n REPOSITORY_ACCESS_FORBIDDEN,\n REPOSITORY_ARCHIVED,\n REPOSITORY_BLOCKED,\n REPOSITORY_CHANGED,\n REPOSITORY_EMPTY,\n REPOSITORY_MIRRORED,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { deduplicateArray } from '../../../util/array.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { setBaseUrl } from '../../../util/http/forgejo.ts';\nimport { map } from '../../../util/promises.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { getPrBodyStruct, hashBody } from '../pr-body.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n FindPRConfig,\n Issue,\n MergePRConfig,\n Platform,\n PlatformParams,\n PlatformResult,\n Pr,\n RepoParams,\n RepoResult,\n RepoSortMethod,\n SortMethod,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport * as helper from './forgejo-helper.ts';\nimport { forgejoHttp } from './forgejo-helper.ts';\nimport { ForgejoPrCache } from './pr-cache.ts';\nimport type { Comment, Label, PRMergeMethod, Repo } from './schema.ts';\nimport type { CombinedCommitStatus, PRUpdateParams } from './types.ts';\nimport {\n DRAFT_PREFIX,\n getMergeMethod,\n getRepoUrl,\n isAllowed,\n smartLinks,\n toRenovatePR,\n trimTrailingApiPath,\n usableRepo,\n} from './utils.ts';\n\ninterface ForgejoRepoConfig {\n ignorePrAuthor: boolean;\n repository: string;\n mergeMethod: PRMergeMethod;\n\n issueList: Promise<Issue[]> | null;\n labelList: Promise<Label[]> | null;\n defaultBranch: string;\n cloneSubmodules: boolean;\n cloneSubmodulesFilter: string[] | undefined;\n hasIssuesEnabled: boolean;\n isOrgRepo: boolean;\n orgName: string;\n}\n\nexport const id = 'forgejo';\n\nconst defaults = {\n hostType: 'forgejo',\n endpoint: 'https://code.forgejo.org/',\n version: '0.0.0',\n};\n\nlet config: ForgejoRepoConfig = {} as any;\nlet botUserID: number;\nlet botUserName: string;\n\nexport function resetPlatform(): void {\n config = {} as any;\n botUserID = undefined as never;\n botUserName = undefined as never;\n defaults.hostType = 'forgejo';\n defaults.endpoint = 'https://code.forgejo.org/';\n defaults.version = '0.0.0';\n setBaseUrl(defaults.endpoint);\n}\n\nfunction toRenovateIssue(data: Issue): Issue {\n return {\n number: data.number,\n state: data.state,\n title: data.title,\n body: data.body,\n };\n}\n\nfunction matchesState(actual: string, expected: string): boolean {\n if (expected === 'all') {\n return true;\n }\n if (expected.startsWith('!')) {\n return actual !== expected.substring(1);\n }\n\n return actual === expected;\n}\n\nfunction findCommentByTopic(\n comments: Comment[],\n topic: string,\n): Comment | null {\n return comments.find((c) => c.body.startsWith(`### ${topic}\\n\\n`)) ?? null;\n}\n\nfunction findCommentByContent(\n comments: Comment[],\n content: string,\n): Comment | null {\n return comments.find((c) => c.body.trim() === content) ?? null;\n}\n\nfunction getLabelList(): Promise<Label[]> {\n if (config.labelList === null) {\n const repoLabels = helper\n .getRepoLabels(config.repository, {\n memCache: false,\n })\n .then((labels) => {\n logger.debug(`Retrieved ${labels.length} repo labels`);\n return labels;\n });\n\n const orgLabels = config.isOrgRepo\n ? helper\n .getOrgLabels(config.orgName, {\n memCache: false,\n })\n .then((labels) => {\n logger.debug(`Retrieved ${labels.length} org labels`);\n return labels;\n })\n .catch((err) => {\n // Will fail if owner of repo is not org\n logger.debug({ err }, `Unable to fetch organization labels`);\n return [] as Label[];\n })\n : Promise.resolve([]);\n\n config.labelList = Promise.all([repoLabels, orgLabels]).then((labels) =>\n ([] as Label[]).concat(...labels),\n );\n }\n\n return config.labelList;\n}\n\nasync function lookupLabelByName(name: string): Promise<number | null> {\n logger.debug(`lookupLabelByName(${name})`);\n const labelList = await getLabelList();\n return labelList.find((l) => l.name === name)?.id ?? null;\n}\n\ninterface FetchRepositoriesArgs {\n topic?: string;\n sort?: RepoSortMethod;\n order?: SortMethod;\n}\n\nasync function fetchRepositories({\n topic,\n sort,\n order,\n}: FetchRepositoriesArgs): Promise<string[]> {\n const repos = await helper.searchRepos({\n uid: botUserID,\n archived: false,\n ...(topic && {\n topic: true,\n q: topic,\n }),\n ...(sort && {\n sort,\n }),\n ...(order && {\n order,\n }),\n });\n return repos.filter(usableRepo).map((r) => r.full_name);\n}\n\nconst platform: Platform = {\n async initPlatform({\n endpoint,\n token,\n }: PlatformParams): Promise<PlatformResult> {\n if (!token) {\n throw new Error(\n 'Init: You must configure a Forgejo personal access token',\n );\n }\n\n if (endpoint) {\n let baseEndpoint = trimTrailingApiPath(endpoint);\n baseEndpoint = ensureTrailingSlash(baseEndpoint);\n defaults.endpoint = baseEndpoint;\n } else {\n logger.debug(`Using default Forgejo endpoint: ${defaults.endpoint}`);\n }\n setBaseUrl(defaults.endpoint);\n\n let gitAuthor: string;\n try {\n const user = await helper.getCurrentUser({ token });\n // oxlint-disable-next-line typescript/prefer-nullish-coalescing -- `full_name` can be emtpy string\n gitAuthor = `${user.full_name || user.login} <${user.email}>`;\n botUserID = user.id;\n botUserName = user.login;\n const env = getEnv();\n /* v8 ignore if: experimental feature */\n if (semver.valid(env.RENOVATE_X_PLATFORM_VERSION)) {\n defaults.version = env.RENOVATE_X_PLATFORM_VERSION!;\n } else {\n defaults.version = await helper.getVersion({ token });\n }\n\n logger.debug(`Forgejo version: ${defaults.version}`);\n } catch (err) {\n logger.debug(\n { err },\n 'Error authenticating with Forgejo. Check your token',\n );\n throw new Error('Init: Authentication failure');\n }\n\n return {\n endpoint: defaults.endpoint,\n gitAuthor,\n };\n },\n\n async getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n ): Promise<string | null> {\n const repo = repoName ?? config.repository;\n const contents = await helper.getRepoContents(repo, fileName, branchOrTag);\n if (contents.type !== 'file') {\n return null;\n }\n return contents.contentString ?? null;\n },\n\n async getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n ): Promise<any> {\n // TODO #22198\n const raw = await platform.getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n },\n\n async initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n gitUrl,\n }: RepoParams): Promise<RepoResult> {\n let repo: Repo;\n\n config = {} as any;\n config.repository = repository;\n config.cloneSubmodules = !!cloneSubmodules;\n config.cloneSubmodulesFilter = cloneSubmodulesFilter;\n config.ignorePrAuthor = GlobalConfig.get('ignorePrAuthor');\n\n // Try to fetch information about repository\n try {\n repo = await helper.getRepo(repository);\n } catch (err) {\n logger.debug({ err }, 'Unknown Forgejo initRepo error');\n throw err;\n }\n\n // Ensure appropriate repository state and permissions\n if (repo.archived) {\n logger.debug('Repository is archived - aborting renovation');\n throw new Error(REPOSITORY_ARCHIVED);\n }\n if (repo.mirror) {\n logger.debug('Repository is a mirror - aborting renovation');\n throw new Error(REPOSITORY_MIRRORED);\n }\n if (!repo.permissions.pull || !repo.permissions.push) {\n logger.debug(\n 'Repository does not permit pull or push - aborting renovation',\n );\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n if (repo.empty) {\n logger.debug('Repository is empty - aborting renovation');\n throw new Error(REPOSITORY_EMPTY);\n }\n\n if (repo.has_pull_requests === false) {\n logger.debug('Repo has disabled pull requests - aborting renovation');\n throw new Error(REPOSITORY_BLOCKED);\n }\n\n // similar to forgejo behaviour- if default merge style is allowed, use this;\n // else fall back to predefined order. Order chosen to minimize commits - see\n // https://github.com/renovatebot/renovate/pull/37768 for discussion.\n const preferredOrder: PRMergeMethod[] = [\n ...(repo.default_merge_style ? [repo.default_merge_style] : []),\n 'fast-forward-only',\n 'squash',\n 'merge',\n 'rebase',\n 'rebase-merge',\n ];\n\n const mergeStyle = preferredOrder.find((style) => isAllowed(style, repo));\n\n if (mergeStyle) {\n config.mergeMethod = mergeStyle;\n } else {\n logger.debug(\n 'Repository has no allowed merge methods - aborting renovation',\n );\n throw new Error(REPOSITORY_BLOCKED);\n }\n\n try {\n config.isOrgRepo = await helper.isOrg(repo.owner.login);\n } catch (err) {\n logger.debug({ err }, 'Forgejo initRepo() error');\n throw err;\n }\n\n // Determine author email and branches\n config.defaultBranch = repo.default_branch;\n logger.debug(`${repository} default branch = ${config.defaultBranch}`);\n\n const url = getRepoUrl(repo, gitUrl, defaults.endpoint);\n\n // Initialize Git storage\n await git.initRepo({\n ...config,\n url,\n });\n\n // Reset cached resources\n config.issueList = null;\n config.labelList = null;\n config.hasIssuesEnabled = !repo.external_tracker && repo.has_issues;\n config.orgName = repo.owner.login;\n\n return {\n defaultBranch: config.defaultBranch,\n isFork: !!repo.fork,\n repoFingerprint: repoFingerprint(repo.id, defaults.endpoint),\n };\n },\n\n async getRepos(config?: AutodiscoverConfig): Promise<string[]> {\n logger.debug('Auto-discovering Forgejo repositories');\n try {\n if (config?.topics) {\n logger.debug({ topics: config.topics }, 'Auto-discovering by topics');\n const fetchRepoArgs: FetchRepositoriesArgs[] = config.topics.map(\n (topic) => {\n return {\n topic,\n sort: config.sort,\n order: config.order,\n };\n },\n );\n const repos = await map(fetchRepoArgs, fetchRepositories);\n return deduplicateArray(repos.flat());\n } else if (config?.namespaces) {\n logger.debug(\n { namespaces: config.namespaces },\n 'Auto-discovering by organization',\n );\n const repos = await map(\n config.namespaces,\n async (organization: string) => {\n const orgRepos = await helper.orgListRepos(organization);\n return orgRepos\n .filter((r) => !r.mirror && !r.archived)\n .map((r) => r.full_name);\n },\n );\n return deduplicateArray(repos.flat());\n } else {\n return await fetchRepositories({\n sort: config?.sort,\n order: config?.order,\n });\n }\n } catch (err) {\n logger.error({ err }, 'Forgejo getRepos() error');\n throw err;\n }\n },\n\n async setBranchStatus({\n branchName,\n context,\n description,\n state,\n url: target_url,\n }: BranchStatusConfig): Promise<void> {\n try {\n // Create new status for branch commit\n const branchCommit = git.getBranchCommit(branchName);\n // TODO: check branchCommit\n\n await helper.createCommitStatus(config.repository, branchCommit!, {\n state: helper.renovateToForgejoStatusMapping[state] || 'pending',\n context,\n description,\n ...(target_url && { target_url }),\n });\n\n // Refresh caches by re-fetching commit status for branch\n await helper.getCombinedCommitStatus(config.repository, branchName, {\n memCache: false,\n });\n } catch (err) {\n logger.warn({ err }, 'Failed to set branch status');\n }\n },\n\n async getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n ): Promise<BranchStatus> {\n let ccs: CombinedCommitStatus;\n try {\n ccs = await helper.getCombinedCommitStatus(config.repository, branchName);\n } catch (err) {\n if (err.statusCode === 404) {\n logger.debug(\n 'Received 404 when checking branch status, assuming branch deletion',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n\n logger.debug('Unknown error when checking branch status');\n throw err;\n }\n\n logger.debug({ ccs }, 'Branch status check result');\n if (\n !internalChecksAsSuccess &&\n ccs.worstStatus === 'success' &&\n ccs.statuses.every((status) => status.context?.startsWith('renovate/'))\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n\n return helper.forgejoToRenovateStatusMapping[ccs.worstStatus];\n },\n\n async getBranchStatusCheck(\n branchName: string,\n context: string,\n ): Promise<BranchStatus | null> {\n const ccs = await helper.getCombinedCommitStatus(\n config.repository,\n branchName,\n );\n const cs = ccs.statuses.find((s) => s.context === context);\n if (!cs) {\n return null;\n } // no status check exists\n return helper.forgejoToRenovateStatusMapping[cs.status];\n },\n\n getPrList(): Promise<Pr[]> {\n return ForgejoPrCache.getPrs(\n forgejoHttp,\n config.repository,\n config.ignorePrAuthor,\n botUserName,\n );\n },\n\n async getPr(number: number): Promise<Pr | null> {\n // Search for pull request in cached list or attempt to query directly\n const prList = await platform.getPrList();\n let pr = prList.find((p) => p.number === number) ?? null;\n if (pr) {\n logger.debug('Returning from cached PRs');\n } else {\n logger.debug('PR not found in cached PRs - trying to fetch directly');\n const gpr = await helper.getPR(config.repository, number);\n pr = toRenovatePR(gpr, botUserName);\n\n // Add pull request to cache for further lookups / queries\n if (pr) {\n await ForgejoPrCache.setPr(\n forgejoHttp,\n config.repository,\n config.ignorePrAuthor,\n botUserName,\n pr,\n );\n }\n }\n\n // Abort and return null if no match was found\n if (!pr) {\n return null;\n }\n\n return pr;\n },\n\n async findPr({\n branchName,\n prTitle: title,\n state = 'all',\n includeOtherAuthors,\n targetBranch,\n }: FindPRConfig): Promise<Pr | null> {\n logger.debug(`findPr(${branchName}, ${title!}, ${state})`);\n if (includeOtherAuthors && isString(targetBranch)) {\n // do not use pr cache as it only fetches prs created by the bot account\n const pr = await helper.getPRByBranch(\n config.repository,\n targetBranch,\n branchName,\n );\n if (!pr) {\n return null;\n }\n\n return toRenovatePR(pr, null);\n }\n const prList = await platform.getPrList();\n const pr = prList.find(\n (p) =>\n p.sourceRepo === config.repository &&\n p.sourceBranch === branchName &&\n matchesState(p.state, state) &&\n (!title || p.title === title),\n );\n\n if (pr) {\n logger.debug(`Found PR #${pr.number}`);\n }\n return pr ?? null;\n },\n\n async createPr({\n sourceBranch,\n targetBranch,\n prTitle,\n prBody: rawBody,\n labels: labelNames,\n platformPrOptions,\n draftPR,\n }: CreatePRConfig): Promise<Pr> {\n let title = prTitle;\n const base = targetBranch;\n const head = sourceBranch;\n const body = sanitize(rawBody);\n if (draftPR) {\n title = DRAFT_PREFIX + title;\n }\n\n logger.debug(`Creating pull request: ${title} (${head} => ${base})`);\n try {\n const labels = Array.isArray(labelNames)\n ? await map(labelNames, lookupLabelByName)\n : [];\n const gpr = await helper.createPR(config.repository, {\n base,\n head,\n title,\n body,\n labels: labels.filter(isNumber),\n });\n\n if (platformPrOptions?.usePlatformAutomerge) {\n // Only Forgejo v10.0.0+ support delete_branch_after_merge.\n // This is required to not have undesired behavior when renovate finds existing branches on next run.\n // Codeberg usees git versioning like `11.0.1-99-c504062+gitea-1.22.0` so allow any version >= 10.0.0-0.\n if (semver.gte(defaults.version, '10.0.0-0')) {\n try {\n await helper.mergePR(config.repository, gpr.number, {\n Do:\n getMergeMethod(platformPrOptions?.automergeStrategy) ??\n config.mergeMethod,\n merge_when_checks_succeed: true,\n delete_branch_after_merge: true,\n });\n\n logger.debug(\n { prNumber: gpr.number },\n 'Forgejo-native automerge: success',\n );\n } catch (err) {\n logger.warn(\n { err, prNumber: gpr.number },\n 'Forgejo-native automerge: fail',\n );\n }\n } else {\n logger.debug(\n { prNumber: gpr.number },\n `Forgejo-native automerge: not supported on this version of Forgejo. Use 10.0.0 or newer.`,\n );\n }\n }\n\n const pr = toRenovatePR(gpr, botUserName);\n if (!pr) {\n throw new Error('Can not parse newly created Pull Request');\n }\n\n await ForgejoPrCache.setPr(\n forgejoHttp,\n config.repository,\n config.ignorePrAuthor,\n botUserName,\n pr,\n );\n return pr;\n } catch (err) {\n // When the user manually deletes a branch from Renovate, the PR remains but is no longer linked to any branch. In\n // the most recent versions of Forgejo, the PR gets automatically closed when that happens, but older versions do\n // not handle this properly and keep the PR open. As pushing a branch with the same name resurrects the PR, this\n // would cause a HTTP 409 conflict error, which we hereby gracefully handle.\n if (err.statusCode === 409) {\n logger.warn(\n { prTitle: title, sourceBranch },\n 'Attempting to gracefully recover from 409 Conflict response in createPr()',\n );\n\n // Refresh cached PR list and search for pull request with matching information\n ForgejoPrCache.forceSync();\n const pr = await platform.findPr({\n branchName: sourceBranch,\n state: 'open',\n });\n\n // If a valid PR was found, return and gracefully recover from the error. Otherwise, abort and throw error.\n // v8 ignore else -- TODO: add test #40625\n if (pr?.bodyStruct) {\n if (pr.title !== title || pr.bodyStruct.hash !== hashBody(body)) {\n logger.debug(\n `Recovered from 409 Conflict, but PR for ${sourceBranch} is outdated. Updating...`,\n );\n await platform.updatePr({\n number: pr.number,\n prTitle: title,\n prBody: body,\n });\n pr.title = title;\n pr.bodyStruct = getPrBodyStruct(body);\n } else {\n logger.debug(\n `Recovered from 409 Conflict and PR for ${sourceBranch} is up-to-date`,\n );\n }\n\n return pr;\n }\n }\n\n throw err;\n }\n },\n\n async updatePr({\n number,\n prTitle,\n prBody: body,\n labels,\n state,\n targetBranch,\n }: UpdatePrConfig): Promise<void> {\n let title = prTitle;\n if ((await getPrList()).find((pr) => pr.number === number)?.isDraft) {\n title = DRAFT_PREFIX + title;\n }\n\n const prUpdateParams: PRUpdateParams = {\n title,\n ...(body && { body }),\n ...(state && { state }),\n };\n if (targetBranch) {\n prUpdateParams.base = targetBranch;\n }\n\n /**\n * Update PR labels.\n * In the Forgejo API, labels are replaced on each update if the field is present.\n * If the field is not present (i.e., undefined), labels aren't updated.\n * However, the labels array must contain label IDs instead of names,\n * so a lookup is performed to fetch the details (including the ID) of each label.\n */\n if (Array.isArray(labels)) {\n prUpdateParams.labels = (await map(labels, lookupLabelByName)).filter(\n isNumber,\n );\n if (labels.length !== prUpdateParams.labels.length) {\n logger.warn(\n 'Some labels could not be looked up. Renovate may halt label updates assuming changes by others.',\n );\n }\n }\n\n const gpr = await helper.updatePR(\n config.repository,\n number,\n prUpdateParams,\n );\n const pr = toRenovatePR(gpr, botUserName);\n if (pr) {\n await ForgejoPrCache.setPr(\n forgejoHttp,\n config.repository,\n config.ignorePrAuthor,\n botUserName,\n pr,\n );\n }\n },\n\n async mergePr({ id, strategy }: MergePRConfig): Promise<boolean> {\n try {\n await helper.mergePR(config.repository, id, {\n Do: getMergeMethod(strategy) ?? config.mergeMethod,\n });\n return true;\n } catch (err) {\n logger.warn({ err, id }, 'Merging of PR failed');\n return false;\n }\n },\n\n getIssueList(): Promise<Issue[]> {\n if (config.hasIssuesEnabled === false) {\n return Promise.resolve([]);\n }\n config.issueList ??= helper\n .searchIssues(config.repository, { state: 'all' }, { memCache: false })\n .then((issues) => {\n const issueList = issues.map(toRenovateIssue);\n logger.debug(`Retrieved ${issueList.length} Issues`);\n return issueList;\n });\n\n return config.issueList;\n },\n\n async getIssue(number: number, memCache = true): Promise<Issue | null> {\n if (config.hasIssuesEnabled === false) {\n return null;\n }\n try {\n const body = (\n await helper.getIssue(config.repository, number, { memCache })\n ).body;\n return {\n number,\n body,\n };\n } catch (err) {\n logger.debug({ err, number }, 'Error getting issue');\n return null;\n }\n },\n\n async findIssue(title: string): Promise<Issue | null> {\n const issueList = await platform.getIssueList();\n const issue = issueList.find(\n (i) => i.state === 'open' && i.title === title,\n );\n\n if (!issue) {\n return null;\n }\n // TODO: types (#22198)\n logger.debug(`Found Issue #${issue.number!}`);\n // TODO #22198\n return getIssue!(issue.number!);\n },\n\n async ensureIssue({\n title,\n reuseTitle,\n body: content,\n labels: labelNames,\n shouldReOpen,\n once,\n }: EnsureIssueConfig): Promise<'updated' | 'created' | null> {\n logger.debug(`ensureIssue(${title})`);\n if (config.hasIssuesEnabled === false) {\n logger.info(\n 'Cannot ensure issue because issues are disabled in this repository',\n );\n return null;\n }\n try {\n const body = smartLinks(content);\n\n const issueList = await platform.getIssueList();\n let issues = issueList.filter((i) => i.title === title);\n if (!issues.length) {\n issues = issueList.filter((i) => i.title === reuseTitle);\n }\n\n const labels = Array.isArray(labelNames)\n ? (await Promise.all(labelNames.map(lookupLabelByName))).filter(\n isNumber,\n )\n : undefined;\n\n // Update any matching issues which currently exist\n if (issues.length) {\n let activeIssue = issues.find((i) => i.state === 'open');\n\n // If no active issue was found, decide if it shall be skipped, re-opened or updated without state change\n if (!activeIssue) {\n if (once) {\n logger.debug('Issue already closed - skipping update');\n return null;\n }\n if (shouldReOpen) {\n logger.debug('Reopening previously closed Issue');\n }\n\n // Pick the last issue in the list as the active one\n activeIssue = issues[issues.length - 1];\n }\n\n // Close any duplicate issues\n for (const issue of issues) {\n if (issue.state === 'open' && issue.number !== activeIssue.number) {\n // TODO: types (#22198)\n logger.warn({ issueNo: issue.number! }, 'Closing duplicate issue');\n // TODO #22198\n await helper.closeIssue(config.repository, issue.number!);\n }\n }\n\n // Check if issue has already correct state\n if (\n activeIssue.title === title &&\n activeIssue.body === body &&\n activeIssue.state === 'open'\n ) {\n logger.debug(\n // TODO: types (#22198)\n `Issue #${activeIssue.number!} is open and up to date - nothing to do`,\n );\n return null;\n }\n\n if (shouldReOpen || activeIssue.state === 'open') {\n // Update issue body and re-open\n logger.debug(`Updating Issue #${activeIssue.number}`);\n const existingIssue = await helper.updateIssue(\n config.repository,\n // TODO #22198\n activeIssue.number!,\n {\n body,\n title,\n state: 'open',\n },\n );\n\n // Test whether the issues need to be updated\n const existingLabelIds = (existingIssue.labels ?? []).map(\n (label) => label.id,\n );\n if (\n labels &&\n (labels.length !== existingLabelIds.length ||\n labels.filter((labelId) => !existingLabelIds.includes(labelId))\n .length !== 0)\n ) {\n await helper.updateIssueLabels(\n config.repository,\n // TODO #22198\n activeIssue.number!,\n {\n labels,\n },\n );\n }\n\n return 'updated';\n }\n }\n\n // Create new issue and reset cache\n const issue = await helper.createIssue(config.repository, {\n body,\n title,\n labels,\n });\n logger.debug(`Created new Issue #${issue.number}`);\n config.issueList = null;\n\n return 'created';\n } catch (err) {\n logger.warn({ err }, 'Could not ensure issue');\n }\n\n return null;\n },\n\n async ensureIssueClosing(title: string): Promise<void> {\n logger.debug(`ensureIssueClosing(${title})`);\n if (config.hasIssuesEnabled === false) {\n return;\n }\n const issueList = await platform.getIssueList();\n for (const issue of issueList) {\n if (issue.state === 'open' && issue.title === title) {\n logger.debug(`Closing issue...issueNo: ${issue.number!}`);\n // TODO #22198\n await helper.closeIssue(config.repository, issue.number!);\n }\n }\n },\n\n async deleteLabel(issue: number, labelName: string): Promise<void> {\n logger.debug(`Deleting label ${labelName} from Issue #${issue}`);\n const label = await lookupLabelByName(labelName);\n if (label) {\n await helper.unassignLabel(config.repository, issue, label);\n } else {\n logger.warn({ issue, labelName }, 'Failed to lookup label for deletion');\n }\n },\n\n async ensureComment({\n number: issue,\n topic,\n content,\n }: EnsureCommentConfig): Promise<boolean> {\n try {\n let body = sanitize(content);\n const commentList = await helper.getComments(config.repository, issue);\n\n // Search comment by either topic or exact body\n let comment: Comment | null = null;\n if (topic) {\n comment = findCommentByTopic(commentList, topic);\n body = `### ${topic}\\n\\n${body}`;\n } else {\n comment = findCommentByContent(commentList, body);\n }\n\n // Create a new comment if no match has been found, otherwise update if necessary\n if (!comment) {\n comment = await helper.createComment(config.repository, issue, body);\n logger.info(\n { repository: config.repository, issue, comment: comment.id },\n 'Comment added',\n );\n } else if (comment.body === body) {\n logger.debug(`Comment #${comment.id} is already up-to-date`);\n } else {\n await helper.updateComment(config.repository, comment.id, body);\n logger.debug(\n { repository: config.repository, issue, comment: comment.id },\n 'Comment updated',\n );\n }\n\n return true;\n } catch (err) {\n logger.warn({ err, issue, subject: topic }, 'Error ensuring comment');\n return false;\n }\n },\n\n async ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n ): Promise<void> {\n const { number: issue } = deleteConfig;\n const key =\n deleteConfig.type === 'by-topic'\n ? deleteConfig.topic\n : deleteConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${issue} is removed`);\n const commentList = await helper.getComments(config.repository, issue);\n\n let comment: Comment | null = null;\n // v8 ignore else -- TODO: add test #40625\n if (deleteConfig.type === 'by-topic') {\n comment = findCommentByTopic(commentList, deleteConfig.topic);\n } else if (deleteConfig.type === 'by-content') {\n const body = sanitize(deleteConfig.content);\n comment = findCommentByContent(commentList, body);\n }\n\n // Abort and do nothing if no matching comment was found\n if (!comment) {\n return;\n }\n\n // Try to delete comment\n try {\n await helper.deleteComment(config.repository, comment.id);\n } catch (err) {\n logger.warn(\n { err, issue, config: deleteConfig },\n 'Error deleting comment',\n );\n }\n },\n\n async getBranchPr(branchName: string): Promise<Pr | null> {\n logger.debug(`getBranchPr(${branchName})`);\n const pr = await platform.findPr({ branchName, state: 'open' });\n return pr ? platform.getPr(pr.number) : null;\n },\n\n async addAssignees(number: number, assignees: string[]): Promise<void> {\n logger.debug(\n `Updating assignees '${assignees?.join(', ')}' on Issue #${number}`,\n );\n await helper.updateIssue(config.repository, number, {\n assignees,\n });\n },\n\n async addReviewers(number: number, reviewers: string[]): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers?.join(', ')}' to #${number}`);\n try {\n const teamReviewers = new Set(\n reviewers\n .filter((r) => r.startsWith('team:'))\n .map((r) => r.substring(5)),\n );\n const userReviewers = new Set(\n reviewers.filter((r) => !r.startsWith('team:')),\n );\n\n await helper.requestPrReviewers(config.repository, number, {\n reviewers: [...userReviewers],\n ...(teamReviewers.size && {\n team_reviewers: [...teamReviewers],\n }),\n });\n } catch (err) {\n logger.warn({ err, number, reviewers }, 'Failed to assign reviewer');\n }\n },\n\n massageMarkdown(prBody: string): string {\n return smartTruncate(smartLinks(prBody), maxBodyLength());\n },\n\n maxBodyLength,\n};\n\nexport function maxBodyLength(): number {\n return 1000000;\n}\n\n/* oxlint-disable typescript/unbound-method */\nexport const {\n addAssignees,\n addReviewers,\n createPr,\n deleteLabel,\n ensureComment,\n ensureCommentRemoval,\n ensureIssue,\n ensureIssueClosing,\n findIssue,\n findPr,\n getBranchPr,\n getBranchStatus,\n getBranchStatusCheck,\n getIssue,\n getRawFile,\n getJsonFile,\n getIssueList,\n getPr,\n massageMarkdown,\n getPrList,\n getRepos,\n initPlatform,\n initRepo,\n mergePr,\n setBranchStatus,\n updatePr,\n} = platform;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["helper\n .getRepoLabels","helper\n .getOrgLabels","helper.searchRepos","helper.getCurrentUser","helper.getVersion","helper.getRepoContents","helper.getRepo","helper.isOrg","git.initRepo","helper.orgListRepos","git.getBranchCommit","helper.createCommitStatus","helper.renovateToForgejoStatusMapping","helper.getCombinedCommitStatus","helper.forgejoToRenovateStatusMapping","helper.getPR","helper.getPRByBranch","helper.createPR","helper.mergePR","helper.updatePR","helper\n .searchIssues","helper.getIssue","helper.closeIssue","helper.updateIssue","helper.updateIssueLabels","helper.createIssue","helper.unassignLabel","helper.getComments","helper.createComment","helper.updateComment","helper.deleteComment","helper.requestPrReviewers"],"sources":["../../../../lib/modules/platform/forgejo/index.ts"],"sourcesContent":["import { isNumber, isString } from '@sindresorhus/is';\nimport semver from 'semver';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n REPOSITORY_ACCESS_FORBIDDEN,\n REPOSITORY_ARCHIVED,\n REPOSITORY_BLOCKED,\n REPOSITORY_CHANGED,\n REPOSITORY_EMPTY,\n REPOSITORY_MIRRORED,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { deduplicateArray } from '../../../util/array.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { setBaseUrl } from '../../../util/http/forgejo.ts';\nimport { map } from '../../../util/promises.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { getPrBodyStruct, hashBody } from '../pr-body.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n FindPRConfig,\n Issue,\n MergePRConfig,\n Platform,\n PlatformParams,\n PlatformResult,\n Pr,\n RepoParams,\n RepoResult,\n RepoSortMethod,\n SortMethod,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport * as helper from './forgejo-helper.ts';\nimport { forgejoHttp } from './forgejo-helper.ts';\nimport { ForgejoPrCache } from './pr-cache.ts';\nimport type { Comment, Label, PRMergeMethod, Repo } from './schema.ts';\nimport type { CombinedCommitStatus, PRUpdateParams } from './types.ts';\nimport {\n DRAFT_PREFIX,\n getMergeMethod,\n getRepoUrl,\n isAllowed,\n smartLinks,\n toRenovatePR,\n trimTrailingApiPath,\n usableRepo,\n} from './utils.ts';\n\ninterface ForgejoRepoConfig {\n ignorePrAuthor: boolean;\n repository: string;\n mergeMethod: PRMergeMethod;\n\n issueList: Promise<Issue[]> | null;\n labelList: Promise<Label[]> | null;\n defaultBranch: string;\n cloneSubmodules: boolean;\n cloneSubmodulesFilter: string[] | undefined;\n hasIssuesEnabled: boolean;\n isOrgRepo: boolean;\n orgName: string;\n}\n\nexport const id = 'forgejo';\n\nconst defaults = {\n hostType: 'forgejo',\n endpoint: 'https://code.forgejo.org/',\n version: '0.0.0',\n};\n\nlet config: ForgejoRepoConfig = {} as any;\nlet botUserID: number;\nlet botUserName: string;\n\nexport function resetPlatform(): void {\n config = {} as any;\n botUserID = undefined as never;\n botUserName = undefined as never;\n defaults.hostType = 'forgejo';\n defaults.endpoint = 'https://code.forgejo.org/';\n defaults.version = '0.0.0';\n setBaseUrl(defaults.endpoint);\n}\n\nfunction toRenovateIssue(data: Issue): Issue {\n return {\n number: data.number,\n state: data.state,\n title: data.title,\n body: data.body,\n };\n}\n\nfunction matchesState(actual: string, expected: string): boolean {\n if (expected === 'all') {\n return true;\n }\n if (expected.startsWith('!')) {\n return actual !== expected.substring(1);\n }\n\n return actual === expected;\n}\n\nfunction findCommentByTopic(\n comments: Comment[],\n topic: string,\n): Comment | null {\n return comments.find((c) => c.body.startsWith(`### ${topic}\\n\\n`)) ?? null;\n}\n\nfunction findCommentByContent(\n comments: Comment[],\n content: string,\n): Comment | null {\n return comments.find((c) => c.body.trim() === content) ?? null;\n}\n\nfunction getLabelList(): Promise<Label[]> {\n if (config.labelList === null) {\n const repoLabels = helper\n .getRepoLabels(config.repository, {\n memCache: false,\n })\n .then((labels) => {\n logger.debug(`Retrieved ${labels.length} repo labels`);\n return labels;\n });\n\n const orgLabels = config.isOrgRepo\n ? helper\n .getOrgLabels(config.orgName, {\n memCache: false,\n })\n .then((labels) => {\n logger.debug(`Retrieved ${labels.length} org labels`);\n return labels;\n })\n .catch((err) => {\n // Will fail if owner of repo is not org\n logger.debug({ err }, `Unable to fetch organization labels`);\n return [] as Label[];\n })\n : Promise.resolve([]);\n\n config.labelList = Promise.all([repoLabels, orgLabels]).then((labels) =>\n ([] as Label[]).concat(...labels),\n );\n }\n\n return config.labelList;\n}\n\nasync function lookupLabelByName(name: string): Promise<number | null> {\n logger.debug(`lookupLabelByName(${name})`);\n const labelList = await getLabelList();\n return labelList.find((l) => l.name === name)?.id ?? null;\n}\n\ninterface FetchRepositoriesArgs {\n topic?: string;\n sort?: RepoSortMethod;\n order?: SortMethod;\n}\n\nasync function fetchRepositories({\n topic,\n sort,\n order,\n}: FetchRepositoriesArgs): Promise<string[]> {\n const repos = await helper.searchRepos({\n uid: botUserID,\n archived: false,\n ...(topic && {\n topic: true,\n q: topic,\n }),\n ...(sort && {\n sort,\n }),\n ...(order && {\n order,\n }),\n });\n return repos.filter(usableRepo).map((r) => r.full_name);\n}\n\nconst platform: Platform = {\n async initPlatform({\n endpoint,\n token,\n }: PlatformParams): Promise<PlatformResult> {\n if (!token) {\n throw new Error(\n 'Init: You must configure a Forgejo personal access token',\n );\n }\n\n if (endpoint) {\n let baseEndpoint = trimTrailingApiPath(endpoint);\n baseEndpoint = ensureTrailingSlash(baseEndpoint);\n defaults.endpoint = baseEndpoint;\n } else {\n logger.debug(`Using default Forgejo endpoint: ${defaults.endpoint}`);\n }\n setBaseUrl(defaults.endpoint);\n\n let gitAuthor: string;\n try {\n const user = await helper.getCurrentUser({ token });\n // oxlint-disable-next-line typescript/prefer-nullish-coalescing -- `full_name` can be emtpy string\n gitAuthor = `${user.full_name || user.login} <${user.email}>`;\n botUserID = user.id;\n botUserName = user.login;\n const env = getEnv();\n /* v8 ignore if: experimental feature */\n if (semver.valid(env.RENOVATE_X_PLATFORM_VERSION)) {\n defaults.version = env.RENOVATE_X_PLATFORM_VERSION!;\n } else {\n defaults.version = await helper.getVersion({ token });\n }\n\n logger.debug(`Forgejo version: ${defaults.version}`);\n } catch (err) {\n logger.debug(\n { err },\n 'Error authenticating with Forgejo. Check your token',\n );\n throw new Error('Init: Authentication failure');\n }\n\n return {\n endpoint: defaults.endpoint,\n gitAuthor,\n };\n },\n\n async getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n ): Promise<string | null> {\n const repo = repoName ?? config.repository;\n const contents = await helper.getRepoContents(repo, fileName, branchOrTag);\n if (contents.type !== 'file') {\n return null;\n }\n return contents.contentString ?? null;\n },\n\n async getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n ): Promise<any> {\n // TODO #22198\n const raw = await platform.getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n },\n\n async initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n gitUrl,\n }: RepoParams): Promise<RepoResult> {\n let repo: Repo;\n\n config = {} as any;\n config.repository = repository;\n config.cloneSubmodules = !!cloneSubmodules;\n config.cloneSubmodulesFilter = cloneSubmodulesFilter;\n config.ignorePrAuthor = GlobalConfig.get('ignorePrAuthor');\n\n // Try to fetch information about repository\n try {\n repo = await helper.getRepo(repository);\n } catch (err) {\n logger.debug({ err }, 'Unknown Forgejo initRepo error');\n throw err;\n }\n\n // Ensure appropriate repository state and permissions\n if (repo.archived) {\n logger.debug('Repository is archived - aborting renovation');\n throw new Error(REPOSITORY_ARCHIVED);\n }\n if (repo.mirror) {\n logger.debug('Repository is a mirror - aborting renovation');\n throw new Error(REPOSITORY_MIRRORED);\n }\n if (!repo.permissions.pull || !repo.permissions.push) {\n logger.debug(\n 'Repository does not permit pull or push - aborting renovation',\n );\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n if (repo.empty) {\n logger.debug('Repository is empty - aborting renovation');\n throw new Error(REPOSITORY_EMPTY);\n }\n\n if (repo.has_pull_requests === false) {\n logger.debug('Repo has disabled pull requests - aborting renovation');\n throw new Error(REPOSITORY_BLOCKED);\n }\n\n // similar to forgejo behaviour- if default merge style is allowed, use this;\n // else fall back to predefined order. Order chosen to minimize commits - see\n // https://github.com/renovatebot/renovate/pull/37768 for discussion.\n const preferredOrder: PRMergeMethod[] = [\n ...(repo.default_merge_style ? [repo.default_merge_style] : []),\n 'fast-forward-only',\n 'squash',\n 'merge',\n 'rebase',\n 'rebase-merge',\n ];\n\n const mergeStyle = preferredOrder.find((style) => isAllowed(style, repo));\n\n if (mergeStyle) {\n config.mergeMethod = mergeStyle;\n } else {\n logger.debug(\n 'Repository has no allowed merge methods - aborting renovation',\n );\n throw new Error(REPOSITORY_BLOCKED);\n }\n\n try {\n config.isOrgRepo = await helper.isOrg(repo.owner.login);\n } catch (err) {\n logger.debug({ err }, 'Forgejo initRepo() error');\n throw err;\n }\n\n // Determine author email and branches\n config.defaultBranch = repo.default_branch;\n logger.debug(`${repository} default branch = ${config.defaultBranch}`);\n\n const url = getRepoUrl(repo, gitUrl, defaults.endpoint);\n\n // Initialize Git storage\n await git.initRepo({\n ...config,\n url,\n });\n\n // Reset cached resources\n config.issueList = null;\n config.labelList = null;\n config.hasIssuesEnabled = !repo.external_tracker && repo.has_issues;\n config.orgName = repo.owner.login;\n\n return {\n defaultBranch: config.defaultBranch,\n isFork: !!repo.fork,\n repoFingerprint: repoFingerprint(repo.id, defaults.endpoint),\n };\n },\n\n async getRepos(config?: AutodiscoverConfig): Promise<string[]> {\n logger.debug('Auto-discovering Forgejo repositories');\n try {\n if (config?.topics) {\n logger.debug({ topics: config.topics }, 'Auto-discovering by topics');\n const fetchRepoArgs: FetchRepositoriesArgs[] = config.topics.map(\n (topic) => {\n return {\n topic,\n sort: config.sort,\n order: config.order,\n };\n },\n );\n const repos = await map(fetchRepoArgs, fetchRepositories);\n return deduplicateArray(repos.flat());\n }\n if (config?.namespaces) {\n logger.debug(\n { namespaces: config.namespaces },\n 'Auto-discovering by organization',\n );\n const repos = await map(\n config.namespaces,\n async (organization: string) => {\n const orgRepos = await helper.orgListRepos(organization);\n return orgRepos\n .filter((r) => !r.mirror && !r.archived)\n .map((r) => r.full_name);\n },\n );\n return deduplicateArray(repos.flat());\n }\n return await fetchRepositories({\n sort: config?.sort,\n order: config?.order,\n });\n } catch (err) {\n logger.error({ err }, 'Forgejo getRepos() error');\n throw err;\n }\n },\n\n async setBranchStatus({\n branchName,\n context,\n description,\n state,\n url: target_url,\n }: BranchStatusConfig): Promise<void> {\n try {\n // Create new status for branch commit\n const branchCommit = git.getBranchCommit(branchName);\n // TODO: check branchCommit\n\n await helper.createCommitStatus(config.repository, branchCommit!, {\n state: helper.renovateToForgejoStatusMapping[state] || 'pending',\n context,\n description,\n ...(target_url && { target_url }),\n });\n\n // Refresh caches by re-fetching commit status for branch\n await helper.getCombinedCommitStatus(config.repository, branchName, {\n memCache: false,\n });\n } catch (err) {\n logger.warn({ err }, 'Failed to set branch status');\n }\n },\n\n async getBranchStatus(\n branchName: string,\n internalChecksAsSuccess: boolean,\n ): Promise<BranchStatus> {\n let ccs: CombinedCommitStatus;\n try {\n ccs = await helper.getCombinedCommitStatus(config.repository, branchName);\n } catch (err) {\n if (err.statusCode === 404) {\n logger.debug(\n 'Received 404 when checking branch status, assuming branch deletion',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n\n logger.debug('Unknown error when checking branch status');\n throw err;\n }\n\n logger.debug({ ccs }, 'Branch status check result');\n if (\n !internalChecksAsSuccess &&\n ccs.worstStatus === 'success' &&\n ccs.statuses.every((status) => status.context?.startsWith('renovate/'))\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n\n return helper.forgejoToRenovateStatusMapping[ccs.worstStatus];\n },\n\n async getBranchStatusCheck(\n branchName: string,\n context: string,\n ): Promise<BranchStatus | null> {\n const ccs = await helper.getCombinedCommitStatus(\n config.repository,\n branchName,\n );\n const cs = ccs.statuses.find((s) => s.context === context);\n if (!cs) {\n return null;\n } // no status check exists\n return helper.forgejoToRenovateStatusMapping[cs.status];\n },\n\n getPrList(): Promise<Pr[]> {\n return ForgejoPrCache.getPrs(\n forgejoHttp,\n config.repository,\n config.ignorePrAuthor,\n botUserName,\n );\n },\n\n async getPr(number: number): Promise<Pr | null> {\n // Search for pull request in cached list or attempt to query directly\n const prList = await platform.getPrList();\n let pr = prList.find((p) => p.number === number) ?? null;\n if (pr) {\n logger.debug('Returning from cached PRs');\n } else {\n logger.debug('PR not found in cached PRs - trying to fetch directly');\n const gpr = await helper.getPR(config.repository, number);\n pr = toRenovatePR(gpr, botUserName);\n\n // Add pull request to cache for further lookups / queries\n if (pr) {\n await ForgejoPrCache.setPr(\n forgejoHttp,\n config.repository,\n config.ignorePrAuthor,\n botUserName,\n pr,\n );\n }\n }\n\n // Abort and return null if no match was found\n if (!pr) {\n return null;\n }\n\n return pr;\n },\n\n async findPr({\n branchName,\n prTitle: title,\n state = 'all',\n includeOtherAuthors,\n targetBranch,\n }: FindPRConfig): Promise<Pr | null> {\n logger.debug(`findPr(${branchName}, ${title!}, ${state})`);\n if (includeOtherAuthors && isString(targetBranch)) {\n // do not use pr cache as it only fetches prs created by the bot account\n const pr = await helper.getPRByBranch(\n config.repository,\n targetBranch,\n branchName,\n );\n if (!pr) {\n return null;\n }\n\n return toRenovatePR(pr, null);\n }\n const prList = await platform.getPrList();\n const pr = prList.find(\n (p) =>\n p.sourceRepo === config.repository &&\n p.sourceBranch === branchName &&\n matchesState(p.state, state) &&\n (!title || p.title === title),\n );\n\n if (pr) {\n logger.debug(`Found PR #${pr.number}`);\n }\n return pr ?? null;\n },\n\n async createPr({\n sourceBranch,\n targetBranch,\n prTitle,\n prBody: rawBody,\n labels: labelNames,\n platformPrOptions,\n draftPR,\n }: CreatePRConfig): Promise<Pr> {\n let title = prTitle;\n const base = targetBranch;\n const head = sourceBranch;\n const body = sanitize(rawBody);\n if (draftPR) {\n title = DRAFT_PREFIX + title;\n }\n\n logger.debug(`Creating pull request: ${title} (${head} => ${base})`);\n try {\n const labels = Array.isArray(labelNames)\n ? await map(labelNames, lookupLabelByName)\n : [];\n const gpr = await helper.createPR(config.repository, {\n base,\n head,\n title,\n body,\n labels: labels.filter(isNumber),\n });\n\n if (platformPrOptions?.usePlatformAutomerge) {\n // Only Forgejo v10.0.0+ support delete_branch_after_merge.\n // This is required to not have undesired behavior when renovate finds existing branches on next run.\n // Codeberg usees git versioning like `11.0.1-99-c504062+gitea-1.22.0` so allow any version >= 10.0.0-0.\n if (semver.gte(defaults.version, '10.0.0-0')) {\n try {\n await helper.mergePR(config.repository, gpr.number, {\n Do:\n getMergeMethod(platformPrOptions?.automergeStrategy) ??\n config.mergeMethod,\n merge_when_checks_succeed: true,\n delete_branch_after_merge: true,\n });\n\n logger.debug(\n { prNumber: gpr.number },\n 'Forgejo-native automerge: success',\n );\n } catch (err) {\n logger.warn(\n { err, prNumber: gpr.number },\n 'Forgejo-native automerge: fail',\n );\n }\n } else {\n logger.debug(\n { prNumber: gpr.number },\n `Forgejo-native automerge: not supported on this version of Forgejo. Use 10.0.0 or newer.`,\n );\n }\n }\n\n const pr = toRenovatePR(gpr, botUserName);\n if (!pr) {\n throw new Error('Can not parse newly created Pull Request');\n }\n\n await ForgejoPrCache.setPr(\n forgejoHttp,\n config.repository,\n config.ignorePrAuthor,\n botUserName,\n pr,\n );\n return pr;\n } catch (err) {\n // When the user manually deletes a branch from Renovate, the PR remains but is no longer linked to any branch. In\n // the most recent versions of Forgejo, the PR gets automatically closed when that happens, but older versions do\n // not handle this properly and keep the PR open. As pushing a branch with the same name resurrects the PR, this\n // would cause a HTTP 409 conflict error, which we hereby gracefully handle.\n if (err.statusCode === 409) {\n logger.warn(\n { prTitle: title, sourceBranch },\n 'Attempting to gracefully recover from 409 Conflict response in createPr()',\n );\n\n // Refresh cached PR list and search for pull request with matching information\n ForgejoPrCache.forceSync();\n const pr = await platform.findPr({\n branchName: sourceBranch,\n state: 'open',\n });\n\n // If a valid PR was found, return and gracefully recover from the error. Otherwise, abort and throw error.\n // v8 ignore else -- TODO: add test #40625\n if (pr?.bodyStruct) {\n if (pr.title !== title || pr.bodyStruct.hash !== hashBody(body)) {\n logger.debug(\n `Recovered from 409 Conflict, but PR for ${sourceBranch} is outdated. Updating...`,\n );\n await platform.updatePr({\n number: pr.number,\n prTitle: title,\n prBody: body,\n });\n pr.title = title;\n pr.bodyStruct = getPrBodyStruct(body);\n } else {\n logger.debug(\n `Recovered from 409 Conflict and PR for ${sourceBranch} is up-to-date`,\n );\n }\n\n return pr;\n }\n }\n\n throw err;\n }\n },\n\n async updatePr({\n number,\n prTitle,\n prBody: body,\n labels,\n state,\n targetBranch,\n }: UpdatePrConfig): Promise<void> {\n let title = prTitle;\n if ((await getPrList()).find((pr) => pr.number === number)?.isDraft) {\n title = DRAFT_PREFIX + title;\n }\n\n const prUpdateParams: PRUpdateParams = {\n title,\n ...(body && { body }),\n ...(state && { state }),\n };\n if (targetBranch) {\n prUpdateParams.base = targetBranch;\n }\n\n /**\n * Update PR labels.\n * In the Forgejo API, labels are replaced on each update if the field is present.\n * If the field is not present (i.e., undefined), labels aren't updated.\n * However, the labels array must contain label IDs instead of names,\n * so a lookup is performed to fetch the details (including the ID) of each label.\n */\n if (Array.isArray(labels)) {\n prUpdateParams.labels = (await map(labels, lookupLabelByName)).filter(\n isNumber,\n );\n if (labels.length !== prUpdateParams.labels.length) {\n logger.warn(\n 'Some labels could not be looked up. Renovate may halt label updates assuming changes by others.',\n );\n }\n }\n\n const gpr = await helper.updatePR(\n config.repository,\n number,\n prUpdateParams,\n );\n const pr = toRenovatePR(gpr, botUserName);\n if (pr) {\n await ForgejoPrCache.setPr(\n forgejoHttp,\n config.repository,\n config.ignorePrAuthor,\n botUserName,\n pr,\n );\n }\n },\n\n async mergePr({ id, strategy }: MergePRConfig): Promise<boolean> {\n try {\n await helper.mergePR(config.repository, id, {\n Do: getMergeMethod(strategy) ?? config.mergeMethod,\n });\n return true;\n } catch (err) {\n logger.warn({ err, id }, 'Merging of PR failed');\n return false;\n }\n },\n\n getIssueList(): Promise<Issue[]> {\n if (config.hasIssuesEnabled === false) {\n return Promise.resolve([]);\n }\n config.issueList ??= helper\n .searchIssues(config.repository, { state: 'all' }, { memCache: false })\n .then((issues) => {\n const issueList = issues.map(toRenovateIssue);\n logger.debug(`Retrieved ${issueList.length} Issues`);\n return issueList;\n });\n\n return config.issueList;\n },\n\n async getIssue(number: number, memCache = true): Promise<Issue | null> {\n if (config.hasIssuesEnabled === false) {\n return null;\n }\n try {\n const body = (\n await helper.getIssue(config.repository, number, { memCache })\n ).body;\n return {\n number,\n body,\n };\n } catch (err) {\n logger.debug({ err, number }, 'Error getting issue');\n return null;\n }\n },\n\n async findIssue(title: string): Promise<Issue | null> {\n const issueList = await platform.getIssueList();\n const issue = issueList.find(\n (i) => i.state === 'open' && i.title === title,\n );\n\n if (!issue) {\n return null;\n }\n // TODO: types (#22198)\n logger.debug(`Found Issue #${issue.number!}`);\n // TODO #22198\n return getIssue!(issue.number!);\n },\n\n async ensureIssue({\n title,\n reuseTitle,\n body: content,\n labels: labelNames,\n shouldReOpen,\n once,\n }: EnsureIssueConfig): Promise<'updated' | 'created' | null> {\n logger.debug(`ensureIssue(${title})`);\n if (config.hasIssuesEnabled === false) {\n logger.info(\n 'Cannot ensure issue because issues are disabled in this repository',\n );\n return null;\n }\n try {\n const body = smartLinks(content);\n\n const issueList = await platform.getIssueList();\n let issues = issueList.filter((i) => i.title === title);\n if (!issues.length) {\n issues = issueList.filter((i) => i.title === reuseTitle);\n }\n\n const labels = Array.isArray(labelNames)\n ? (await Promise.all(labelNames.map(lookupLabelByName))).filter(\n isNumber,\n )\n : undefined;\n\n // Update any matching issues which currently exist\n if (issues.length) {\n let activeIssue = issues.find((i) => i.state === 'open');\n\n // If no active issue was found, decide if it shall be skipped, re-opened or updated without state change\n if (!activeIssue) {\n if (once) {\n logger.debug('Issue already closed - skipping update');\n return null;\n }\n if (shouldReOpen) {\n logger.debug('Reopening previously closed Issue');\n }\n\n // Pick the last issue in the list as the active one\n activeIssue = issues.at(-1)!;\n }\n\n // Close any duplicate issues\n for (const issue of issues) {\n if (issue.state === 'open' && issue.number !== activeIssue.number) {\n // TODO: types (#22198)\n logger.warn({ issueNo: issue.number! }, 'Closing duplicate issue');\n // TODO #22198\n await helper.closeIssue(config.repository, issue.number!);\n }\n }\n\n // Check if issue has already correct state\n if (\n activeIssue.title === title &&\n activeIssue.body === body &&\n activeIssue.state === 'open'\n ) {\n logger.debug(\n // TODO: types (#22198)\n `Issue #${activeIssue.number!} is open and up to date - nothing to do`,\n );\n return null;\n }\n\n if (shouldReOpen || activeIssue.state === 'open') {\n // Update issue body and re-open\n logger.debug(`Updating Issue #${activeIssue.number}`);\n const existingIssue = await helper.updateIssue(\n config.repository,\n // TODO #22198\n activeIssue.number!,\n {\n body,\n title,\n state: 'open',\n },\n );\n\n // Test whether the issues need to be updated\n const existingLabelIds = (existingIssue.labels ?? []).map(\n (label) => label.id,\n );\n if (\n labels &&\n (labels.length !== existingLabelIds.length ||\n labels.filter((labelId) => !existingLabelIds.includes(labelId))\n .length !== 0)\n ) {\n await helper.updateIssueLabels(\n config.repository,\n // TODO #22198\n activeIssue.number!,\n {\n labels,\n },\n );\n }\n\n return 'updated';\n }\n }\n\n // Create new issue and reset cache\n const issue = await helper.createIssue(config.repository, {\n body,\n title,\n labels,\n });\n logger.debug(`Created new Issue #${issue.number}`);\n config.issueList = null;\n\n return 'created';\n } catch (err) {\n logger.warn({ err }, 'Could not ensure issue');\n }\n\n return null;\n },\n\n async ensureIssueClosing(title: string): Promise<void> {\n logger.debug(`ensureIssueClosing(${title})`);\n if (config.hasIssuesEnabled === false) {\n return;\n }\n const issueList = await platform.getIssueList();\n for (const issue of issueList) {\n if (issue.state === 'open' && issue.title === title) {\n logger.debug(`Closing issue...issueNo: ${issue.number!}`);\n // TODO #22198\n await helper.closeIssue(config.repository, issue.number!);\n }\n }\n },\n\n async deleteLabel(issue: number, labelName: string): Promise<void> {\n logger.debug(`Deleting label ${labelName} from Issue #${issue}`);\n const label = await lookupLabelByName(labelName);\n if (label) {\n await helper.unassignLabel(config.repository, issue, label);\n } else {\n logger.warn({ issue, labelName }, 'Failed to lookup label for deletion');\n }\n },\n\n async ensureComment({\n number: issue,\n topic,\n content,\n }: EnsureCommentConfig): Promise<boolean> {\n try {\n let body = sanitize(content);\n const commentList = await helper.getComments(config.repository, issue);\n\n // Search comment by either topic or exact body\n let comment: Comment | null = null;\n if (topic) {\n comment = findCommentByTopic(commentList, topic);\n body = `### ${topic}\\n\\n${body}`;\n } else {\n comment = findCommentByContent(commentList, body);\n }\n\n // Create a new comment if no match has been found, otherwise update if necessary\n if (!comment) {\n comment = await helper.createComment(config.repository, issue, body);\n logger.info(\n { repository: config.repository, issue, comment: comment.id },\n 'Comment added',\n );\n } else if (comment.body === body) {\n logger.debug(`Comment #${comment.id} is already up-to-date`);\n } else {\n await helper.updateComment(config.repository, comment.id, body);\n logger.debug(\n { repository: config.repository, issue, comment: comment.id },\n 'Comment updated',\n );\n }\n\n return true;\n } catch (err) {\n logger.warn({ err, issue, subject: topic }, 'Error ensuring comment');\n return false;\n }\n },\n\n async ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n ): Promise<void> {\n const { number: issue } = deleteConfig;\n const key =\n deleteConfig.type === 'by-topic'\n ? deleteConfig.topic\n : deleteConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${issue} is removed`);\n const commentList = await helper.getComments(config.repository, issue);\n\n let comment: Comment | null = null;\n // v8 ignore else -- TODO: add test #40625\n if (deleteConfig.type === 'by-topic') {\n comment = findCommentByTopic(commentList, deleteConfig.topic);\n } else if (deleteConfig.type === 'by-content') {\n const body = sanitize(deleteConfig.content);\n comment = findCommentByContent(commentList, body);\n }\n\n // Abort and do nothing if no matching comment was found\n if (!comment) {\n return;\n }\n\n // Try to delete comment\n try {\n await helper.deleteComment(config.repository, comment.id);\n } catch (err) {\n logger.warn(\n { err, issue, config: deleteConfig },\n 'Error deleting comment',\n );\n }\n },\n\n async getBranchPr(branchName: string): Promise<Pr | null> {\n logger.debug(`getBranchPr(${branchName})`);\n const pr = await platform.findPr({ branchName, state: 'open' });\n return pr ? platform.getPr(pr.number) : null;\n },\n\n async addAssignees(number: number, assignees: string[]): Promise<void> {\n logger.debug(\n `Updating assignees '${assignees?.join(', ')}' on Issue #${number}`,\n );\n await helper.updateIssue(config.repository, number, {\n assignees,\n });\n },\n\n async addReviewers(number: number, reviewers: string[]): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers?.join(', ')}' to #${number}`);\n try {\n const teamReviewers = new Set(\n reviewers\n .filter((r) => r.startsWith('team:'))\n .map((r) => r.substring(5)),\n );\n const userReviewers = new Set(\n reviewers.filter((r) => !r.startsWith('team:')),\n );\n\n await helper.requestPrReviewers(config.repository, number, {\n reviewers: [...userReviewers],\n ...(teamReviewers.size && {\n team_reviewers: [...teamReviewers],\n }),\n });\n } catch (err) {\n logger.warn({ err, number, reviewers }, 'Failed to assign reviewer');\n }\n },\n\n massageMarkdown(prBody: string): string {\n return smartTruncate(smartLinks(prBody), maxBodyLength());\n },\n\n maxBodyLength,\n};\n\nexport function maxBodyLength(): number {\n return 1000000;\n}\n\n/* oxlint-disable typescript/unbound-method */\nexport const {\n addAssignees,\n addReviewers,\n createPr,\n deleteLabel,\n ensureComment,\n ensureCommentRemoval,\n ensureIssue,\n ensureIssueClosing,\n findIssue,\n findPr,\n getBranchPr,\n getBranchStatus,\n getBranchStatusCheck,\n getIssue,\n getRawFile,\n getJsonFile,\n getIssueList,\n getPr,\n massageMarkdown,\n getPrList,\n getRepos,\n initPlatform,\n initRepo,\n mergePr,\n setBranchStatus,\n updatePr,\n} = platform;\n"],"mappings":"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"}
@@ -49,7 +49,7 @@ function getMergeMethod(strategy) {
49
49
  }
50
50
  const API_PATH = "/api/v1";
51
51
  const DRAFT_PREFIX = "WIP: ";
52
- const reconfigurePrRegex = regEx(/reconfigure$/g);
52
+ const reconfigurePrRegex = regEx(/reconfigure$/);
53
53
  function toRenovatePR(data, author) {
54
54
  if (!data.base?.ref || !data.head?.label || !data.head?.sha || !data.head?.repo?.full_name) {
55
55
  logger.trace(`Skipping Pull Request #${data.number} due to missing base and/or head branch`);
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":["hostRules.find"],"sources":["../../../../lib/modules/platform/forgejo/utils.ts"],"sourcesContent":["import { isNonEmptyArray } from '@sindresorhus/is';\nimport type { MergeStrategy } from '../../../config/types.ts';\nimport { CONFIG_GIT_URL_UNAVAILABLE } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { getPrBodyStruct } from '../pr-body.ts';\nimport type { GitUrlOption, Pr } from '../types.ts';\nimport type { PR, PRMergeMethod, Repo } from './schema.ts';\n\nexport function smartLinks(body: string): string {\n return body\n ?.replace(regEx(/\\]\\(\\.\\.\\/issues\\//g), '](issues/')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](pulls/');\n}\n\nexport function trimTrailingApiPath(url: string): string {\n return url?.replace(regEx(/api\\/v1\\/?$/g), '');\n}\n\nexport function getRepoUrl(\n repo: Repo,\n gitUrl: GitUrlOption | undefined,\n endpoint: string,\n): string {\n if (gitUrl === 'ssh') {\n if (!repo.ssh_url) {\n throw new Error(CONFIG_GIT_URL_UNAVAILABLE);\n }\n logger.debug(`Using SSH URL: ${repo.ssh_url}`);\n return repo.ssh_url;\n }\n\n // Find options for current host and determine Git endpoint\n const opts = hostRules.find({\n hostType: 'forgejo',\n url: endpoint,\n });\n\n if (gitUrl === 'endpoint') {\n const url = parseUrl(endpoint);\n if (!url) {\n throw new Error(CONFIG_GIT_URL_UNAVAILABLE);\n }\n url.username = opts.token ?? '';\n url.pathname = `${url.pathname}${repo.full_name}.git`;\n logger.debug(\n { url: url.toString() },\n 'using URL based on configured endpoint',\n );\n return url.toString();\n }\n\n if (!repo.clone_url) {\n throw new Error(CONFIG_GIT_URL_UNAVAILABLE);\n }\n\n logger.debug(`Using HTTP URL: ${repo.clone_url}`);\n const repoUrl = parseUrl(repo.clone_url);\n if (!repoUrl) {\n throw new Error(CONFIG_GIT_URL_UNAVAILABLE);\n }\n repoUrl.username = opts.token ?? '';\n return repoUrl.toString();\n}\n\nexport function getMergeMethod(\n strategy: MergeStrategy | undefined,\n): PRMergeMethod | null {\n switch (strategy) {\n case 'fast-forward':\n return 'rebase';\n case 'merge-commit':\n return 'merge';\n case 'rebase':\n return 'rebase-merge';\n case 'squash':\n return strategy;\n case 'auto':\n default:\n return null;\n }\n}\n\nexport const API_PATH = '/api/v1';\n\nexport const DRAFT_PREFIX = 'WIP: ';\nconst reconfigurePrRegex = regEx(/reconfigure$/g);\n\nexport function toRenovatePR(data: PR, author: string | null): Pr | null {\n if (\n !data.base?.ref ||\n !data.head?.label ||\n !data.head?.sha ||\n !data.head?.repo?.full_name\n ) {\n logger.trace(\n `Skipping Pull Request #${data.number} due to missing base and/or head branch`,\n );\n return null;\n }\n\n const createdBy = data.user?.login;\n if (\n createdBy &&\n author &&\n !reconfigurePrRegex.test(data.head.label) &&\n createdBy !== author\n ) {\n return null;\n }\n\n let title = data.title;\n let isDraft = false;\n if (title.startsWith(DRAFT_PREFIX)) {\n title = title.substring(DRAFT_PREFIX.length);\n isDraft = true;\n }\n const labels = coerceArray(data.labels).map((l) => l.name);\n\n return {\n labels,\n number: data.number,\n state: data.merged ? 'merged' : data.state,\n title,\n isDraft,\n bodyStruct: getPrBodyStruct(data.body),\n sha: data.head.sha,\n sourceBranch: data.head.label,\n targetBranch: data.base.ref,\n sourceRepo: data.head.repo.full_name,\n createdAt: data.created_at,\n cannotMergeReason: data.mergeable\n ? undefined\n : `pr.mergeable=\"${data.mergeable}\"`,\n hasAssignees: !!(data.assignee?.login ?? isNonEmptyArray(data.assignees)),\n };\n}\n\n/**\n * Check if a repository is usable.\n * A repo isn't usable if one of the following conditions is met:\n * - The repo is a `mirror`\n * - We don't have pull or push permissions\n * - Pull requests are disabled\n * @param repo Repo to check\n * @returns `true` if the repository is usable, `false` otherwise\n */\nexport function usableRepo(repo: Repo): boolean {\n if (repo.mirror === true) {\n return false;\n }\n\n if (repo.permissions.pull === false || repo.permissions.push === false) {\n logger.debug(\n `Skipping repository ${repo.full_name} because of missing pull or push permissions`,\n );\n return false;\n }\n\n if (repo.has_pull_requests === false) {\n logger.debug(\n `Skipping repository ${repo.full_name} because pull requests are disabled`,\n );\n return false;\n }\n return true;\n}\n\nexport function isAllowed(style: PRMergeMethod, repo: Repo): boolean {\n switch (style) {\n case 'merge':\n return repo.allow_merge_commits;\n case 'rebase':\n return repo.allow_rebase;\n case 'rebase-merge':\n return repo.allow_rebase_explicit;\n case 'squash':\n return repo.allow_squash_merge;\n case 'fast-forward-only':\n return repo.allow_fast_forward_only_merge;\n }\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,WAAW,MAAsB;CAC/C,OAAO,MACH,QAAQ,MAAM,qBAAqB,GAAG,WAAW,CAAC,CACnD,QAAQ,MAAM,mBAAmB,GAAG,UAAU;AACnD;AAEA,SAAgB,oBAAoB,KAAqB;CACvD,OAAO,KAAK,QAAQ,MAAM,cAAc,GAAG,EAAE;AAC/C;AAEA,SAAgB,WACd,MACA,QACA,UACQ;CACR,IAAI,WAAW,OAAO;EACpB,IAAI,CAAC,KAAK,SACR,MAAM,IAAI,MAAM,0BAA0B;EAE5C,OAAO,MAAM,kBAAkB,KAAK,SAAS;EAC7C,OAAO,KAAK;CACd;CAGA,MAAM,OAAOA,KAAe;EAC1B,UAAU;EACV,KAAK;CACP,CAAC;CAED,IAAI,WAAW,YAAY;EACzB,MAAM,MAAM,SAAS,QAAQ;EAC7B,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,0BAA0B;EAE5C,IAAI,WAAW,KAAK,SAAS;EAC7B,IAAI,WAAW,GAAG,IAAI,WAAW,KAAK,UAAU;EAChD,OAAO,MACL,EAAE,KAAK,IAAI,SAAS,EAAE,GACtB,wCACF;EACA,OAAO,IAAI,SAAS;CACtB;CAEA,IAAI,CAAC,KAAK,WACR,MAAM,IAAI,MAAM,0BAA0B;CAG5C,OAAO,MAAM,mBAAmB,KAAK,WAAW;CAChD,MAAM,UAAU,SAAS,KAAK,SAAS;CACvC,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,0BAA0B;CAE5C,QAAQ,WAAW,KAAK,SAAS;CACjC,OAAO,QAAQ,SAAS;AAC1B;AAEA,SAAgB,eACd,UACsB;CACtB,QAAQ,UAAR;EACE,KAAK,gBACH,OAAO;EACT,KAAK,gBACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,UACH,OAAO;EAET,SACE,OAAO;CACX;AACF;AAEA,MAAa,WAAW;AAExB,MAAa,eAAe;AAC5B,MAAM,qBAAqB,MAAM,eAAe;AAEhD,SAAgB,aAAa,MAAU,QAAkC;CACvE,IACE,CAAC,KAAK,MAAM,OACZ,CAAC,KAAK,MAAM,SACZ,CAAC,KAAK,MAAM,OACZ,CAAC,KAAK,MAAM,MAAM,WAClB;EACA,OAAO,MACL,0BAA0B,KAAK,OAAO,wCACxC;EACA,OAAO;CACT;CAEA,MAAM,YAAY,KAAK,MAAM;CAC7B,IACE,aACA,UACA,CAAC,mBAAmB,KAAK,KAAK,KAAK,KAAK,KACxC,cAAc,QAEd,OAAO;CAGT,IAAI,QAAQ,KAAK;CACjB,IAAI,UAAU;CACd,IAAI,MAAM,WAAA,OAAuB,GAAG;EAClC,QAAQ,MAAM,UAAU,CAAmB;EAC3C,UAAU;CACZ;CAGA,OAAO;EACL,QAHa,YAAY,KAAK,MAAM,CAAC,CAAC,KAAK,MAAM,EAAE,IAG9C;EACL,QAAQ,KAAK;EACb,OAAO,KAAK,SAAS,WAAW,KAAK;EACrC;EACA;EACA,YAAY,gBAAgB,KAAK,IAAI;EACrC,KAAK,KAAK,KAAK;EACf,cAAc,KAAK,KAAK;EACxB,cAAc,KAAK,KAAK;EACxB,YAAY,KAAK,KAAK,KAAK;EAC3B,WAAW,KAAK;EAChB,mBAAmB,KAAK,YACpB,KAAA,IACA,iBAAiB,KAAK,UAAU;EACpC,cAAc,CAAC,EAAE,KAAK,UAAU,SAAS,gBAAgB,KAAK,SAAS;CACzE;AACF;;;;;;;;;;AAWA,SAAgB,WAAW,MAAqB;CAC9C,IAAI,KAAK,WAAW,MAClB,OAAO;CAGT,IAAI,KAAK,YAAY,SAAS,SAAS,KAAK,YAAY,SAAS,OAAO;EACtE,OAAO,MACL,uBAAuB,KAAK,UAAU,6CACxC;EACA,OAAO;CACT;CAEA,IAAI,KAAK,sBAAsB,OAAO;EACpC,OAAO,MACL,uBAAuB,KAAK,UAAU,oCACxC;EACA,OAAO;CACT;CACA,OAAO;AACT;AAEA,SAAgB,UAAU,OAAsB,MAAqB;CACnE,QAAQ,OAAR;EACE,KAAK,SACH,OAAO,KAAK;EACd,KAAK,UACH,OAAO,KAAK;EACd,KAAK,gBACH,OAAO,KAAK;EACd,KAAK,UACH,OAAO,KAAK;EACd,KAAK,qBACH,OAAO,KAAK;CAChB;AACF"}
1
+ {"version":3,"file":"utils.js","names":["hostRules.find"],"sources":["../../../../lib/modules/platform/forgejo/utils.ts"],"sourcesContent":["import { isNonEmptyArray } from '@sindresorhus/is';\nimport type { MergeStrategy } from '../../../config/types.ts';\nimport { CONFIG_GIT_URL_UNAVAILABLE } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport { getPrBodyStruct } from '../pr-body.ts';\nimport type { GitUrlOption, Pr } from '../types.ts';\nimport type { PR, PRMergeMethod, Repo } from './schema.ts';\n\nexport function smartLinks(body: string): string {\n return body\n ?.replace(regEx(/\\]\\(\\.\\.\\/issues\\//g), '](issues/')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](pulls/');\n}\n\nexport function trimTrailingApiPath(url: string): string {\n return url?.replace(regEx(/api\\/v1\\/?$/g), '');\n}\n\nexport function getRepoUrl(\n repo: Repo,\n gitUrl: GitUrlOption | undefined,\n endpoint: string,\n): string {\n if (gitUrl === 'ssh') {\n if (!repo.ssh_url) {\n throw new Error(CONFIG_GIT_URL_UNAVAILABLE);\n }\n logger.debug(`Using SSH URL: ${repo.ssh_url}`);\n return repo.ssh_url;\n }\n\n // Find options for current host and determine Git endpoint\n const opts = hostRules.find({\n hostType: 'forgejo',\n url: endpoint,\n });\n\n if (gitUrl === 'endpoint') {\n const url = parseUrl(endpoint);\n if (!url) {\n throw new Error(CONFIG_GIT_URL_UNAVAILABLE);\n }\n url.username = opts.token ?? '';\n url.pathname = `${url.pathname}${repo.full_name}.git`;\n logger.debug(\n { url: url.toString() },\n 'using URL based on configured endpoint',\n );\n return url.toString();\n }\n\n if (!repo.clone_url) {\n throw new Error(CONFIG_GIT_URL_UNAVAILABLE);\n }\n\n logger.debug(`Using HTTP URL: ${repo.clone_url}`);\n const repoUrl = parseUrl(repo.clone_url);\n if (!repoUrl) {\n throw new Error(CONFIG_GIT_URL_UNAVAILABLE);\n }\n repoUrl.username = opts.token ?? '';\n return repoUrl.toString();\n}\n\nexport function getMergeMethod(\n strategy: MergeStrategy | undefined,\n): PRMergeMethod | null {\n switch (strategy) {\n case 'fast-forward':\n return 'rebase';\n case 'merge-commit':\n return 'merge';\n case 'rebase':\n return 'rebase-merge';\n case 'squash':\n return strategy;\n case 'auto':\n default:\n return null;\n }\n}\n\nexport const API_PATH = '/api/v1';\n\nexport const DRAFT_PREFIX = 'WIP: ';\nconst reconfigurePrRegex = regEx(/reconfigure$/);\n\nexport function toRenovatePR(data: PR, author: string | null): Pr | null {\n if (\n !data.base?.ref ||\n !data.head?.label ||\n !data.head?.sha ||\n !data.head?.repo?.full_name\n ) {\n logger.trace(\n `Skipping Pull Request #${data.number} due to missing base and/or head branch`,\n );\n return null;\n }\n\n const createdBy = data.user?.login;\n if (\n createdBy &&\n author &&\n !reconfigurePrRegex.test(data.head.label) &&\n createdBy !== author\n ) {\n return null;\n }\n\n let title = data.title;\n let isDraft = false;\n if (title.startsWith(DRAFT_PREFIX)) {\n title = title.substring(DRAFT_PREFIX.length);\n isDraft = true;\n }\n const labels = coerceArray(data.labels).map((l) => l.name);\n\n return {\n labels,\n number: data.number,\n state: data.merged ? 'merged' : data.state,\n title,\n isDraft,\n bodyStruct: getPrBodyStruct(data.body),\n sha: data.head.sha,\n sourceBranch: data.head.label,\n targetBranch: data.base.ref,\n sourceRepo: data.head.repo.full_name,\n createdAt: data.created_at,\n cannotMergeReason: data.mergeable\n ? undefined\n : `pr.mergeable=\"${data.mergeable}\"`,\n hasAssignees: !!(data.assignee?.login ?? isNonEmptyArray(data.assignees)),\n };\n}\n\n/**\n * Check if a repository is usable.\n * A repo isn't usable if one of the following conditions is met:\n * - The repo is a `mirror`\n * - We don't have pull or push permissions\n * - Pull requests are disabled\n * @param repo Repo to check\n * @returns `true` if the repository is usable, `false` otherwise\n */\nexport function usableRepo(repo: Repo): boolean {\n if (repo.mirror === true) {\n return false;\n }\n\n if (repo.permissions.pull === false || repo.permissions.push === false) {\n logger.debug(\n `Skipping repository ${repo.full_name} because of missing pull or push permissions`,\n );\n return false;\n }\n\n if (repo.has_pull_requests === false) {\n logger.debug(\n `Skipping repository ${repo.full_name} because pull requests are disabled`,\n );\n return false;\n }\n return true;\n}\n\nexport function isAllowed(style: PRMergeMethod, repo: Repo): boolean {\n switch (style) {\n case 'merge':\n return repo.allow_merge_commits;\n case 'rebase':\n return repo.allow_rebase;\n case 'rebase-merge':\n return repo.allow_rebase_explicit;\n case 'squash':\n return repo.allow_squash_merge;\n case 'fast-forward-only':\n return repo.allow_fast_forward_only_merge;\n }\n}\n"],"mappings":"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"}