renovate 43.28.0 → 43.29.1

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.
@@ -1,4 +1,7 @@
1
+ import { logger } from "../../../logger/index.js";
1
2
  import { withCache } from "../../../util/cache/package/with-cache.js";
3
+ import { RequestError } from "../../../util/http/got.js";
4
+ import "../../../util/http/index.js";
2
5
  import { Datasource } from "../datasource.js";
3
6
  import { GithubReleasesDatasource } from "../github-releases/index.js";
4
7
  import { id } from "../../versioning/python/index.js";
@@ -50,7 +53,10 @@ var PythonVersionDatasource = class extends Datasource {
50
53
  const response = await this.http.getJson(registryUrl, PythonRelease);
51
54
  result.releases.push(...response.body.filter((release) => release.isStable).filter((release) => pythonPrebuildVersions.has(release.version)));
52
55
  } catch (err) {
53
- this.handleGenericErrors(err);
56
+ if (err instanceof RequestError && err.response?.statusCode === 429) {
57
+ logger.debug({ err }, "Rate limited by python.org, using prebuild releases");
58
+ result.releases.push(...pythonPrebuildReleases?.releases ?? []);
59
+ } else this.handleGenericErrors(err);
54
60
  }
55
61
  for (const release of result.releases) release.isDeprecated = pythonEolVersions.get(release.version.split(".").slice(0, 2).join("."));
56
62
  return result.releases.length ? result : null;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["versioning","eolRegistryUrl"],"sources":["../../../../lib/modules/datasource/python-version/index.ts"],"sourcesContent":["import { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { id as versioning } from '../../versioning/python/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport { registryUrl as eolRegistryUrl } from '../endoflife-date/common.ts';\nimport { EndoflifeDateDatasource } from '../endoflife-date/index.ts';\nimport { GithubReleasesDatasource } from '../github-releases/index.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport { datasource, defaultRegistryUrl, githubBaseUrl } from './common.ts';\nimport { PythonRelease } from './schema.ts';\n\nexport class PythonVersionDatasource extends Datasource {\n static readonly id = datasource;\n pythonPrebuildDatasource: GithubReleasesDatasource;\n pythonEolDatasource: EndoflifeDateDatasource;\n\n constructor() {\n super(datasource);\n this.pythonPrebuildDatasource = new GithubReleasesDatasource();\n this.pythonEolDatasource = new EndoflifeDateDatasource();\n }\n\n override readonly customRegistrySupport = false;\n\n override readonly defaultRegistryUrls = [defaultRegistryUrl];\n\n override readonly defaultVersioning = versioning;\n\n override readonly caching = true;\n\n async getPrebuildReleases(): Promise<ReleaseResult | null> {\n return await this.pythonPrebuildDatasource.getReleases({\n registryUrl: githubBaseUrl,\n packageName: 'containerbase/python-prebuild',\n });\n }\n\n async getEolReleases(): Promise<ReleaseResult | null> {\n return await this.pythonEolDatasource.getReleases({\n registryUrl: eolRegistryUrl,\n packageName: 'python',\n });\n }\n\n private async _getReleases({\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore next 3 -- should never happen */\n if (!registryUrl) {\n return null;\n }\n const pythonPrebuildReleases = await this.getPrebuildReleases();\n const pythonPrebuildVersions = new Set<string>(\n pythonPrebuildReleases?.releases.map((release) => release.version),\n );\n const pythonEolReleases = await this.getEolReleases();\n const pythonEolVersions = new Map(\n pythonEolReleases?.releases\n .filter((release) => release.isDeprecated !== undefined)\n .map((release) => [\n release.version.split('.').slice(0, 2).join('.'),\n release.isDeprecated,\n ]),\n );\n const result: ReleaseResult = {\n homepage: 'https://python.org',\n sourceUrl: 'https://github.com/python/cpython',\n registryUrl,\n releases: [],\n };\n try {\n const response = await this.http.getJson(registryUrl, PythonRelease);\n result.releases.push(\n ...response.body\n .filter((release) => release.isStable)\n .filter((release) => pythonPrebuildVersions.has(release.version)),\n );\n } catch (err) {\n this.handleGenericErrors(err);\n }\n for (const release of result.releases) {\n release.isDeprecated = pythonEolVersions.get(\n release.version.split('.').slice(0, 2).join('.'),\n );\n }\n\n return result.releases.length ? result : null;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${datasource}`,\n key: `${config.registryUrl}`,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n}\n"],"mappings":";;;;;;;;;;AAUA,IAAa,0BAAb,cAA6C,WAAW;CACtD,OAAgB,KAAK;CACrB;CACA;CAEA,cAAc;AACZ,QAAM,WAAW;AACjB,OAAK,2BAA2B,IAAI,0BAA0B;AAC9D,OAAK,sBAAsB,IAAI,yBAAyB;;CAG1D,AAAkB,wBAAwB;CAE1C,AAAkB,sBAAsB,CAAC,mBAAmB;CAE5D,AAAkB,oBAAoBA;CAEtC,AAAkB,UAAU;CAE5B,MAAM,sBAAqD;AACzD,SAAO,MAAM,KAAK,yBAAyB,YAAY;GACrD,aAAa;GACb,aAAa;GACd,CAAC;;CAGJ,MAAM,iBAAgD;AACpD,SAAO,MAAM,KAAK,oBAAoB,YAAY;GACnCC;GACb,aAAa;GACd,CAAC;;CAGJ,MAAc,aAAa,EACzB,eACmD;;AAEnD,MAAI,CAAC,YACH,QAAO;EAET,MAAM,yBAAyB,MAAM,KAAK,qBAAqB;EAC/D,MAAM,yBAAyB,IAAI,IACjC,wBAAwB,SAAS,KAAK,YAAY,QAAQ,QAAQ,CACnE;EACD,MAAM,oBAAoB,MAAM,KAAK,gBAAgB;EACrD,MAAM,oBAAoB,IAAI,IAC5B,mBAAmB,SAChB,QAAQ,YAAY,QAAQ,iBAAiB,OAAU,CACvD,KAAK,YAAY,CAChB,QAAQ,QAAQ,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,EAChD,QAAQ,aACT,CAAC,CACL;EACD,MAAM,SAAwB;GAC5B,UAAU;GACV,WAAW;GACX;GACA,UAAU,EAAE;GACb;AACD,MAAI;GACF,MAAM,WAAW,MAAM,KAAK,KAAK,QAAQ,aAAa,cAAc;AACpE,UAAO,SAAS,KACd,GAAG,SAAS,KACT,QAAQ,YAAY,QAAQ,SAAS,CACrC,QAAQ,YAAY,uBAAuB,IAAI,QAAQ,QAAQ,CAAC,CACpE;WACM,KAAK;AACZ,QAAK,oBAAoB,IAAI;;AAE/B,OAAK,MAAM,WAAW,OAAO,SAC3B,SAAQ,eAAe,kBAAkB,IACvC,QAAQ,QAAQ,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,CACjD;AAGH,SAAO,OAAO,SAAS,SAAS,SAAS;;CAG3C,YAAY,QAA0D;AACpE,SAAO,UACL;GACE,WAAW,cAAc;GACzB,KAAK,GAAG,OAAO;GACf,UAAU;GACX,QACK,KAAK,aAAa,OAAO,CAChC"}
1
+ {"version":3,"file":"index.js","names":["versioning","eolRegistryUrl","HttpError"],"sources":["../../../../lib/modules/datasource/python-version/index.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport { id as versioning } from '../../versioning/python/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport { registryUrl as eolRegistryUrl } from '../endoflife-date/common.ts';\nimport { EndoflifeDateDatasource } from '../endoflife-date/index.ts';\nimport { GithubReleasesDatasource } from '../github-releases/index.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport { datasource, defaultRegistryUrl, githubBaseUrl } from './common.ts';\nimport { PythonRelease } from './schema.ts';\n\nexport class PythonVersionDatasource extends Datasource {\n static readonly id = datasource;\n pythonPrebuildDatasource: GithubReleasesDatasource;\n pythonEolDatasource: EndoflifeDateDatasource;\n\n constructor() {\n super(datasource);\n this.pythonPrebuildDatasource = new GithubReleasesDatasource();\n this.pythonEolDatasource = new EndoflifeDateDatasource();\n }\n\n override readonly customRegistrySupport = false;\n\n override readonly defaultRegistryUrls = [defaultRegistryUrl];\n\n override readonly defaultVersioning = versioning;\n\n override readonly caching = true;\n\n async getPrebuildReleases(): Promise<ReleaseResult | null> {\n return await this.pythonPrebuildDatasource.getReleases({\n registryUrl: githubBaseUrl,\n packageName: 'containerbase/python-prebuild',\n });\n }\n\n async getEolReleases(): Promise<ReleaseResult | null> {\n return await this.pythonEolDatasource.getReleases({\n registryUrl: eolRegistryUrl,\n packageName: 'python',\n });\n }\n\n private async _getReleases({\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n /* v8 ignore next 3 -- should never happen */\n if (!registryUrl) {\n return null;\n }\n const pythonPrebuildReleases = await this.getPrebuildReleases();\n const pythonPrebuildVersions = new Set<string>(\n pythonPrebuildReleases?.releases.map((release) => release.version),\n );\n const pythonEolReleases = await this.getEolReleases();\n const pythonEolVersions = new Map(\n pythonEolReleases?.releases\n .filter((release) => release.isDeprecated !== undefined)\n .map((release) => [\n release.version.split('.').slice(0, 2).join('.'),\n release.isDeprecated,\n ]),\n );\n const result: ReleaseResult = {\n homepage: 'https://python.org',\n sourceUrl: 'https://github.com/python/cpython',\n registryUrl,\n releases: [],\n };\n try {\n const response = await this.http.getJson(registryUrl, PythonRelease);\n result.releases.push(\n ...response.body\n .filter((release) => release.isStable)\n .filter((release) => pythonPrebuildVersions.has(release.version)),\n );\n } catch (err) {\n if (err instanceof HttpError && err.response?.statusCode === 429) {\n logger.debug(\n { err },\n 'Rate limited by python.org, using prebuild releases',\n );\n result.releases.push(...(pythonPrebuildReleases?.releases ?? []));\n } else {\n this.handleGenericErrors(err);\n }\n }\n for (const release of result.releases) {\n release.isDeprecated = pythonEolVersions.get(\n release.version.split('.').slice(0, 2).join('.'),\n );\n }\n\n return result.releases.length ? result : null;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${datasource}`,\n key: `${config.registryUrl}`,\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,IAAa,0BAAb,cAA6C,WAAW;CACtD,OAAgB,KAAK;CACrB;CACA;CAEA,cAAc;AACZ,QAAM,WAAW;AACjB,OAAK,2BAA2B,IAAI,0BAA0B;AAC9D,OAAK,sBAAsB,IAAI,yBAAyB;;CAG1D,AAAkB,wBAAwB;CAE1C,AAAkB,sBAAsB,CAAC,mBAAmB;CAE5D,AAAkB,oBAAoBA;CAEtC,AAAkB,UAAU;CAE5B,MAAM,sBAAqD;AACzD,SAAO,MAAM,KAAK,yBAAyB,YAAY;GACrD,aAAa;GACb,aAAa;GACd,CAAC;;CAGJ,MAAM,iBAAgD;AACpD,SAAO,MAAM,KAAK,oBAAoB,YAAY;GACnCC;GACb,aAAa;GACd,CAAC;;CAGJ,MAAc,aAAa,EACzB,eACmD;;AAEnD,MAAI,CAAC,YACH,QAAO;EAET,MAAM,yBAAyB,MAAM,KAAK,qBAAqB;EAC/D,MAAM,yBAAyB,IAAI,IACjC,wBAAwB,SAAS,KAAK,YAAY,QAAQ,QAAQ,CACnE;EACD,MAAM,oBAAoB,MAAM,KAAK,gBAAgB;EACrD,MAAM,oBAAoB,IAAI,IAC5B,mBAAmB,SAChB,QAAQ,YAAY,QAAQ,iBAAiB,OAAU,CACvD,KAAK,YAAY,CAChB,QAAQ,QAAQ,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,EAChD,QAAQ,aACT,CAAC,CACL;EACD,MAAM,SAAwB;GAC5B,UAAU;GACV,WAAW;GACX;GACA,UAAU,EAAE;GACb;AACD,MAAI;GACF,MAAM,WAAW,MAAM,KAAK,KAAK,QAAQ,aAAa,cAAc;AACpE,UAAO,SAAS,KACd,GAAG,SAAS,KACT,QAAQ,YAAY,QAAQ,SAAS,CACrC,QAAQ,YAAY,uBAAuB,IAAI,QAAQ,QAAQ,CAAC,CACpE;WACM,KAAK;AACZ,OAAI,eAAeC,gBAAa,IAAI,UAAU,eAAe,KAAK;AAChE,WAAO,MACL,EAAE,KAAK,EACP,sDACD;AACD,WAAO,SAAS,KAAK,GAAI,wBAAwB,YAAY,EAAE,CAAE;SAEjE,MAAK,oBAAoB,IAAI;;AAGjC,OAAK,MAAM,WAAW,OAAO,SAC3B,SAAQ,eAAe,kBAAkB,IACvC,QAAQ,QAAQ,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,CACjD;AAGH,SAAO,OAAO,SAAS,SAAS,SAAS;;CAG3C,YAAY,QAA0D;AACpE,SAAO,UACL;GACE,WAAW,cAAc;GACzB,KAAK,GAAG,OAAO;GACf,UAAU;GACX,QACK,KAAK,aAAa,OAAO,CAChC"}
@@ -328,7 +328,7 @@ async function closeIssue(issueNumber) {
328
328
  * See https://bitbucket.org/tutorials/markdowndemo/src for supported markdown syntax
329
329
  */
330
330
  function massageMarkdown(input) {
331
- let massaged = smartTruncate(input, maxBodyLength()).replace("you tick the rebase/retry checkbox", "by renaming this PR to start with \"rebase!\"").replace("checking the rebase/retry box above", "renaming the PR to start with \"rebase!\"").replace(regEx(/<details>\n(<summary>View abandoned dependencies.*<\/summary>\n\n)([\s\S]*?)<\/details>/), "$2").replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), "").replace(regEx(/\]\(\.\.\/pull\//g), "](../../pull-requests/").replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), "");
331
+ let massaged = smartTruncate(input, maxBodyLength()).replace("you tick the rebase/retry checkbox", "by renaming this PR to start with \"rebase!\"").replace("checking the rebase/retry box above", "renaming the PR to start with \"rebase!\"").replace(regEx(/<details>\n(<summary>View abandoned dependencies.*<\/summary>\n\n)([\s\S]*?)<\/details>/), "$2").replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), "").replace(regEx(/\]\(\.\.\/issues\//g), "](../../issues/").replace(regEx(/\]\(\.\.\/pull\//g), "](../../pull-requests/").replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), "");
332
332
  massaged = massageDetailSummaryHtmlToNestedLists(massaged);
333
333
  return massageCodeblockMarkdown(massaged);
334
334
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["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 { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { UUIDRegex, matchRegexOrGlobList } from '../../../util/string-match.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 { RepoInfo, Repositories, UnresolvedPrTasks } 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 let { body: repos } = await bitbucketHttp.getJson(\n `/2.0/repositories/?role=contributor`,\n { paginate: true },\n Repositories,\n );\n\n // if autodiscoverProjects is configured\n // 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 =\n `/2.0/repositories/${repo}/src/` +\n (finalBranchOrTag ?? `HEAD`) +\n `/${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', false),\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 { hostname } = new URL(defaults.endpoint);\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(/\\]\\(\\.\\.\\/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 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 };\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":["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 { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport { UUIDRegex, matchRegexOrGlobList } from '../../../util/string-match.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 { RepoInfo, Repositories, UnresolvedPrTasks } 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 let { body: repos } = await bitbucketHttp.getJson(\n `/2.0/repositories/?role=contributor`,\n { paginate: true },\n Repositories,\n );\n\n // if autodiscoverProjects is configured\n // 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 =\n `/2.0/repositories/${repo}/src/` +\n (finalBranchOrTag ?? `HEAD`) +\n `/${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', false),\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 { hostname } = new URL(defaults.endpoint);\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 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 };\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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"}
@@ -195,7 +195,7 @@ async function getRepos() {
195
195
  return res;
196
196
  }
197
197
  function massageMarkdown(input) {
198
- return input.replace("you tick the rebase/retry checkbox", "PR is renamed to start with \"rebase!\"").replace("checking the rebase/retry box above", "renaming the PR to start with \"rebase!\"").replace(regEx(/<\/?summary>/g), "**").replace(regEx(/<\/?details>/g), "").replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), "").replace(regEx(/\]\(\.\.\/pull\//g), "](../../pull-requests/").replace(regEx(/(?<hiddenComment><!--renovate-(?:debug|config-hash):.*?-->)/g), "[//]: # ($<hiddenComment>)");
198
+ return input.replace("you tick the rebase/retry checkbox", "PR is renamed to start with \"rebase!\"").replace("checking the rebase/retry box above", "renaming the PR to start with \"rebase!\"").replace(regEx(/<\/?summary>/g), "**").replace(regEx(/<\/?details>/g), "").replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), "").replace(regEx(/\]\(\.\.\/issues\//g), "](#").replace(regEx(/\]\(\.\.\/pull\//g), "](../../pull-requests/").replace(regEx(/(?<hiddenComment><!--renovate-(?:debug|config-hash):.*?-->)/g), "[//]: # ($<hiddenComment>)");
199
199
  }
200
200
  /**
201
201
  * Unsed, no Dashboard
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["client.listRepositories","client.getRepositoryInfo","client.getCodeCommitUrl","git.initRepo","client.listPullRequests","client.getPr","client.getFile","client.createPr","client.updatePrDescription","client.updatePrTitle","client.updatePrStatus","client.createPrApprovalRule","client.getPrComments","client.createPrComment","client.updateComment","client.deleteComment"],"sources":["../../../../lib/modules/platform/codecommit/index.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\nimport type {\n GetCommentsForPullRequestOutput,\n ListRepositoriesOutput,\n} from '@aws-sdk/client-codecommit';\nimport { PullRequestStatusEnum } from '@aws-sdk/client-codecommit';\nimport {\n PLATFORM_BAD_CREDENTIALS,\n REPOSITORY_EMPTY,\n REPOSITORY_NOT_FOUND,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus, PrState } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport type {\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 { getNewBranchName, repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport * as client from './codecommit-client.ts';\n\nexport interface CodeCommitPr extends Pr {\n body: string;\n destinationCommit: string;\n sourceCommit: string;\n}\n\ninterface Config {\n repository?: string;\n defaultBranch?: string;\n region?: string;\n prList?: CodeCommitPr[];\n}\n\nexport const id = 'codecommit';\nexport const experimental = true;\n\nconst platformConfig = {\n endpoint: 'https://git-codecommit.us-east-1.amazonaws.com',\n};\n\nlet config: Config = {} as any;\n\nexport async function initPlatform({\n endpoint,\n username,\n password,\n token: awsToken,\n}: PlatformParams): Promise<PlatformResult> {\n const accessKeyId = username;\n const secretAccessKey = password;\n const env = process.env;\n let region: string | undefined;\n\n if (accessKeyId) {\n env.AWS_ACCESS_KEY_ID = accessKeyId;\n }\n if (secretAccessKey) {\n env.AWS_SECRET_ACCESS_KEY = secretAccessKey;\n }\n if (awsToken) {\n env.AWS_SESSION_TOKEN = awsToken;\n }\n\n if (endpoint) {\n const regionReg = regEx(/.*codecommit\\.(?<region>.+)\\.amazonaws\\.com/);\n const codeCommitMatch = regionReg.exec(endpoint);\n region = codeCommitMatch?.groups?.region;\n if (region) {\n env.AWS_REGION = region;\n } else {\n logger.warn(\"Can't parse region, make sure your endpoint is correct\");\n }\n }\n\n // If any of the below fails, it will throw an exception stopping the program.\n client.buildCodeCommitClient();\n // To check if we have permission to codecommit, throws exception if failed.\n await client.listRepositories();\n\n platformConfig.endpoint =\n endpoint ??\n `https://git-codecommit.${env.AWS_REGION ?? 'us-east-1'}.amazonaws.com/`;\n\n const platformResult: PlatformResult = {\n endpoint: platformConfig.endpoint,\n };\n return platformResult;\n}\n\nexport async function initRepo({\n repository,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(\"${repository}\")`);\n\n config = { repository } as Config;\n\n let repo;\n try {\n repo = await client.getRepositoryInfo(repository);\n } catch (err) {\n logger.error({ err }, 'Could not find repository');\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n\n if (!repo?.repositoryMetadata) {\n logger.error({ repository }, 'Could not find repository');\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n logger.debug({ repositoryDetails: repo }, 'Repository details');\n const metadata = repo.repositoryMetadata;\n\n const url = client.getCodeCommitUrl(metadata, repository);\n try {\n await git.initRepo({\n url,\n });\n } catch (err) {\n logger.debug({ err }, 'Failed to git init');\n throw new Error(PLATFORM_BAD_CREDENTIALS);\n }\n\n if (!metadata.defaultBranch || !metadata.repositoryId) {\n logger.debug('Repo is empty');\n throw new Error(REPOSITORY_EMPTY);\n }\n\n const defaultBranch = metadata.defaultBranch;\n config.defaultBranch = defaultBranch;\n logger.debug(`${repository} default branch = ${defaultBranch}`);\n\n return {\n repoFingerprint: repoFingerprint(\n metadata.repositoryId,\n platformConfig.endpoint,\n ),\n defaultBranch,\n isFork: false,\n };\n}\n\nexport async function getPrList(): Promise<CodeCommitPr[]> {\n logger.debug('getPrList()');\n\n if (config.prList) {\n return config.prList;\n }\n\n const listPrsResponse = await client.listPullRequests(config.repository!);\n const fetchedPrs: CodeCommitPr[] = [];\n\n if (listPrsResponse && !listPrsResponse.pullRequestIds) {\n return fetchedPrs;\n }\n\n const prIds = coerceArray(listPrsResponse.pullRequestIds);\n\n for (const prId of prIds) {\n const prRes = await client.getPr(prId);\n\n if (!prRes?.pullRequest) {\n continue;\n }\n const prInfo = prRes.pullRequest;\n const pr: CodeCommitPr = {\n targetBranch: prInfo.pullRequestTargets![0].destinationReference!,\n sourceBranch: prInfo.pullRequestTargets![0].sourceReference!,\n destinationCommit: prInfo.pullRequestTargets![0].destinationCommit!,\n sourceCommit: prInfo.pullRequestTargets![0].sourceCommit!,\n state:\n prInfo.pullRequestStatus === PullRequestStatusEnum.OPEN\n ? 'open'\n : 'closed',\n number: Number.parseInt(prId),\n title: prInfo.title!,\n body: prInfo.description!,\n createdAt: prInfo.creationDate?.toISOString(),\n };\n fetchedPrs.push(pr);\n }\n\n config.prList = fetchedPrs;\n\n logger.debug(`Retrieved Pull Requests, count: ${fetchedPrs.length}`);\n return fetchedPrs;\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n}: FindPRConfig): Promise<CodeCommitPr | null> {\n let prsFiltered: CodeCommitPr[] = [];\n try {\n const prs = await getPrList();\n const refsHeadBranchName = getNewBranchName(branchName);\n prsFiltered = prs.filter(\n (item) => item.sourceBranch === refsHeadBranchName,\n );\n\n if (prTitle) {\n prsFiltered = prsFiltered.filter(\n (item) => item.title.toUpperCase() === prTitle.toUpperCase(),\n );\n }\n\n switch (state) {\n case 'all':\n break;\n case '!open':\n prsFiltered = prsFiltered.filter((item) => item.state !== 'open');\n break;\n default:\n prsFiltered = prsFiltered.filter((item) => item.state === 'open');\n break;\n }\n } catch (err) {\n logger.error({ err }, 'findPr error');\n }\n if (prsFiltered.length === 0) {\n return null;\n }\n return prsFiltered[0];\n}\n\nexport async function getBranchPr(\n branchName: string,\n): Promise<CodeCommitPr | 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\nexport async function getPr(\n pullRequestId: number,\n): Promise<CodeCommitPr | null> {\n logger.debug(`getPr(${pullRequestId})`);\n const prRes = await client.getPr(`${pullRequestId}`);\n\n if (!prRes?.pullRequest) {\n return null;\n }\n\n const prInfo = prRes.pullRequest;\n let prState: PrState;\n if (prInfo.pullRequestTargets![0].mergeMetadata?.isMerged) {\n prState = 'merged';\n } else {\n prState =\n prInfo.pullRequestStatus === PullRequestStatusEnum.OPEN\n ? 'open'\n : 'closed';\n }\n\n return {\n sourceBranch: prInfo.pullRequestTargets![0].sourceReference!,\n sourceCommit: prInfo.pullRequestTargets![0].sourceCommit!,\n state: prState,\n number: pullRequestId,\n title: prInfo.title!,\n targetBranch: prInfo.pullRequestTargets![0].destinationReference!,\n destinationCommit: prInfo.pullRequestTargets![0].destinationCommit!,\n body: prInfo.description!,\n };\n}\n\nexport async function getRepos(): Promise<string[]> {\n logger.debug('Autodiscovering AWS CodeCommit repositories');\n\n let reposRes: ListRepositoriesOutput;\n try {\n reposRes = await client.listRepositories();\n //todo do we need pagination? maximum number of repos is 1000 without pagination, also the same for free account\n } catch (error) {\n logger.error({ error }, 'Could not retrieve repositories');\n return [];\n }\n\n const res: string[] = [];\n\n const repoNames = coerceArray(reposRes?.repositories);\n\n for (const repo of repoNames) {\n // v8 ignore else -- TODO: add test #40625\n if (repo.repositoryName) {\n res.push(repo.repositoryName);\n }\n }\n\n return res;\n}\n\nexport function massageMarkdown(input: string): string {\n // Remove any HTML we use\n return input\n .replace(\n 'you tick the rebase/retry checkbox',\n 'PR is renamed to start with \"rebase!\"',\n )\n .replace(\n 'checking the rebase/retry box above',\n 'renaming the PR to start with \"rebase!\"',\n )\n .replace(regEx(/<\\/?summary>/g), '**')\n .replace(regEx(/<\\/?details>/g), '')\n .replace(regEx(`\\n---\\n\\n.*?<!-- rebase-check -->.*?\\n`), '')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](../../pull-requests/')\n .replace(\n regEx(/(?<hiddenComment><!--renovate-(?:debug|config-hash):.*?-->)/g),\n '[//]: # ($<hiddenComment>)',\n );\n}\n\n/**\n * Unsed, no Dashboard\n */\nexport function maxBodyLength(): number {\n return Infinity;\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const fileRes = await client.getFile(\n repoName ?? config.repository,\n fileName,\n branchOrTag,\n );\n if (!fileRes?.fileContent) {\n return null;\n }\n const buf = Buffer.from(fileRes.fileContent);\n return buf.toString();\n}\n\nconst AMAZON_MAX_BODY_LENGTH = 10239;\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle: title,\n prBody: body,\n}: CreatePRConfig): Promise<CodeCommitPr> {\n const description = smartTruncate(sanitize(body), AMAZON_MAX_BODY_LENGTH);\n\n const prCreateRes = await client.createPr(\n title,\n sanitize(description),\n sourceBranch,\n targetBranch,\n config.repository,\n );\n\n if (\n !prCreateRes.pullRequest?.title ||\n !prCreateRes.pullRequest?.pullRequestId ||\n !prCreateRes.pullRequest?.description ||\n !prCreateRes.pullRequest?.pullRequestTargets?.length\n ) {\n throw new Error('Could not create pr, missing PR info');\n }\n\n return {\n number: Number.parseInt(prCreateRes.pullRequest.pullRequestId),\n state: 'open',\n title: prCreateRes.pullRequest.title,\n sourceBranch,\n targetBranch,\n sourceCommit: prCreateRes.pullRequest.pullRequestTargets[0].sourceCommit!,\n destinationCommit:\n prCreateRes.pullRequest.pullRequestTargets[0].destinationCommit!,\n sourceRepo: config.repository,\n body: prCreateRes.pullRequest.description,\n };\n}\n\nexport async function updatePr({\n number: prNo,\n prTitle: title,\n prBody: body,\n state,\n}: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prNo}, ${title}, body)`);\n\n let cachedPr: CodeCommitPr | undefined = undefined;\n const cachedPrs = config.prList ?? [];\n for (const p of cachedPrs) {\n // v8 ignore else -- TODO: add test #40625\n if (p.number === prNo) {\n cachedPr = p;\n }\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (body && cachedPr?.body !== body) {\n await client.updatePrDescription(\n `${prNo}`,\n smartTruncate(sanitize(body), AMAZON_MAX_BODY_LENGTH),\n );\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (title && cachedPr?.title !== title) {\n await client.updatePrTitle(`${prNo}`, title);\n }\n\n const prStatusInput =\n state === 'closed'\n ? PullRequestStatusEnum.CLOSED\n : PullRequestStatusEnum.OPEN;\n // v8 ignore else -- TODO: add test #40625\n if (cachedPr?.state !== prStatusInput) {\n try {\n await client.updatePrStatus(`${prNo}`, prStatusInput);\n } catch {\n // safety check\n // do nothing, it's ok to fail sometimes when trying to update from open to open or from closed to closed.\n }\n }\n}\n\n// Auto-Merge not supported currently.\n/* v8 ignore next */\nexport async function mergePr({\n branchName,\n id: prNo,\n}: MergePRConfig): Promise<boolean> {\n logger.debug(`mergePr(${prNo}, ${branchName!})`);\n await client.getPr(`${prNo}`);\n return Promise.resolve(false);\n //\n // /* v8 ignore next */\n // if (!prOut) {\n // return false;\n // }\n // const pReq = prOut.pullRequest;\n // const targets = pReq?.pullRequestTargets;\n //\n // /* v8 ignore next */\n // if (!targets) {\n // return false;\n // }\n //\n // if (strategy === 'rebase') {\n // logger.warn('CodeCommit does not support a \"rebase\" strategy.');\n // return false;\n // }\n //\n // try {\n // if (strategy === 'auto' || strategy === 'squash') {\n // await client.squashMerge(\n // targets[0].repositoryName!,\n // targets[0].sourceReference!,\n // targets[0].destinationReference!,\n // pReq?.title\n // );\n // } else if (strategy === 'fast-forward') {\n // await client.fastForwardMerge(\n // targets[0].repositoryName!,\n // targets[0].sourceReference!,\n // targets[0].destinationReference!\n // );\n // } else {\n // logger.debug(`unsupported strategy`);\n // return false;\n // }\n // } catch (err) {\n // logger.debug({ err }, `PR merge error`);\n // logger.info({ pr: prNo }, 'PR automerge failed');\n // return false;\n // }\n //\n // logger.trace(`Updating PR ${prNo} to status ${PullRequestStatusEnum.CLOSED}`);\n //\n // try {\n // const response = await client.updatePrStatus(\n // `${prNo}`,\n // PullRequestStatusEnum.CLOSED\n // );\n // const isClosed =\n // response.pullRequest?.pullRequestStatus === PullRequestStatusEnum.CLOSED;\n //\n // if (!isClosed) {\n // logger.warn(\n // {\n // pullRequestId: prNo,\n // status: response.pullRequest?.pullRequestStatus,\n // },\n // `Expected PR to have status`\n // );\n // }\n // return true;\n // } catch (err) {\n // logger.debug({ err }, 'Failed to set the PR as Closed.');\n // return false;\n // }\n}\n\nexport async function addReviewers(\n prNo: number,\n reviewers: string[],\n): Promise<void> {\n const numberOfApprovers = reviewers.length;\n const approvalRuleContents = `{\"Version\":\"2018-11-08\",\"Statements\": [{\"Type\": \"Approvers\",\"NumberOfApprovalsNeeded\":${numberOfApprovers},\"ApprovalPoolMembers\": ${JSON.stringify(\n reviewers,\n )}}]}`;\n const res = await client.createPrApprovalRule(\n `${prNo}`,\n approvalRuleContents,\n );\n // v8 ignore else -- TODO: add test #40625\n if (res) {\n const approvalRule = res.approvalRule;\n logger.debug({ approvalRule }, `Approval Rule Added to PR #${prNo}:`);\n }\n}\n\n/* v8 ignore next */\nexport function addAssignees(\n _iid: number,\n _assignees: string[],\n): Promise<void> {\n // CodeCommit does not support adding reviewers\n return Promise.resolve();\n}\n\n/* v8 ignore next */\nexport function findIssue(_title: string): Promise<Issue | null> {\n // CodeCommit does not have issues\n return Promise.resolve(null);\n}\n\n/* v8 ignore next */\nexport function ensureIssue(\n _cfg: EnsureIssueConfig,\n): Promise<EnsureIssueResult | null> {\n // CodeCommit does not have issues\n return Promise.resolve(null);\n}\n\n/* v8 ignore next */\nexport function getIssueList(): Promise<Issue[]> {\n // CodeCommit does not have issues\n return Promise.resolve([]);\n}\n\n/* v8 ignore next */\nexport function ensureIssueClosing(_title: string): Promise<void> {\n // CodeCommit does not have issues\n return Promise.resolve();\n}\n\n/* v8 ignore next */\nexport function deleteLabel(_prNumber: number, _label: string): Promise<void> {\n return Promise.resolve();\n}\n\n// Returns the combined status for a branch.\n/* v8 ignore next */\nexport function getBranchStatus(branchName: string): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n logger.debug(\n 'returning branch status yellow, because getBranchStatus isnt supported on aws yet',\n );\n return Promise.resolve('yellow');\n}\n\n/* v8 ignore next */\nexport function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n logger.debug(`getBranchStatusCheck(${branchName}, context=${context})`);\n logger.debug(\n 'returning null, because getBranchStatusCheck is not supported on aws yet',\n );\n return Promise.resolve(null);\n}\n\n/* v8 ignore next */\nexport function setBranchStatus(_cfg: BranchStatusConfig): Promise<void> {\n return Promise.resolve();\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n logger.debug(`ensureComment(${number}, ${topic!}, content)`);\n const header = topic ? `### ${topic}\\n\\n` : '';\n const body = `${header}${sanitize(content)}`;\n let prCommentsResponse: GetCommentsForPullRequestOutput;\n try {\n prCommentsResponse = await client.getPrComments(`${number}`);\n } catch (err) {\n logger.debug({ err }, 'Unable to retrieve pr comments');\n return false;\n }\n\n let commentId: string | undefined = undefined;\n let commentNeedsUpdating = false;\n\n if (!prCommentsResponse?.commentsForPullRequestData) {\n return false;\n }\n\n for (const commentObj of prCommentsResponse.commentsForPullRequestData) {\n if (!commentObj?.comments) {\n continue;\n }\n const firstCommentContent = commentObj.comments[0].content;\n if (\n (topic && firstCommentContent?.startsWith(header)) === true ||\n (!topic && firstCommentContent === body)\n ) {\n commentId = commentObj.comments[0].commentId;\n commentNeedsUpdating = firstCommentContent !== body;\n break;\n }\n }\n\n if (!commentId) {\n const prs = await getPrList();\n const thisPr = prs.filter((item) => item.number === number);\n\n if (!thisPr[0].sourceCommit || !thisPr[0].destinationCommit) {\n return false;\n }\n\n await client.createPrComment(\n `${number}`,\n config.repository,\n body,\n thisPr[0].destinationCommit,\n thisPr[0].sourceCommit,\n );\n logger.info(\n { repository: config.repository, prNo: number, topic },\n 'Comment added',\n );\n } else if (commentNeedsUpdating && commentId) {\n await client.updateComment(commentId, body);\n\n logger.debug(\n { repository: config.repository, prNo: number, topic },\n 'Comment updated',\n );\n } else {\n logger.debug(\n { repository: config.repository, prNo: number, topic },\n 'Comment is already update-to-date',\n );\n }\n\n return true;\n}\n\nexport async function ensureCommentRemoval(\n removeConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: prNo } = removeConfig;\n const key =\n removeConfig.type === 'by-topic'\n ? removeConfig.topic\n : removeConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${prNo} is removed`);\n\n let prCommentsResponse: GetCommentsForPullRequestOutput;\n try {\n prCommentsResponse = await client.getPrComments(`${prNo}`);\n } catch (err) {\n logger.debug({ err }, 'Unable to retrieve pr comments');\n return;\n }\n\n if (!prCommentsResponse?.commentsForPullRequestData) {\n logger.debug('commentsForPullRequestData not found');\n return;\n }\n\n let commentIdToRemove: string | undefined;\n for (const commentObj of prCommentsResponse.commentsForPullRequestData) {\n if (!commentObj?.comments) {\n logger.debug(\n 'comments object not found under commentsForPullRequestData',\n );\n continue;\n }\n\n for (const comment of commentObj.comments) {\n // v8 ignore else -- TODO: add test #40625\n if (\n (removeConfig.type === 'by-topic' &&\n comment.content?.startsWith(`### ${removeConfig.topic}\\n\\n`)) ===\n true ||\n (removeConfig.type === 'by-content' &&\n removeConfig.content === comment.content?.trim())\n ) {\n commentIdToRemove = comment.commentId;\n break;\n }\n }\n // v8 ignore else -- TODO: add test #40625\n if (commentIdToRemove) {\n await client.deleteComment(commentIdToRemove);\n logger.debug(`comment \"${key}\" in PR #${prNo} was removed`);\n break;\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["client.listRepositories","client.getRepositoryInfo","client.getCodeCommitUrl","git.initRepo","client.listPullRequests","client.getPr","client.getFile","client.createPr","client.updatePrDescription","client.updatePrTitle","client.updatePrStatus","client.createPrApprovalRule","client.getPrComments","client.createPrComment","client.updateComment","client.deleteComment"],"sources":["../../../../lib/modules/platform/codecommit/index.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\nimport type {\n GetCommentsForPullRequestOutput,\n ListRepositoriesOutput,\n} from '@aws-sdk/client-codecommit';\nimport { PullRequestStatusEnum } from '@aws-sdk/client-codecommit';\nimport {\n PLATFORM_BAD_CREDENTIALS,\n REPOSITORY_EMPTY,\n REPOSITORY_NOT_FOUND,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus, PrState } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { parseJson } from '../../../util/common.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport type {\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 { getNewBranchName, repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport * as client from './codecommit-client.ts';\n\nexport interface CodeCommitPr extends Pr {\n body: string;\n destinationCommit: string;\n sourceCommit: string;\n}\n\ninterface Config {\n repository?: string;\n defaultBranch?: string;\n region?: string;\n prList?: CodeCommitPr[];\n}\n\nexport const id = 'codecommit';\nexport const experimental = true;\n\nconst platformConfig = {\n endpoint: 'https://git-codecommit.us-east-1.amazonaws.com',\n};\n\nlet config: Config = {} as any;\n\nexport async function initPlatform({\n endpoint,\n username,\n password,\n token: awsToken,\n}: PlatformParams): Promise<PlatformResult> {\n const accessKeyId = username;\n const secretAccessKey = password;\n const env = process.env;\n let region: string | undefined;\n\n if (accessKeyId) {\n env.AWS_ACCESS_KEY_ID = accessKeyId;\n }\n if (secretAccessKey) {\n env.AWS_SECRET_ACCESS_KEY = secretAccessKey;\n }\n if (awsToken) {\n env.AWS_SESSION_TOKEN = awsToken;\n }\n\n if (endpoint) {\n const regionReg = regEx(/.*codecommit\\.(?<region>.+)\\.amazonaws\\.com/);\n const codeCommitMatch = regionReg.exec(endpoint);\n region = codeCommitMatch?.groups?.region;\n if (region) {\n env.AWS_REGION = region;\n } else {\n logger.warn(\"Can't parse region, make sure your endpoint is correct\");\n }\n }\n\n // If any of the below fails, it will throw an exception stopping the program.\n client.buildCodeCommitClient();\n // To check if we have permission to codecommit, throws exception if failed.\n await client.listRepositories();\n\n platformConfig.endpoint =\n endpoint ??\n `https://git-codecommit.${env.AWS_REGION ?? 'us-east-1'}.amazonaws.com/`;\n\n const platformResult: PlatformResult = {\n endpoint: platformConfig.endpoint,\n };\n return platformResult;\n}\n\nexport async function initRepo({\n repository,\n}: RepoParams): Promise<RepoResult> {\n logger.debug(`initRepo(\"${repository}\")`);\n\n config = { repository } as Config;\n\n let repo;\n try {\n repo = await client.getRepositoryInfo(repository);\n } catch (err) {\n logger.error({ err }, 'Could not find repository');\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n\n if (!repo?.repositoryMetadata) {\n logger.error({ repository }, 'Could not find repository');\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n logger.debug({ repositoryDetails: repo }, 'Repository details');\n const metadata = repo.repositoryMetadata;\n\n const url = client.getCodeCommitUrl(metadata, repository);\n try {\n await git.initRepo({\n url,\n });\n } catch (err) {\n logger.debug({ err }, 'Failed to git init');\n throw new Error(PLATFORM_BAD_CREDENTIALS);\n }\n\n if (!metadata.defaultBranch || !metadata.repositoryId) {\n logger.debug('Repo is empty');\n throw new Error(REPOSITORY_EMPTY);\n }\n\n const defaultBranch = metadata.defaultBranch;\n config.defaultBranch = defaultBranch;\n logger.debug(`${repository} default branch = ${defaultBranch}`);\n\n return {\n repoFingerprint: repoFingerprint(\n metadata.repositoryId,\n platformConfig.endpoint,\n ),\n defaultBranch,\n isFork: false,\n };\n}\n\nexport async function getPrList(): Promise<CodeCommitPr[]> {\n logger.debug('getPrList()');\n\n if (config.prList) {\n return config.prList;\n }\n\n const listPrsResponse = await client.listPullRequests(config.repository!);\n const fetchedPrs: CodeCommitPr[] = [];\n\n if (listPrsResponse && !listPrsResponse.pullRequestIds) {\n return fetchedPrs;\n }\n\n const prIds = coerceArray(listPrsResponse.pullRequestIds);\n\n for (const prId of prIds) {\n const prRes = await client.getPr(prId);\n\n if (!prRes?.pullRequest) {\n continue;\n }\n const prInfo = prRes.pullRequest;\n const pr: CodeCommitPr = {\n targetBranch: prInfo.pullRequestTargets![0].destinationReference!,\n sourceBranch: prInfo.pullRequestTargets![0].sourceReference!,\n destinationCommit: prInfo.pullRequestTargets![0].destinationCommit!,\n sourceCommit: prInfo.pullRequestTargets![0].sourceCommit!,\n state:\n prInfo.pullRequestStatus === PullRequestStatusEnum.OPEN\n ? 'open'\n : 'closed',\n number: Number.parseInt(prId),\n title: prInfo.title!,\n body: prInfo.description!,\n createdAt: prInfo.creationDate?.toISOString(),\n };\n fetchedPrs.push(pr);\n }\n\n config.prList = fetchedPrs;\n\n logger.debug(`Retrieved Pull Requests, count: ${fetchedPrs.length}`);\n return fetchedPrs;\n}\n\nexport async function findPr({\n branchName,\n prTitle,\n state = 'all',\n}: FindPRConfig): Promise<CodeCommitPr | null> {\n let prsFiltered: CodeCommitPr[] = [];\n try {\n const prs = await getPrList();\n const refsHeadBranchName = getNewBranchName(branchName);\n prsFiltered = prs.filter(\n (item) => item.sourceBranch === refsHeadBranchName,\n );\n\n if (prTitle) {\n prsFiltered = prsFiltered.filter(\n (item) => item.title.toUpperCase() === prTitle.toUpperCase(),\n );\n }\n\n switch (state) {\n case 'all':\n break;\n case '!open':\n prsFiltered = prsFiltered.filter((item) => item.state !== 'open');\n break;\n default:\n prsFiltered = prsFiltered.filter((item) => item.state === 'open');\n break;\n }\n } catch (err) {\n logger.error({ err }, 'findPr error');\n }\n if (prsFiltered.length === 0) {\n return null;\n }\n return prsFiltered[0];\n}\n\nexport async function getBranchPr(\n branchName: string,\n): Promise<CodeCommitPr | 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\nexport async function getPr(\n pullRequestId: number,\n): Promise<CodeCommitPr | null> {\n logger.debug(`getPr(${pullRequestId})`);\n const prRes = await client.getPr(`${pullRequestId}`);\n\n if (!prRes?.pullRequest) {\n return null;\n }\n\n const prInfo = prRes.pullRequest;\n let prState: PrState;\n if (prInfo.pullRequestTargets![0].mergeMetadata?.isMerged) {\n prState = 'merged';\n } else {\n prState =\n prInfo.pullRequestStatus === PullRequestStatusEnum.OPEN\n ? 'open'\n : 'closed';\n }\n\n return {\n sourceBranch: prInfo.pullRequestTargets![0].sourceReference!,\n sourceCommit: prInfo.pullRequestTargets![0].sourceCommit!,\n state: prState,\n number: pullRequestId,\n title: prInfo.title!,\n targetBranch: prInfo.pullRequestTargets![0].destinationReference!,\n destinationCommit: prInfo.pullRequestTargets![0].destinationCommit!,\n body: prInfo.description!,\n };\n}\n\nexport async function getRepos(): Promise<string[]> {\n logger.debug('Autodiscovering AWS CodeCommit repositories');\n\n let reposRes: ListRepositoriesOutput;\n try {\n reposRes = await client.listRepositories();\n //todo do we need pagination? maximum number of repos is 1000 without pagination, also the same for free account\n } catch (error) {\n logger.error({ error }, 'Could not retrieve repositories');\n return [];\n }\n\n const res: string[] = [];\n\n const repoNames = coerceArray(reposRes?.repositories);\n\n for (const repo of repoNames) {\n // v8 ignore else -- TODO: add test #40625\n if (repo.repositoryName) {\n res.push(repo.repositoryName);\n }\n }\n\n return res;\n}\n\nexport function massageMarkdown(input: string): string {\n // Remove any HTML we use\n return input\n .replace(\n 'you tick the rebase/retry checkbox',\n 'PR is renamed to start with \"rebase!\"',\n )\n .replace(\n 'checking the rebase/retry box above',\n 'renaming the PR to start with \"rebase!\"',\n )\n .replace(regEx(/<\\/?summary>/g), '**')\n .replace(regEx(/<\\/?details>/g), '')\n .replace(regEx(`\\n---\\n\\n.*?<!-- rebase-check -->.*?\\n`), '')\n .replace(regEx(/\\]\\(\\.\\.\\/issues\\//g), '](#')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](../../pull-requests/')\n .replace(\n regEx(/(?<hiddenComment><!--renovate-(?:debug|config-hash):.*?-->)/g),\n '[//]: # ($<hiddenComment>)',\n );\n}\n\n/**\n * Unsed, no Dashboard\n */\nexport function maxBodyLength(): number {\n return Infinity;\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const fileRes = await client.getFile(\n repoName ?? config.repository,\n fileName,\n branchOrTag,\n );\n if (!fileRes?.fileContent) {\n return null;\n }\n const buf = Buffer.from(fileRes.fileContent);\n return buf.toString();\n}\n\nconst AMAZON_MAX_BODY_LENGTH = 10239;\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle: title,\n prBody: body,\n}: CreatePRConfig): Promise<CodeCommitPr> {\n const description = smartTruncate(sanitize(body), AMAZON_MAX_BODY_LENGTH);\n\n const prCreateRes = await client.createPr(\n title,\n sanitize(description),\n sourceBranch,\n targetBranch,\n config.repository,\n );\n\n if (\n !prCreateRes.pullRequest?.title ||\n !prCreateRes.pullRequest?.pullRequestId ||\n !prCreateRes.pullRequest?.description ||\n !prCreateRes.pullRequest?.pullRequestTargets?.length\n ) {\n throw new Error('Could not create pr, missing PR info');\n }\n\n return {\n number: Number.parseInt(prCreateRes.pullRequest.pullRequestId),\n state: 'open',\n title: prCreateRes.pullRequest.title,\n sourceBranch,\n targetBranch,\n sourceCommit: prCreateRes.pullRequest.pullRequestTargets[0].sourceCommit!,\n destinationCommit:\n prCreateRes.pullRequest.pullRequestTargets[0].destinationCommit!,\n sourceRepo: config.repository,\n body: prCreateRes.pullRequest.description,\n };\n}\n\nexport async function updatePr({\n number: prNo,\n prTitle: title,\n prBody: body,\n state,\n}: UpdatePrConfig): Promise<void> {\n logger.debug(`updatePr(${prNo}, ${title}, body)`);\n\n let cachedPr: CodeCommitPr | undefined = undefined;\n const cachedPrs = config.prList ?? [];\n for (const p of cachedPrs) {\n // v8 ignore else -- TODO: add test #40625\n if (p.number === prNo) {\n cachedPr = p;\n }\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (body && cachedPr?.body !== body) {\n await client.updatePrDescription(\n `${prNo}`,\n smartTruncate(sanitize(body), AMAZON_MAX_BODY_LENGTH),\n );\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (title && cachedPr?.title !== title) {\n await client.updatePrTitle(`${prNo}`, title);\n }\n\n const prStatusInput =\n state === 'closed'\n ? PullRequestStatusEnum.CLOSED\n : PullRequestStatusEnum.OPEN;\n // v8 ignore else -- TODO: add test #40625\n if (cachedPr?.state !== prStatusInput) {\n try {\n await client.updatePrStatus(`${prNo}`, prStatusInput);\n } catch {\n // safety check\n // do nothing, it's ok to fail sometimes when trying to update from open to open or from closed to closed.\n }\n }\n}\n\n// Auto-Merge not supported currently.\n/* v8 ignore next */\nexport async function mergePr({\n branchName,\n id: prNo,\n}: MergePRConfig): Promise<boolean> {\n logger.debug(`mergePr(${prNo}, ${branchName!})`);\n await client.getPr(`${prNo}`);\n return Promise.resolve(false);\n //\n // /* v8 ignore next */\n // if (!prOut) {\n // return false;\n // }\n // const pReq = prOut.pullRequest;\n // const targets = pReq?.pullRequestTargets;\n //\n // /* v8 ignore next */\n // if (!targets) {\n // return false;\n // }\n //\n // if (strategy === 'rebase') {\n // logger.warn('CodeCommit does not support a \"rebase\" strategy.');\n // return false;\n // }\n //\n // try {\n // if (strategy === 'auto' || strategy === 'squash') {\n // await client.squashMerge(\n // targets[0].repositoryName!,\n // targets[0].sourceReference!,\n // targets[0].destinationReference!,\n // pReq?.title\n // );\n // } else if (strategy === 'fast-forward') {\n // await client.fastForwardMerge(\n // targets[0].repositoryName!,\n // targets[0].sourceReference!,\n // targets[0].destinationReference!\n // );\n // } else {\n // logger.debug(`unsupported strategy`);\n // return false;\n // }\n // } catch (err) {\n // logger.debug({ err }, `PR merge error`);\n // logger.info({ pr: prNo }, 'PR automerge failed');\n // return false;\n // }\n //\n // logger.trace(`Updating PR ${prNo} to status ${PullRequestStatusEnum.CLOSED}`);\n //\n // try {\n // const response = await client.updatePrStatus(\n // `${prNo}`,\n // PullRequestStatusEnum.CLOSED\n // );\n // const isClosed =\n // response.pullRequest?.pullRequestStatus === PullRequestStatusEnum.CLOSED;\n //\n // if (!isClosed) {\n // logger.warn(\n // {\n // pullRequestId: prNo,\n // status: response.pullRequest?.pullRequestStatus,\n // },\n // `Expected PR to have status`\n // );\n // }\n // return true;\n // } catch (err) {\n // logger.debug({ err }, 'Failed to set the PR as Closed.');\n // return false;\n // }\n}\n\nexport async function addReviewers(\n prNo: number,\n reviewers: string[],\n): Promise<void> {\n const numberOfApprovers = reviewers.length;\n const approvalRuleContents = `{\"Version\":\"2018-11-08\",\"Statements\": [{\"Type\": \"Approvers\",\"NumberOfApprovalsNeeded\":${numberOfApprovers},\"ApprovalPoolMembers\": ${JSON.stringify(\n reviewers,\n )}}]}`;\n const res = await client.createPrApprovalRule(\n `${prNo}`,\n approvalRuleContents,\n );\n // v8 ignore else -- TODO: add test #40625\n if (res) {\n const approvalRule = res.approvalRule;\n logger.debug({ approvalRule }, `Approval Rule Added to PR #${prNo}:`);\n }\n}\n\n/* v8 ignore next */\nexport function addAssignees(\n _iid: number,\n _assignees: string[],\n): Promise<void> {\n // CodeCommit does not support adding reviewers\n return Promise.resolve();\n}\n\n/* v8 ignore next */\nexport function findIssue(_title: string): Promise<Issue | null> {\n // CodeCommit does not have issues\n return Promise.resolve(null);\n}\n\n/* v8 ignore next */\nexport function ensureIssue(\n _cfg: EnsureIssueConfig,\n): Promise<EnsureIssueResult | null> {\n // CodeCommit does not have issues\n return Promise.resolve(null);\n}\n\n/* v8 ignore next */\nexport function getIssueList(): Promise<Issue[]> {\n // CodeCommit does not have issues\n return Promise.resolve([]);\n}\n\n/* v8 ignore next */\nexport function ensureIssueClosing(_title: string): Promise<void> {\n // CodeCommit does not have issues\n return Promise.resolve();\n}\n\n/* v8 ignore next */\nexport function deleteLabel(_prNumber: number, _label: string): Promise<void> {\n return Promise.resolve();\n}\n\n// Returns the combined status for a branch.\n/* v8 ignore next */\nexport function getBranchStatus(branchName: string): Promise<BranchStatus> {\n logger.debug(`getBranchStatus(${branchName})`);\n logger.debug(\n 'returning branch status yellow, because getBranchStatus isnt supported on aws yet',\n );\n return Promise.resolve('yellow');\n}\n\n/* v8 ignore next */\nexport function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n logger.debug(`getBranchStatusCheck(${branchName}, context=${context})`);\n logger.debug(\n 'returning null, because getBranchStatusCheck is not supported on aws yet',\n );\n return Promise.resolve(null);\n}\n\n/* v8 ignore next */\nexport function setBranchStatus(_cfg: BranchStatusConfig): Promise<void> {\n return Promise.resolve();\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n logger.debug(`ensureComment(${number}, ${topic!}, content)`);\n const header = topic ? `### ${topic}\\n\\n` : '';\n const body = `${header}${sanitize(content)}`;\n let prCommentsResponse: GetCommentsForPullRequestOutput;\n try {\n prCommentsResponse = await client.getPrComments(`${number}`);\n } catch (err) {\n logger.debug({ err }, 'Unable to retrieve pr comments');\n return false;\n }\n\n let commentId: string | undefined = undefined;\n let commentNeedsUpdating = false;\n\n if (!prCommentsResponse?.commentsForPullRequestData) {\n return false;\n }\n\n for (const commentObj of prCommentsResponse.commentsForPullRequestData) {\n if (!commentObj?.comments) {\n continue;\n }\n const firstCommentContent = commentObj.comments[0].content;\n if (\n (topic && firstCommentContent?.startsWith(header)) === true ||\n (!topic && firstCommentContent === body)\n ) {\n commentId = commentObj.comments[0].commentId;\n commentNeedsUpdating = firstCommentContent !== body;\n break;\n }\n }\n\n if (!commentId) {\n const prs = await getPrList();\n const thisPr = prs.filter((item) => item.number === number);\n\n if (!thisPr[0].sourceCommit || !thisPr[0].destinationCommit) {\n return false;\n }\n\n await client.createPrComment(\n `${number}`,\n config.repository,\n body,\n thisPr[0].destinationCommit,\n thisPr[0].sourceCommit,\n );\n logger.info(\n { repository: config.repository, prNo: number, topic },\n 'Comment added',\n );\n } else if (commentNeedsUpdating && commentId) {\n await client.updateComment(commentId, body);\n\n logger.debug(\n { repository: config.repository, prNo: number, topic },\n 'Comment updated',\n );\n } else {\n logger.debug(\n { repository: config.repository, prNo: number, topic },\n 'Comment is already update-to-date',\n );\n }\n\n return true;\n}\n\nexport async function ensureCommentRemoval(\n removeConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: prNo } = removeConfig;\n const key =\n removeConfig.type === 'by-topic'\n ? removeConfig.topic\n : removeConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${prNo} is removed`);\n\n let prCommentsResponse: GetCommentsForPullRequestOutput;\n try {\n prCommentsResponse = await client.getPrComments(`${prNo}`);\n } catch (err) {\n logger.debug({ err }, 'Unable to retrieve pr comments');\n return;\n }\n\n if (!prCommentsResponse?.commentsForPullRequestData) {\n logger.debug('commentsForPullRequestData not found');\n return;\n }\n\n let commentIdToRemove: string | undefined;\n for (const commentObj of prCommentsResponse.commentsForPullRequestData) {\n if (!commentObj?.comments) {\n logger.debug(\n 'comments object not found under commentsForPullRequestData',\n );\n continue;\n }\n\n for (const comment of commentObj.comments) {\n // v8 ignore else -- TODO: add test #40625\n if (\n (removeConfig.type === 'by-topic' &&\n comment.content?.startsWith(`### ${removeConfig.topic}\\n\\n`)) ===\n true ||\n (removeConfig.type === 'by-content' &&\n removeConfig.content === comment.content?.trim())\n ) {\n commentIdToRemove = comment.commentId;\n break;\n }\n }\n // v8 ignore else -- TODO: add test #40625\n if (commentIdToRemove) {\n await client.deleteComment(commentIdToRemove);\n logger.debug(`comment \"${key}\" in PR #${prNo} was removed`);\n break;\n }\n }\n}\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ import { isNonEmptyArray } from "@sindresorhus/is";
8
8
 
9
9
  //#region lib/modules/platform/forgejo/utils.ts
10
10
  function smartLinks(body) {
11
- return body?.replace(regEx(/\]\(\.\.\/pull\//g), "](pulls/");
11
+ return body?.replace(regEx(/\]\(\.\.\/issues\//g), "](issues/").replace(regEx(/\]\(\.\.\/pull\//g), "](pulls/");
12
12
  }
13
13
  function trimTrailingApiPath(url) {
14
14
  return url?.replace(regEx(/api\/v1\/?$/g), "");
@@ -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 {\n CONFIG_GIT_URL_UNAVAILABLE,\n REPOSITORY_BLOCKED,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.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 './types.ts';\n\nexport function smartLinks(body: string): string {\n return body?.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 (!data) {\n return null;\n }\n\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?.username;\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 = (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 logger.debug('Repo has unknown merge style - aborting renovation');\n throw new Error(REPOSITORY_BLOCKED);\n}\n"],"mappings":"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"}
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 {\n CONFIG_GIT_URL_UNAVAILABLE,\n REPOSITORY_BLOCKED,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.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 './types.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 (!data) {\n return null;\n }\n\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?.username;\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 = (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 logger.debug('Repo has unknown merge style - aborting renovation');\n throw new Error(REPOSITORY_BLOCKED);\n}\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ import { isNonEmptyArray } from "@sindresorhus/is";
8
8
 
9
9
  //#region lib/modules/platform/gitea/utils.ts
10
10
  function smartLinks(body) {
11
- return body?.replace(regEx(/\]\(\.\.\/pull\//g), "](pulls/");
11
+ return body?.replace(regEx(/\]\(\.\.\/issues\//g), "](issues/").replace(regEx(/\]\(\.\.\/pull\//g), "](pulls/");
12
12
  }
13
13
  function trimTrailingApiPath(url) {
14
14
  return url?.replace(regEx(/api\/v1\/?$/g), "");
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":["hostRules.find"],"sources":["../../../../lib/modules/platform/gitea/utils.ts"],"sourcesContent":["import { isNonEmptyArray } from '@sindresorhus/is';\nimport type { MergeStrategy } from '../../../config/types.ts';\nimport {\n CONFIG_GIT_URL_UNAVAILABLE,\n REPOSITORY_BLOCKED,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.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 './types.ts';\n\nexport function smartLinks(body: string): string {\n return body?.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: 'gitea',\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 (!data) {\n return null;\n }\n\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?.username;\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 = (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 logger.debug('Repo has unknown merge style - aborting renovation');\n throw new Error(REPOSITORY_BLOCKED);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","names":["hostRules.find"],"sources":["../../../../lib/modules/platform/gitea/utils.ts"],"sourcesContent":["import { isNonEmptyArray } from '@sindresorhus/is';\nimport type { MergeStrategy } from '../../../config/types.ts';\nimport {\n CONFIG_GIT_URL_UNAVAILABLE,\n REPOSITORY_BLOCKED,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.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 './types.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: 'gitea',\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 (!data) {\n return null;\n }\n\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?.username;\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 = (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 logger.debug('Repo has unknown merge style - aborting renovation');\n throw new Error(REPOSITORY_BLOCKED);\n}\n"],"mappings":"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"}
@@ -426,7 +426,7 @@ async function mergePr({ id }) {
426
426
  }
427
427
  }
428
428
  function massageMarkdown(input) {
429
- return smartTruncate(input.replace(regEx(/Pull Request/g), "Merge Request").replace(regEx(/\bPR: #/g), "MR: !").replace(regEx(/\bPR\b/g), "MR").replace(regEx(/\bPRs\b/g), "MRs").replace(regEx(/\]\(\.\.\/pull\//g), "](!").replace(regEx(/\u0000/g), ""), maxBodyLength());
429
+ return smartTruncate(input.replace(regEx(/Pull Request/g), "Merge Request").replace(regEx(/\bPR: #/g), "MR: !").replace(regEx(/\bPR\b/g), "MR").replace(regEx(/\bPRs\b/g), "MRs").replace(regEx(/\]\(\.\.\/pull\//g), "](!").replace(regEx(/\]\(\.\.\/issues\//g), "](#").replace(regEx(/\u0000/g), ""), maxBodyLength());
430
430
  }
431
431
  function maxBodyLength() {
432
432
  if (semver.lt(defaults.version, "13.4.0")) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["git.initRepo","git.getBranchCommit","git.branchExists","p.all"],"sources":["../../../../lib/modules/platform/gitlab/index.ts"],"sourcesContent":["import { isArray, isEmptyArray, isNonEmptyArray } from '@sindresorhus/is';\nimport pMap from 'p-map';\nimport semver from 'semver';\nimport { setTimeout } from 'timers/promises';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n REPOSITORY_ACCESS_FORBIDDEN,\n REPOSITORY_ARCHIVED,\n REPOSITORY_CHANGED,\n REPOSITORY_DISABLED,\n REPOSITORY_EMPTY,\n REPOSITORY_MIRRORED,\n REPOSITORY_NOT_FOUND,\n TEMPORARY_ERROR,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { noLeadingAtSymbol, parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { GitlabHttpOptions } from '../../../util/http/gitlab.ts';\nimport { setBaseUrl } from '../../../util/http/gitlab.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { parseInteger } from '../../../util/number.ts';\nimport * as p from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport type { EmailAddress } from '../../../util/schema-utils/index.ts';\nimport { ensureTrailingSlash, getQueryString } from '../../../util/url.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformPrOptions,\n PlatformResult,\n Pr,\n ReattemptPlatformAutomergeConfig,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport {\n getMemberUserIDs,\n getMemberUsernames,\n getUserID,\n gitlabApi,\n isUserBusy,\n} from './http.ts';\nimport { getMR, updateMR } from './merge-request.ts';\nimport { GitlabPrCache } from './pr-cache.ts';\nimport type { GitLabMergeRequest } from './schema.ts';\nimport { LastPipelineId } from './schema.ts';\nimport type {\n GitlabComment,\n GitlabIssue,\n GitlabPr,\n MergeMethod,\n RepoResponse,\n} from './types.ts';\nimport {\n DRAFT_PREFIX,\n DRAFT_PREFIX_DEPRECATED,\n defaults,\n getRepoUrl,\n prInfo,\n} from './utils.ts';\n\nexport { extractRulesFromCodeOwnersLines } from './code-owners.ts';\n\nlet config: {\n repository: string;\n email: EmailAddress;\n issueList: GitlabIssue[] | undefined;\n mergeMethod: MergeMethod;\n mergeTrainsEnabled: boolean;\n defaultBranch: string;\n cloneSubmodules: boolean | undefined;\n cloneSubmodulesFilter: string[] | undefined;\n ignorePrAuthor: boolean | undefined;\n squash: boolean;\n} = {} as any;\n\nexport function resetPlatform(): void {\n config = {} as any;\n draftPrefix = DRAFT_PREFIX;\n defaults.hostType = 'gitlab';\n defaults.endpoint = 'https://gitlab.com/api/v4/';\n defaults.version = '0.0.0';\n setBaseUrl(defaults.endpoint);\n}\n\nexport const id = 'gitlab';\n\nlet draftPrefix = DRAFT_PREFIX;\nlet botUserName: string;\n\nexport async function initPlatform({\n endpoint,\n username,\n token,\n gitAuthor,\n}: PlatformParams): Promise<PlatformResult> {\n if (!token) {\n throw new Error('Init: You must configure a GitLab personal access token');\n }\n if (endpoint) {\n defaults.endpoint = ensureTrailingSlash(endpoint);\n setBaseUrl(defaults.endpoint);\n } else {\n logger.debug('Using default GitLab endpoint: ' + defaults.endpoint);\n }\n const platformConfig: PlatformResult = {\n endpoint: defaults.endpoint,\n };\n let gitlabVersion: string;\n try {\n if (!gitAuthor) {\n const user = (\n await gitlabApi.getJsonUnchecked<{\n email: EmailAddress;\n name: string;\n id: number;\n commit_email?: EmailAddress;\n }>(`user`, { token })\n ).body;\n platformConfig.gitAuthor = `${user.name} <${\n user.commit_email ?? user.email\n }>`;\n botUserName = user.name;\n }\n const env = getEnv();\n /* v8 ignore next: experimental feature */\n if (env.RENOVATE_X_PLATFORM_VERSION) {\n gitlabVersion = env.RENOVATE_X_PLATFORM_VERSION;\n } else {\n const version = (\n await gitlabApi.getJsonUnchecked<{ version: string }>('version', {\n token,\n })\n ).body;\n gitlabVersion = version.version;\n }\n logger.debug('GitLab version is: ' + gitlabVersion);\n // version is 'x.y.z-edition', so not strictly semver; need to strip edition\n [gitlabVersion] = gitlabVersion.split('-');\n defaults.version = gitlabVersion;\n } catch (err) {\n logger.debug(\n { err },\n 'Error authenticating with GitLab. Check that your token includes \"api\" permissions',\n );\n throw new Error('Init: Authentication failure');\n }\n draftPrefix = semver.lt(defaults.version, '13.2.0')\n ? DRAFT_PREFIX_DEPRECATED\n : DRAFT_PREFIX;\n\n botUserName ??= username!;\n\n return 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 GitLab repositories');\n\n const queryParams: Record<string, any> = {\n membership: true,\n per_page: 100,\n with_merge_requests_enabled: true,\n min_access_level: 30,\n archived: false,\n ...(config?.sort && { order_by: config.sort }),\n ...(config?.order && { sort: config.order }),\n };\n if (config?.topics?.length) {\n queryParams.topic = config.topics.join(',');\n }\n\n const urls = [];\n if (config?.namespaces?.length) {\n queryParams.with_shared = false;\n queryParams.include_subgroups = true;\n urls.push(\n ...config.namespaces.map(\n (namespace) =>\n `groups/${urlEscape(namespace)}/projects?${getQueryString(\n queryParams,\n )}`,\n ),\n );\n } else {\n urls.push('projects?' + getQueryString(queryParams));\n }\n\n try {\n const repos = (\n await pMap(\n urls,\n (url) =>\n gitlabApi.getJsonUnchecked<RepoResponse[]>(url, {\n paginate: true,\n }),\n {\n concurrency: 2,\n },\n )\n ).flatMap((response) => response.body);\n\n logger.debug(`Discovered ${repos.length} project(s)`);\n return repos\n .filter((repo) => !repo.mirror || config?.includeMirrors)\n .map((repo) => repo.path_with_namespace);\n } catch (err) {\n logger.error({ err }, `GitLab getRepos error`);\n throw err;\n }\n}\n\nfunction urlEscape(str: string): string;\nfunction urlEscape(str: string | undefined): string | undefined;\nfunction urlEscape(str: string | undefined): string | undefined {\n return str?.replace(regEx(/\\//g), '%2F');\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const escapedFileName = urlEscape(fileName);\n const repo = urlEscape(repoName) ?? config.repository;\n const url =\n `projects/${repo}/repository/files/${escapedFileName}?ref=` +\n (branchOrTag ?? `HEAD`);\n const res = await gitlabApi.getJsonUnchecked<{ content: string }>(url, {\n cacheProvider: memCacheProvider,\n });\n const buf = res.body.content;\n const str = Buffer.from(buf, 'base64').toString();\n return str;\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\n// Initialize GitLab by getting base branch\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n gitUrl,\n}: RepoParams): Promise<RepoResult> {\n config = {} as any;\n config.repository = urlEscape(repository);\n config.cloneSubmodules = cloneSubmodules;\n config.cloneSubmodulesFilter = cloneSubmodulesFilter;\n config.ignorePrAuthor = GlobalConfig.get('ignorePrAuthor');\n\n let res: HttpResponse<RepoResponse>;\n try {\n res = await gitlabApi.getJsonUnchecked<RepoResponse>(\n `projects/${config.repository}`,\n );\n if (res.body.archived) {\n logger.debug(\n 'Repository is archived - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_ARCHIVED);\n }\n\n if (res.body.mirror && GlobalConfig.get('includeMirrors') !== true) {\n logger.debug(\n 'Repository is a mirror - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_MIRRORED);\n }\n if (res.body.repository_access_level === 'disabled') {\n logger.debug(\n 'Repository portion of project is disabled - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_DISABLED);\n }\n if (res.body.merge_requests_access_level === 'disabled') {\n logger.debug(\n 'MRs are disabled for the project - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_DISABLED);\n }\n if (res.body.default_branch === null || res.body.empty_repo) {\n throw new Error(REPOSITORY_EMPTY);\n }\n config.defaultBranch = res.body.default_branch;\n /* v8 ignore next */\n if (!config.defaultBranch) {\n logger.warn({ resBody: res.body }, 'Error fetching GitLab project');\n throw new Error(TEMPORARY_ERROR);\n }\n config.mergeMethod = res.body.merge_method || 'merge';\n config.mergeTrainsEnabled = res.body.merge_trains_enabled ?? false;\n if (res.body.squash_option) {\n config.squash =\n res.body.squash_option === 'always' ||\n res.body.squash_option === 'default_on';\n }\n logger.debug(`${repository} default branch = ${config.defaultBranch}`);\n logger.debug('Enabling Git FS');\n const url = getRepoUrl(repository, gitUrl, res);\n await git.initRepo({\n ...config,\n url,\n });\n } catch (err) /* v8 ignore next */ {\n logger.debug({ err }, 'Caught initRepo error');\n if (err.message.includes('HEAD is not a symbolic ref')) {\n throw new Error(REPOSITORY_EMPTY);\n }\n if ([REPOSITORY_ARCHIVED, REPOSITORY_EMPTY].includes(err.message)) {\n throw err;\n }\n if (err.statusCode === 403) {\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n if (err.statusCode === 404) {\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n if (err.message === REPOSITORY_DISABLED) {\n throw err;\n }\n logger.debug({ err }, 'Unknown GitLab initRepo error');\n throw err;\n }\n const repoConfig: RepoResult = {\n defaultBranch: config.defaultBranch,\n isFork: !!res.body.forked_from_project,\n repoFingerprint: repoFingerprint(res.body.id, defaults.endpoint),\n };\n return repoConfig;\n}\n\nexport function getBranchForceRebase(): Promise<boolean> {\n const forceRebase =\n config?.mergeMethod !== 'merge' && !config.mergeTrainsEnabled;\n if (forceRebase) {\n logger.once.debug(\n `mergeMethod is ${config.mergeMethod} so PRs will be kept up-to-date with base branch`,\n );\n }\n return Promise.resolve(forceRebase);\n}\n\ntype BranchState =\n | 'pending'\n | 'created'\n | 'running'\n | 'waiting_for_resource'\n | 'manual'\n | 'success'\n | 'failed'\n | 'canceled'\n | 'skipped'\n | 'scheduled';\n\ninterface GitlabBranchStatus {\n status: BranchState;\n name: string;\n allow_failure?: boolean;\n}\n\nasync function getStatus(\n branchName: string,\n useCache = true,\n): Promise<GitlabBranchStatus[]> {\n const branchSha = git.getBranchCommit(branchName);\n try {\n // TODO: types (#22198)\n const url = `projects/${\n config.repository\n }/repository/commits/${branchSha!}/statuses`;\n\n const opts: GitlabHttpOptions = { paginate: true };\n if (useCache) {\n opts.cacheProvider = memCacheProvider;\n } else {\n opts.memCache = false;\n }\n\n return (await gitlabApi.getJsonUnchecked<GitlabBranchStatus[]>(url, opts))\n .body;\n } catch (err) /* v8 ignore next */ {\n logger.debug({ err }, 'Error getting commit status');\n if (err.response?.statusCode === 404) {\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n}\n\nconst gitlabToRenovateStatusMapping: Record<BranchState, BranchStatus> = {\n pending: 'yellow',\n created: 'yellow',\n manual: 'yellow',\n running: 'yellow',\n waiting_for_resource: 'yellow',\n success: 'green',\n failed: 'red',\n canceled: 'red',\n skipped: 'red',\n scheduled: 'yellow',\n};\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\n if (!git.branchExists(branchName)) {\n throw new Error(REPOSITORY_CHANGED);\n }\n\n const branchStatuses = await getStatus(branchName);\n /* v8 ignore next */\n if (!isArray(branchStatuses)) {\n logger.warn(\n { branchName, branchStatuses },\n 'Empty or unexpected branch statuses',\n );\n return 'yellow';\n }\n logger.debug(`Got res with ${branchStatuses.length} results`);\n\n const mr = await getBranchPr(branchName);\n if (mr && mr.sha !== mr.headPipelineSha && mr.headPipelineStatus) {\n logger.debug(\n 'Merge request head pipeline has different sha to commit, assuming merged results pipeline',\n );\n branchStatuses.push({\n status: mr.headPipelineStatus as BranchState,\n name: 'head_pipeline',\n });\n }\n // ignore all skipped jobs\n const res = branchStatuses.filter((check) => check.status !== 'skipped');\n if (res.length === 0) {\n // Return 'pending' if we have no status checks\n return 'yellow';\n }\n if (\n !internalChecksAsSuccess &&\n branchStatuses.every(\n (check) =>\n check.name?.startsWith('renovate/') &&\n gitlabToRenovateStatusMapping[check.status] === 'green',\n )\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n let status: BranchStatus = 'green'; // default to green\n res\n .filter((check) => !check.allow_failure)\n .forEach((check) => {\n // v8 ignore else -- TODO: add test #40625\n if (status !== 'red') {\n // if red, stay red\n let mappedStatus: BranchStatus =\n gitlabToRenovateStatusMapping[check.status];\n if (!mappedStatus) {\n logger.warn(\n { check },\n 'Could not map GitLab check.status to Renovate status',\n );\n mappedStatus = 'yellow';\n }\n if (mappedStatus !== 'green') {\n logger.trace({ check }, 'Found non-green check');\n status = mappedStatus;\n }\n }\n });\n return status;\n}\n\n// Pull Request\nexport async function getPrList(): Promise<Pr[]> {\n return await GitlabPrCache.getPrs(\n gitlabApi,\n config.repository,\n botUserName,\n !!config.ignorePrAuthor,\n );\n}\n\nasync function ignoreApprovals(pr: number): Promise<void> {\n try {\n const url = `projects/${config.repository}/merge_requests/${pr}/approval_rules`;\n const { body: rules } = await gitlabApi.getJsonUnchecked<\n {\n name: string;\n rule_type: string;\n id: number;\n }[]\n >(url);\n\n const ruleName = 'renovateIgnoreApprovals';\n\n const existingAnyApproverRule = rules?.find(\n ({ rule_type }) => rule_type === 'any_approver',\n );\n const existingRegularApproverRules = rules?.filter(\n ({ rule_type, name }) =>\n rule_type !== 'any_approver' &&\n name !== ruleName &&\n rule_type !== 'report_approver' &&\n rule_type !== 'code_owner',\n );\n\n if (existingRegularApproverRules?.length) {\n await p.all(\n existingRegularApproverRules.map((rule) => async (): Promise<void> => {\n await gitlabApi.deleteJson(`${url}/${rule.id}`);\n }),\n );\n }\n\n if (existingAnyApproverRule) {\n await gitlabApi.putJson(`${url}/${existingAnyApproverRule.id}`, {\n body: { ...existingAnyApproverRule, approvals_required: 0 },\n });\n return;\n }\n\n const zeroApproversRule = rules?.find(({ name }) => name === ruleName);\n if (!zeroApproversRule) {\n await gitlabApi.postJson(url, {\n body: {\n name: ruleName,\n approvals_required: 0,\n },\n });\n }\n } catch (err) {\n logger.warn({ err }, 'GitLab: Error adding approval rule');\n }\n}\n\nasync function tryPrAutomerge(\n pr: number,\n platformPrOptions: PlatformPrOptions | undefined,\n): Promise<void> {\n try {\n if (platformPrOptions?.gitLabIgnoreApprovals) {\n await ignoreApprovals(pr);\n }\n\n if (platformPrOptions?.usePlatformAutomerge) {\n // https://docs.gitlab.com/ee/api/merge_requests.html#merge-status\n const desiredDetailedMergeStatus = [\n 'mergeable',\n 'ci_still_running',\n 'not_approved',\n ];\n const desiredPipelineStatus = [\n 'failed', // don't lose time if pipeline failed\n 'running', // pipeline is running, no need to wait for it\n ];\n const desiredStatus = 'can_be_merged';\n const env = getEnv();\n // The default value of 5 attempts results in max. 13.75 seconds timeout if no pipeline created.\n const retryTimes = parseInteger(\n env.RENOVATE_X_GITLAB_AUTO_MERGEABLE_CHECK_ATTEMPS,\n 5,\n );\n\n const mergeDelay = parseInteger(\n env.RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY,\n 250,\n );\n\n // Check for correct merge request status before setting `merge_when_pipeline_succeeds` to `true`.\n for (let attempt = 1; attempt <= retryTimes; attempt += 1) {\n const { body } = await gitlabApi.getJsonUnchecked<{\n merge_status: string;\n detailed_merge_status?: string;\n merge_when_pipeline_succeeds?: boolean;\n pipeline: {\n status: string;\n };\n }>(`projects/${config.repository}/merge_requests/${pr}`, {\n memCache: false,\n });\n\n // Exit early if merge_when_pipeline_succeeds is already set\n if (body.merge_when_pipeline_succeeds === true) {\n logger.debug(\n 'Skipping automerge retry - merge_when_pipeline_succeeds already enabled',\n );\n return;\n }\n // detailed_merge_status is available with Gitlab >=15.6.0\n const use_detailed_merge_status = !!body.detailed_merge_status;\n const detailed_merge_status_check =\n use_detailed_merge_status &&\n desiredDetailedMergeStatus.includes(body.detailed_merge_status!);\n // merge_status is deprecated with Gitlab >= 15.6\n const deprecated_merge_status_check =\n !use_detailed_merge_status && body.merge_status === desiredStatus;\n\n // Only continue if the merge request can be merged and has a pipeline.\n if (\n (detailed_merge_status_check || deprecated_merge_status_check) &&\n body.pipeline !== null &&\n desiredPipelineStatus.includes(body.pipeline.status)\n ) {\n break;\n }\n logger.debug(`PR not yet in mergeable state. Retrying ${attempt}`);\n await setTimeout(mergeDelay * attempt ** 2); // exponential backoff\n }\n\n // Even if Gitlab returns a \"merge-able\" merge request status, enabling auto-merge sometimes\n // returns a 405 Method Not Allowed. It seems to be a timing issue within Gitlab.\n for (let attempt = 1; attempt <= retryTimes; attempt += 1) {\n try {\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${pr}/merge`,\n {\n body: {\n should_remove_source_branch: true,\n merge_when_pipeline_succeeds: true,\n },\n },\n );\n break;\n } catch (err) {\n logger.debug(\n { err },\n `Automerge on PR creation failed. Retrying ${attempt}`,\n );\n }\n await setTimeout(mergeDelay * attempt ** 2); // exponential backoff\n }\n }\n } catch (err) /* v8 ignore next */ {\n logger.debug({ err }, 'Automerge on PR creation failed');\n }\n}\n\nasync function approveMr(mrNumber: number): Promise<void> {\n const env = getEnv();\n const opts: GitlabHttpOptions = {};\n if (env.RENOVATE_X_GITLAB_AUTO_APPROVE_TOKEN) {\n opts.token = env.RENOVATE_X_GITLAB_AUTO_APPROVE_TOKEN;\n }\n logger.debug(`approveMr(${mrNumber})`);\n try {\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_requests/${mrNumber}/approve`,\n opts,\n );\n } catch (err) {\n logger.warn({ err }, 'GitLab: Error approving merge request');\n }\n}\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle,\n prBody: rawDescription,\n draftPR,\n labels,\n platformPrOptions,\n}: CreatePRConfig): Promise<Pr> {\n let title = prTitle;\n if (draftPR) {\n title = draftPrefix + title;\n }\n const description = sanitize(rawDescription);\n logger.debug(`Creating Merge Request: ${title}`);\n const res = await gitlabApi.postJson<GitLabMergeRequest>(\n `projects/${config.repository}/merge_requests`,\n {\n body: {\n source_branch: sourceBranch,\n target_branch: targetBranch,\n remove_source_branch: true,\n title,\n description,\n labels: (labels ?? []).join(','),\n squash: config.squash,\n },\n },\n );\n\n const pr = prInfo(res.body);\n await GitlabPrCache.setPr(\n gitlabApi,\n config.repository,\n botUserName,\n pr,\n !!config.ignorePrAuthor,\n );\n\n if (platformPrOptions?.autoApprove) {\n await approveMr(pr.number);\n }\n\n await tryPrAutomerge(pr.number, platformPrOptions);\n\n return pr;\n}\n\nexport async function getPr(iid: number): Promise<GitlabPr> {\n logger.debug(`getPr(${iid})`);\n const mr = await getMR(config.repository, iid);\n\n // Harmonize fields with GitHub\n return prInfo(mr);\n}\n\nexport async function updatePr({\n number: iid,\n prTitle,\n prBody: description,\n addLabels,\n removeLabels,\n state,\n platformPrOptions,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n let title = prTitle;\n if ((await getPrList()).find((pr) => pr.number === iid)?.isDraft) {\n title = draftPrefix + title;\n }\n const newState = {\n ['closed']: 'close',\n ['open']: 'reopen',\n // TODO: null check (#22198)\n }[state!];\n\n const body: any = {\n title,\n description: sanitize(description),\n ...(newState && { state_event: newState }),\n };\n if (targetBranch) {\n body.target_branch = targetBranch;\n }\n\n if (addLabels) {\n body.add_labels = addLabels;\n }\n\n if (removeLabels) {\n body.remove_labels = removeLabels;\n }\n\n const updatedPrInfo = (\n await gitlabApi.putJson<GitLabMergeRequest>(\n `projects/${config.repository}/merge_requests/${iid}`,\n { body },\n )\n ).body;\n\n const updatedPr = prInfo(updatedPrInfo);\n await GitlabPrCache.setPr(\n gitlabApi,\n config.repository,\n botUserName,\n updatedPr,\n !!config.ignorePrAuthor,\n );\n\n if (platformPrOptions?.autoApprove) {\n await approveMr(iid);\n }\n}\n\nexport async function reattemptPlatformAutomerge({\n number: iid,\n platformPrOptions,\n}: ReattemptPlatformAutomergeConfig): Promise<void> {\n await tryPrAutomerge(iid, platformPrOptions);\n\n logger.debug(`PR platform automerge re-attempted...prNo: ${iid}`);\n}\n\nexport async function mergePr({ id }: MergePRConfig): Promise<boolean> {\n try {\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${id}/merge`,\n {\n body: {\n should_remove_source_branch: true,\n },\n },\n );\n return true;\n } catch (err) /* v8 ignore next */ {\n if (err.statusCode === 401) {\n logger.debug('No permissions to merge PR');\n return false;\n }\n if (err.statusCode === 406) {\n logger.debug({ err }, 'PR not acceptable for merging');\n return false;\n }\n logger.debug({ err }, 'merge PR error');\n logger.debug('PR merge failed');\n return false;\n }\n}\n\nexport function massageMarkdown(input: string): string {\n const desc = input\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/\\bPR: #/g), 'MR: !')\n .replace(regEx(/\\bPR\\b/g), 'MR')\n .replace(regEx(/\\bPRs\\b/g), 'MRs')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](!')\n // Strip unicode null characters as GitLab markdown does not permit them\n .replace(regEx(/\\u0000/g), ''); // eslint-disable-line no-control-regex\n return smartTruncate(desc, maxBodyLength());\n}\n\nexport function maxBodyLength(): number {\n if (semver.lt(defaults.version, '13.4.0')) {\n logger.debug(\n { version: defaults.version },\n 'GitLab versions earlier than 13.4 have issues with long descriptions, truncating to 25K characters',\n );\n return 25000;\n } else {\n return 1000000;\n }\n}\n\n/* v8 ignore next: no need to test */\nexport function labelCharLimit(): number {\n return 255;\n}\n\n// Branch\n\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 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 MR list\n const response = await gitlabApi.getJsonUnchecked<GitLabMergeRequest[]>(\n `projects/${config.repository}/merge_requests?source_branch=${branchName}&state=opened`,\n );\n\n const { body: mrList } = response;\n if (!mrList.length) {\n logger.debug(`No MR found for branch ${branchName}`);\n return null;\n }\n\n return prInfo(mrList[0]);\n }\n\n const prList = await getPrList();\n return (\n prList.find(\n (p: { sourceBranch: string; title: string; state: string }) =>\n p.sourceBranch === branchName &&\n (!prTitle || p.title.toUpperCase() === prTitle.toUpperCase()) &&\n matchesState(p.state, state),\n ) ?? null\n );\n}\n\n// Returns the Pull Request for a branch. Null if not exists.\nexport async function getBranchPr(\n branchName: string,\n): Promise<GitlabPr | 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\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n // cache-bust in case we have rebased\n const res = await getStatus(branchName, false);\n logger.debug(`Got res with ${res.length} results`);\n for (const check of res) {\n if (check.name === context) {\n return gitlabToRenovateStatusMapping[check.status] || 'yellow';\n }\n }\n return null;\n}\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state: renovateState,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n // First, get the branch commit SHA\n const branchSha = git.getBranchCommit(branchName);\n if (!branchSha) {\n logger.warn('Failed to get the branch commit SHA');\n return;\n }\n // Now, check the statuses for that commit\n const url = `projects/${config.repository}/statuses/${branchSha}`;\n let state = 'success';\n if (renovateState === 'yellow') {\n state = 'pending';\n } else if (renovateState === 'red') {\n state = 'failed';\n }\n const options: any = {\n state,\n description,\n context,\n };\n\n // v8 ignore else -- TODO: add test #40625\n if (targetUrl) {\n options.target_url = targetUrl;\n }\n\n const env = getEnv();\n const retryTimes = parseInteger(\n env.RENOVATE_X_GITLAB_BRANCH_STATUS_CHECK_ATTEMPTS,\n 2,\n );\n\n try {\n for (let attempt = 1; attempt <= retryTimes + 1; attempt += 1) {\n const commitUrl = `projects/${config.repository}/repository/commits/${branchSha}`;\n await gitlabApi\n .getJsonSafe(commitUrl, { memCache: false }, LastPipelineId)\n .onValue((pipelineId) => {\n options.pipeline_id = pipelineId;\n });\n if (options.pipeline_id !== undefined) {\n break;\n }\n if (attempt >= retryTimes + 1) {\n logger.debug(`Pipeline not yet created after ${attempt} attempts`);\n } else {\n logger.debug(`Pipeline not yet created. Retrying ${attempt}`);\n }\n // give gitlab some time to create pipelines for the sha\n await setTimeout(\n parseInteger(env.RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY, 1000),\n );\n }\n } catch (err) {\n logger.debug({ err });\n logger.warn('Failed to retrieve commit pipeline');\n }\n\n try {\n await gitlabApi.postJson(url, { body: options });\n\n // update status cache\n await getStatus(branchName, false);\n } catch (err) /* v8 ignore next */ {\n if (\n err.body?.message?.startsWith(\n 'Cannot transition status via :enqueue from :pending',\n )\n ) {\n // https://gitlab.com/gitlab-org/gitlab-foss/issues/25807\n logger.debug('Ignoring status transition error');\n } else {\n logger.debug({ err });\n logger.warn('Failed to set branch status');\n }\n }\n}\n\n// Issue\n\nexport async function getIssueList(): Promise<GitlabIssue[]> {\n // v8 ignore else -- TODO: add test #40625\n if (!config.issueList) {\n const searchParams: Record<string, string> = {\n per_page: '100',\n state: 'opened',\n };\n // v8 ignore else -- TODO: add test #40625\n if (!config.ignorePrAuthor) {\n searchParams.scope = 'created_by_me';\n }\n const query = getQueryString(searchParams);\n const res = await gitlabApi.getJsonUnchecked<\n { iid: number; title: string; labels: string[] }[]\n >(`projects/${config.repository}/issues?${query}`, {\n memCache: false,\n paginate: true,\n });\n /* v8 ignore next */\n if (!isArray(res.body)) {\n logger.warn({ responseBody: res.body }, 'Could not retrieve issue list');\n return [];\n }\n config.issueList = res.body.map((i) => ({\n iid: i.iid,\n title: i.title,\n labels: i.labels,\n }));\n }\n return config.issueList;\n}\n\nexport async function getIssue(\n number: number,\n useCache = true,\n): Promise<Issue | null> {\n try {\n const opts: GitlabHttpOptions = {};\n /* v8 ignore next: temporary code */\n if (useCache) {\n opts.cacheProvider = memCacheProvider;\n } else {\n opts.memCache = false;\n }\n const issueBody = (\n await gitlabApi.getJsonUnchecked<{ description: string }>(\n `projects/${config.repository}/issues/${number}`,\n opts,\n )\n ).body.description;\n return {\n number,\n body: issueBody,\n };\n } catch (err) /* v8 ignore next */ {\n logger.debug({ err, number }, 'Error getting issue');\n return null;\n }\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n try {\n const issueList = await getIssueList();\n const issue = issueList.find((i) => i.title === title);\n if (!issue) {\n return null;\n }\n return await getIssue(issue.iid);\n } catch /* v8 ignore next */ {\n logger.warn('Error finding issue');\n return null;\n }\n}\n\nexport async function ensureIssue({\n title,\n reuseTitle,\n body,\n labels,\n confidential,\n}: EnsureIssueConfig): Promise<'updated' | 'created' | null> {\n logger.debug(`ensureIssue()`);\n const description = massageMarkdown(sanitize(body));\n try {\n const issueList = await getIssueList();\n let issue = issueList.find((i) => i.title === title);\n issue ??= issueList.find((i) => i.title === reuseTitle);\n if (issue) {\n const existingDescription = (\n await gitlabApi.getJsonUnchecked<{ description: string }>(\n `projects/${config.repository}/issues/${issue.iid}`,\n )\n ).body.description;\n if (issue.title !== title || existingDescription !== description) {\n logger.debug('Updating issue');\n await gitlabApi.putJson(\n `projects/${config.repository}/issues/${issue.iid}`,\n {\n body: {\n title,\n description,\n labels: (labels ?? issue.labels ?? []).join(','),\n confidential: confidential ?? false,\n },\n },\n );\n return 'updated';\n }\n } else {\n await gitlabApi.postJson(`projects/${config.repository}/issues`, {\n body: {\n title,\n description,\n labels: (labels ?? []).join(','),\n confidential: confidential ?? false,\n },\n });\n logger.info('Issue created');\n // delete issueList so that it will be refetched as necessary\n delete config.issueList;\n return 'created';\n }\n } catch (err) /* v8 ignore next */ {\n if (err.message.startsWith('Issues are disabled for this repo')) {\n logger.debug(`Could not create issue: ${(err as Error).message}`);\n } else {\n logger.warn({ err }, 'Could not ensure issue');\n }\n }\n return null;\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n logger.debug(`ensureIssueClosing()`);\n const issueList = await getIssueList();\n for (const issue of issueList) {\n if (issue.title === title) {\n logger.debug({ issue }, 'Closing issue');\n await gitlabApi.putJson(\n `projects/${config.repository}/issues/${issue.iid}`,\n {\n body: { state_event: 'close' },\n },\n );\n }\n }\n}\n\nexport async function addAssignees(\n iid: number,\n assignees: string[],\n): Promise<void> {\n try {\n logger.debug(`Adding assignees '${assignees.join(', ')}' to #${iid}`);\n const assigneeIds: number[] = [];\n for (const assignee of assignees) {\n try {\n const userId = await getUserID(assignee);\n assigneeIds.push(userId);\n } catch (err) {\n logger.debug({ assignee, err }, 'getUserID() error');\n logger.warn({ assignee }, 'Failed to add assignee - could not get ID');\n }\n }\n const url = `projects/${\n config.repository\n }/merge_requests/${iid}?${getQueryString({\n 'assignee_ids[]': assigneeIds,\n })}`;\n await gitlabApi.putJson(url);\n } catch (err) {\n logger.debug({ err }, 'addAssignees error');\n logger.warn({ iid, assignees }, 'Failed to add assignees');\n }\n}\n\nexport async function addReviewers(\n iid: number,\n reviewers: string[],\n): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${iid}`);\n\n if (semver.lt(defaults.version, '13.9.0')) {\n logger.warn(\n { version: defaults.version },\n 'Adding reviewers is only available in GitLab 13.9 and onwards',\n );\n return;\n }\n\n let mr: GitLabMergeRequest;\n try {\n mr = await getMR(config.repository, iid);\n } catch (err) {\n logger.warn({ err }, 'Failed to get existing reviewers');\n return;\n }\n\n mr.reviewers = coerceArray(mr.reviewers);\n const existingReviewers = mr.reviewers.map((r) => r.username);\n const existingReviewerIDs = mr.reviewers.map((r) => r.id);\n\n // Figure out which reviewers (of the ones we want to add) are not already on the MR as a reviewer\n const newReviewers = reviewers.filter((r) => !existingReviewers.includes(r));\n\n // Gather the IDs for all the reviewers we want to add\n let newReviewerIDs: number[];\n newReviewerIDs = (\n await p.all(\n newReviewers.map((r) => async () => {\n try {\n return [await getUserID(r)];\n } catch {\n // Unable to fetch userId, try resolve as a group\n return getMemberUserIDs(r);\n }\n }),\n )\n ).flat();\n\n if (isNonEmptyArray(newReviewers) && isEmptyArray(newReviewerIDs)) {\n logger.warn('Failed to get IDs of the new reviewers');\n return;\n }\n\n // Multiple groups may have the same members, so\n // filter out non-distinct values\n newReviewerIDs = [...new Set(newReviewerIDs)];\n\n try {\n await updateMR(config.repository, iid, {\n reviewer_ids: [...existingReviewerIDs, ...newReviewerIDs],\n });\n } catch (err) {\n logger.warn({ err }, 'Failed to add reviewers');\n }\n}\n\nexport async function deleteLabel(\n issueNo: number,\n label: string,\n): Promise<void> {\n logger.debug(`Deleting label ${label} from #${issueNo}`);\n try {\n const pr = await getPr(issueNo);\n const labels = coerceArray(pr.labels)\n .filter((l: string) => l !== label)\n .join(',');\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${issueNo}`,\n {\n body: { labels },\n },\n );\n } catch (err) /* v8 ignore next */ {\n logger.warn({ err, issueNo, label }, 'Failed to delete label');\n }\n}\n\nasync function getComments(issueNo: number): Promise<GitlabComment[]> {\n // GET projects/:owner/:repo/merge_requests/:number/notes\n logger.debug(`Getting comments for #${issueNo}`);\n const url = `projects/${config.repository}/merge_requests/${issueNo}/notes`;\n const comments = (\n await gitlabApi.getJsonUnchecked<GitlabComment[]>(url, { paginate: true })\n ).body;\n logger.debug(`Found ${comments.length} comments`);\n return comments;\n}\n\nasync function addComment(issueNo: number, body: string): Promise<void> {\n // POST projects/:owner/:repo/merge_requests/:number/notes\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes`,\n {\n body: { body },\n },\n );\n}\n\nasync function editComment(\n issueNo: number,\n commentId: number,\n body: string,\n): Promise<void> {\n // PUT projects/:owner/:repo/merge_requests/:number/notes/:id\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}`,\n {\n body: { body },\n },\n );\n}\n\nasync function deleteComment(\n issueNo: number,\n commentId: number,\n): Promise<void> {\n // DELETE projects/:owner/:repo/merge_requests/:number/notes/:id\n await gitlabApi.deleteJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}`,\n );\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n const sanitizedContent = sanitize(content);\n const massagedTopic = topic\n ? topic\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/PR/g), 'MR')\n : topic;\n const comments = await getComments(number);\n let body: string;\n let commentId: number | undefined;\n let commentNeedsUpdating: boolean | undefined;\n // TODO: types (#22198)\n if (topic) {\n logger.debug(`Ensuring comment \"${massagedTopic!}\" in #${number}`);\n body = `### ${topic}\\n\\n${sanitizedContent}`;\n body = smartTruncate(\n body\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/PR/g), 'MR'),\n maxBodyLength(),\n );\n comments.forEach((comment: { body: string; id: number }) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body.startsWith(`### ${massagedTopic!}\\n\\n`)) {\n commentId = comment.id;\n commentNeedsUpdating = comment.body !== body;\n }\n });\n } else {\n logger.debug(`Ensuring content-only comment in #${number}`);\n body = smartTruncate(`${sanitizedContent}`, maxBodyLength());\n comments.forEach((comment: { body: string; id: number }) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body === body) {\n commentId = comment.id;\n commentNeedsUpdating = false;\n }\n });\n }\n if (!commentId) {\n await addComment(number, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Added comment',\n );\n } else if (commentNeedsUpdating) {\n await editComment(number, commentId, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Updated comment',\n );\n } else {\n logger.debug('Comment is already update-to-date');\n }\n return true;\n}\n\nexport async function ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: issueNo } = deleteConfig;\n const key =\n deleteConfig.type === 'by-topic'\n ? deleteConfig.topic\n : deleteConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${issueNo} is removed`);\n\n const comments = await getComments(issueNo);\n let commentId: number | null | undefined = null;\n\n // v8 ignore else -- TODO: add test #40625\n if (deleteConfig.type === 'by-topic') {\n const byTopic = (comment: GitlabComment): boolean =>\n comment.body.startsWith(`### ${deleteConfig.topic}\\n\\n`);\n commentId = comments.find(byTopic)?.id;\n } else if (deleteConfig.type === 'by-content') {\n const byContent = (comment: GitlabComment): boolean =>\n comment.body.trim() === deleteConfig.content;\n commentId = comments.find(byContent)?.id;\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (commentId) {\n await deleteComment(issueNo, commentId);\n }\n}\n\nexport async function filterUnavailableUsers(\n users: string[],\n): Promise<string[]> {\n const filteredUsers: string[] = [];\n for (const user of users) {\n if (!(await isUserBusy(user))) {\n filteredUsers.push(user);\n }\n }\n return filteredUsers;\n}\n\nexport async function expandGroupMembers(\n reviewersOrAssignees: string[],\n): Promise<string[]> {\n const expandedReviewersOrAssignees: string[] = [];\n const normalizedReviewersOrAssigneesWithoutEmails: string[] = [];\n\n // Skip passing user emails to Gitlab API, but include them in the final result\n for (const reviewerOrAssignee of reviewersOrAssignees) {\n if (reviewerOrAssignee.indexOf('@') > 0) {\n expandedReviewersOrAssignees.push(reviewerOrAssignee);\n continue;\n }\n\n // Normalize the potential group names before passing to Gitlab API\n normalizedReviewersOrAssigneesWithoutEmails.push(\n noLeadingAtSymbol(reviewerOrAssignee),\n );\n }\n\n for (const reviewerOrAssignee of normalizedReviewersOrAssigneesWithoutEmails) {\n try {\n const members = await getMemberUsernames(reviewerOrAssignee);\n expandedReviewersOrAssignees.push(...members);\n } catch (err) {\n if (err.statusCode !== 404) {\n logger.debug({ err, reviewerOrAssignee }, 'Unable to fetch group');\n }\n expandedReviewersOrAssignees.push(reviewerOrAssignee);\n }\n }\n return expandedReviewersOrAssignees;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["git.initRepo","git.getBranchCommit","git.branchExists","p.all"],"sources":["../../../../lib/modules/platform/gitlab/index.ts"],"sourcesContent":["import { isArray, isEmptyArray, isNonEmptyArray } from '@sindresorhus/is';\nimport pMap from 'p-map';\nimport semver from 'semver';\nimport { setTimeout } from 'timers/promises';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport {\n REPOSITORY_ACCESS_FORBIDDEN,\n REPOSITORY_ARCHIVED,\n REPOSITORY_CHANGED,\n REPOSITORY_DISABLED,\n REPOSITORY_EMPTY,\n REPOSITORY_MIRRORED,\n REPOSITORY_NOT_FOUND,\n TEMPORARY_ERROR,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport type { BranchStatus } from '../../../types/index.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport { noLeadingAtSymbol, parseJson } from '../../../util/common.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as git from '../../../util/git/index.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { GitlabHttpOptions } from '../../../util/http/gitlab.ts';\nimport { setBaseUrl } from '../../../util/http/gitlab.ts';\nimport type { HttpResponse } from '../../../util/http/types.ts';\nimport { parseInteger } from '../../../util/number.ts';\nimport * as p from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { sanitize } from '../../../util/sanitize.ts';\nimport type { EmailAddress } from '../../../util/schema-utils/index.ts';\nimport { ensureTrailingSlash, getQueryString } from '../../../util/url.ts';\nimport type {\n AutodiscoverConfig,\n BranchStatusConfig,\n CreatePRConfig,\n EnsureCommentConfig,\n EnsureCommentRemovalConfig,\n EnsureIssueConfig,\n FindPRConfig,\n Issue,\n MergePRConfig,\n PlatformParams,\n PlatformPrOptions,\n PlatformResult,\n Pr,\n ReattemptPlatformAutomergeConfig,\n RepoParams,\n RepoResult,\n UpdatePrConfig,\n} from '../types.ts';\nimport { repoFingerprint } from '../util.ts';\nimport { smartTruncate } from '../utils/pr-body.ts';\nimport {\n getMemberUserIDs,\n getMemberUsernames,\n getUserID,\n gitlabApi,\n isUserBusy,\n} from './http.ts';\nimport { getMR, updateMR } from './merge-request.ts';\nimport { GitlabPrCache } from './pr-cache.ts';\nimport type { GitLabMergeRequest } from './schema.ts';\nimport { LastPipelineId } from './schema.ts';\nimport type {\n GitlabComment,\n GitlabIssue,\n GitlabPr,\n MergeMethod,\n RepoResponse,\n} from './types.ts';\nimport {\n DRAFT_PREFIX,\n DRAFT_PREFIX_DEPRECATED,\n defaults,\n getRepoUrl,\n prInfo,\n} from './utils.ts';\n\nexport { extractRulesFromCodeOwnersLines } from './code-owners.ts';\n\nlet config: {\n repository: string;\n email: EmailAddress;\n issueList: GitlabIssue[] | undefined;\n mergeMethod: MergeMethod;\n mergeTrainsEnabled: boolean;\n defaultBranch: string;\n cloneSubmodules: boolean | undefined;\n cloneSubmodulesFilter: string[] | undefined;\n ignorePrAuthor: boolean | undefined;\n squash: boolean;\n} = {} as any;\n\nexport function resetPlatform(): void {\n config = {} as any;\n draftPrefix = DRAFT_PREFIX;\n defaults.hostType = 'gitlab';\n defaults.endpoint = 'https://gitlab.com/api/v4/';\n defaults.version = '0.0.0';\n setBaseUrl(defaults.endpoint);\n}\n\nexport const id = 'gitlab';\n\nlet draftPrefix = DRAFT_PREFIX;\nlet botUserName: string;\n\nexport async function initPlatform({\n endpoint,\n username,\n token,\n gitAuthor,\n}: PlatformParams): Promise<PlatformResult> {\n if (!token) {\n throw new Error('Init: You must configure a GitLab personal access token');\n }\n if (endpoint) {\n defaults.endpoint = ensureTrailingSlash(endpoint);\n setBaseUrl(defaults.endpoint);\n } else {\n logger.debug('Using default GitLab endpoint: ' + defaults.endpoint);\n }\n const platformConfig: PlatformResult = {\n endpoint: defaults.endpoint,\n };\n let gitlabVersion: string;\n try {\n if (!gitAuthor) {\n const user = (\n await gitlabApi.getJsonUnchecked<{\n email: EmailAddress;\n name: string;\n id: number;\n commit_email?: EmailAddress;\n }>(`user`, { token })\n ).body;\n platformConfig.gitAuthor = `${user.name} <${\n user.commit_email ?? user.email\n }>`;\n botUserName = user.name;\n }\n const env = getEnv();\n /* v8 ignore next: experimental feature */\n if (env.RENOVATE_X_PLATFORM_VERSION) {\n gitlabVersion = env.RENOVATE_X_PLATFORM_VERSION;\n } else {\n const version = (\n await gitlabApi.getJsonUnchecked<{ version: string }>('version', {\n token,\n })\n ).body;\n gitlabVersion = version.version;\n }\n logger.debug('GitLab version is: ' + gitlabVersion);\n // version is 'x.y.z-edition', so not strictly semver; need to strip edition\n [gitlabVersion] = gitlabVersion.split('-');\n defaults.version = gitlabVersion;\n } catch (err) {\n logger.debug(\n { err },\n 'Error authenticating with GitLab. Check that your token includes \"api\" permissions',\n );\n throw new Error('Init: Authentication failure');\n }\n draftPrefix = semver.lt(defaults.version, '13.2.0')\n ? DRAFT_PREFIX_DEPRECATED\n : DRAFT_PREFIX;\n\n botUserName ??= username!;\n\n return 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 GitLab repositories');\n\n const queryParams: Record<string, any> = {\n membership: true,\n per_page: 100,\n with_merge_requests_enabled: true,\n min_access_level: 30,\n archived: false,\n ...(config?.sort && { order_by: config.sort }),\n ...(config?.order && { sort: config.order }),\n };\n if (config?.topics?.length) {\n queryParams.topic = config.topics.join(',');\n }\n\n const urls = [];\n if (config?.namespaces?.length) {\n queryParams.with_shared = false;\n queryParams.include_subgroups = true;\n urls.push(\n ...config.namespaces.map(\n (namespace) =>\n `groups/${urlEscape(namespace)}/projects?${getQueryString(\n queryParams,\n )}`,\n ),\n );\n } else {\n urls.push('projects?' + getQueryString(queryParams));\n }\n\n try {\n const repos = (\n await pMap(\n urls,\n (url) =>\n gitlabApi.getJsonUnchecked<RepoResponse[]>(url, {\n paginate: true,\n }),\n {\n concurrency: 2,\n },\n )\n ).flatMap((response) => response.body);\n\n logger.debug(`Discovered ${repos.length} project(s)`);\n return repos\n .filter((repo) => !repo.mirror || config?.includeMirrors)\n .map((repo) => repo.path_with_namespace);\n } catch (err) {\n logger.error({ err }, `GitLab getRepos error`);\n throw err;\n }\n}\n\nfunction urlEscape(str: string): string;\nfunction urlEscape(str: string | undefined): string | undefined;\nfunction urlEscape(str: string | undefined): string | undefined {\n return str?.replace(regEx(/\\//g), '%2F');\n}\n\nexport async function getRawFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<string | null> {\n const escapedFileName = urlEscape(fileName);\n const repo = urlEscape(repoName) ?? config.repository;\n const url =\n `projects/${repo}/repository/files/${escapedFileName}?ref=` +\n (branchOrTag ?? `HEAD`);\n const res = await gitlabApi.getJsonUnchecked<{ content: string }>(url, {\n cacheProvider: memCacheProvider,\n });\n const buf = res.body.content;\n const str = Buffer.from(buf, 'base64').toString();\n return str;\n}\n\nexport async function getJsonFile(\n fileName: string,\n repoName?: string,\n branchOrTag?: string,\n): Promise<any> {\n const raw = await getRawFile(fileName, repoName, branchOrTag);\n return parseJson(raw, fileName);\n}\n\n// Initialize GitLab by getting base branch\nexport async function initRepo({\n repository,\n cloneSubmodules,\n cloneSubmodulesFilter,\n gitUrl,\n}: RepoParams): Promise<RepoResult> {\n config = {} as any;\n config.repository = urlEscape(repository);\n config.cloneSubmodules = cloneSubmodules;\n config.cloneSubmodulesFilter = cloneSubmodulesFilter;\n config.ignorePrAuthor = GlobalConfig.get('ignorePrAuthor');\n\n let res: HttpResponse<RepoResponse>;\n try {\n res = await gitlabApi.getJsonUnchecked<RepoResponse>(\n `projects/${config.repository}`,\n );\n if (res.body.archived) {\n logger.debug(\n 'Repository is archived - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_ARCHIVED);\n }\n\n if (res.body.mirror && GlobalConfig.get('includeMirrors') !== true) {\n logger.debug(\n 'Repository is a mirror - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_MIRRORED);\n }\n if (res.body.repository_access_level === 'disabled') {\n logger.debug(\n 'Repository portion of project is disabled - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_DISABLED);\n }\n if (res.body.merge_requests_access_level === 'disabled') {\n logger.debug(\n 'MRs are disabled for the project - throwing error to abort renovation',\n );\n throw new Error(REPOSITORY_DISABLED);\n }\n if (res.body.default_branch === null || res.body.empty_repo) {\n throw new Error(REPOSITORY_EMPTY);\n }\n config.defaultBranch = res.body.default_branch;\n /* v8 ignore next */\n if (!config.defaultBranch) {\n logger.warn({ resBody: res.body }, 'Error fetching GitLab project');\n throw new Error(TEMPORARY_ERROR);\n }\n config.mergeMethod = res.body.merge_method || 'merge';\n config.mergeTrainsEnabled = res.body.merge_trains_enabled ?? false;\n if (res.body.squash_option) {\n config.squash =\n res.body.squash_option === 'always' ||\n res.body.squash_option === 'default_on';\n }\n logger.debug(`${repository} default branch = ${config.defaultBranch}`);\n logger.debug('Enabling Git FS');\n const url = getRepoUrl(repository, gitUrl, res);\n await git.initRepo({\n ...config,\n url,\n });\n } catch (err) /* v8 ignore next */ {\n logger.debug({ err }, 'Caught initRepo error');\n if (err.message.includes('HEAD is not a symbolic ref')) {\n throw new Error(REPOSITORY_EMPTY);\n }\n if ([REPOSITORY_ARCHIVED, REPOSITORY_EMPTY].includes(err.message)) {\n throw err;\n }\n if (err.statusCode === 403) {\n throw new Error(REPOSITORY_ACCESS_FORBIDDEN);\n }\n if (err.statusCode === 404) {\n throw new Error(REPOSITORY_NOT_FOUND);\n }\n if (err.message === REPOSITORY_DISABLED) {\n throw err;\n }\n logger.debug({ err }, 'Unknown GitLab initRepo error');\n throw err;\n }\n const repoConfig: RepoResult = {\n defaultBranch: config.defaultBranch,\n isFork: !!res.body.forked_from_project,\n repoFingerprint: repoFingerprint(res.body.id, defaults.endpoint),\n };\n return repoConfig;\n}\n\nexport function getBranchForceRebase(): Promise<boolean> {\n const forceRebase =\n config?.mergeMethod !== 'merge' && !config.mergeTrainsEnabled;\n if (forceRebase) {\n logger.once.debug(\n `mergeMethod is ${config.mergeMethod} so PRs will be kept up-to-date with base branch`,\n );\n }\n return Promise.resolve(forceRebase);\n}\n\ntype BranchState =\n | 'pending'\n | 'created'\n | 'running'\n | 'waiting_for_resource'\n | 'manual'\n | 'success'\n | 'failed'\n | 'canceled'\n | 'skipped'\n | 'scheduled';\n\ninterface GitlabBranchStatus {\n status: BranchState;\n name: string;\n allow_failure?: boolean;\n}\n\nasync function getStatus(\n branchName: string,\n useCache = true,\n): Promise<GitlabBranchStatus[]> {\n const branchSha = git.getBranchCommit(branchName);\n try {\n // TODO: types (#22198)\n const url = `projects/${\n config.repository\n }/repository/commits/${branchSha!}/statuses`;\n\n const opts: GitlabHttpOptions = { paginate: true };\n if (useCache) {\n opts.cacheProvider = memCacheProvider;\n } else {\n opts.memCache = false;\n }\n\n return (await gitlabApi.getJsonUnchecked<GitlabBranchStatus[]>(url, opts))\n .body;\n } catch (err) /* v8 ignore next */ {\n logger.debug({ err }, 'Error getting commit status');\n if (err.response?.statusCode === 404) {\n throw new Error(REPOSITORY_CHANGED);\n }\n throw err;\n }\n}\n\nconst gitlabToRenovateStatusMapping: Record<BranchState, BranchStatus> = {\n pending: 'yellow',\n created: 'yellow',\n manual: 'yellow',\n running: 'yellow',\n waiting_for_resource: 'yellow',\n success: 'green',\n failed: 'red',\n canceled: 'red',\n skipped: 'red',\n scheduled: 'yellow',\n};\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\n if (!git.branchExists(branchName)) {\n throw new Error(REPOSITORY_CHANGED);\n }\n\n const branchStatuses = await getStatus(branchName);\n /* v8 ignore next */\n if (!isArray(branchStatuses)) {\n logger.warn(\n { branchName, branchStatuses },\n 'Empty or unexpected branch statuses',\n );\n return 'yellow';\n }\n logger.debug(`Got res with ${branchStatuses.length} results`);\n\n const mr = await getBranchPr(branchName);\n if (mr && mr.sha !== mr.headPipelineSha && mr.headPipelineStatus) {\n logger.debug(\n 'Merge request head pipeline has different sha to commit, assuming merged results pipeline',\n );\n branchStatuses.push({\n status: mr.headPipelineStatus as BranchState,\n name: 'head_pipeline',\n });\n }\n // ignore all skipped jobs\n const res = branchStatuses.filter((check) => check.status !== 'skipped');\n if (res.length === 0) {\n // Return 'pending' if we have no status checks\n return 'yellow';\n }\n if (\n !internalChecksAsSuccess &&\n branchStatuses.every(\n (check) =>\n check.name?.startsWith('renovate/') &&\n gitlabToRenovateStatusMapping[check.status] === 'green',\n )\n ) {\n logger.debug(\n 'Successful checks are all internal renovate/ checks, so returning \"pending\" branch status',\n );\n return 'yellow';\n }\n let status: BranchStatus = 'green'; // default to green\n res\n .filter((check) => !check.allow_failure)\n .forEach((check) => {\n // v8 ignore else -- TODO: add test #40625\n if (status !== 'red') {\n // if red, stay red\n let mappedStatus: BranchStatus =\n gitlabToRenovateStatusMapping[check.status];\n if (!mappedStatus) {\n logger.warn(\n { check },\n 'Could not map GitLab check.status to Renovate status',\n );\n mappedStatus = 'yellow';\n }\n if (mappedStatus !== 'green') {\n logger.trace({ check }, 'Found non-green check');\n status = mappedStatus;\n }\n }\n });\n return status;\n}\n\n// Pull Request\nexport async function getPrList(): Promise<Pr[]> {\n return await GitlabPrCache.getPrs(\n gitlabApi,\n config.repository,\n botUserName,\n !!config.ignorePrAuthor,\n );\n}\n\nasync function ignoreApprovals(pr: number): Promise<void> {\n try {\n const url = `projects/${config.repository}/merge_requests/${pr}/approval_rules`;\n const { body: rules } = await gitlabApi.getJsonUnchecked<\n {\n name: string;\n rule_type: string;\n id: number;\n }[]\n >(url);\n\n const ruleName = 'renovateIgnoreApprovals';\n\n const existingAnyApproverRule = rules?.find(\n ({ rule_type }) => rule_type === 'any_approver',\n );\n const existingRegularApproverRules = rules?.filter(\n ({ rule_type, name }) =>\n rule_type !== 'any_approver' &&\n name !== ruleName &&\n rule_type !== 'report_approver' &&\n rule_type !== 'code_owner',\n );\n\n if (existingRegularApproverRules?.length) {\n await p.all(\n existingRegularApproverRules.map((rule) => async (): Promise<void> => {\n await gitlabApi.deleteJson(`${url}/${rule.id}`);\n }),\n );\n }\n\n if (existingAnyApproverRule) {\n await gitlabApi.putJson(`${url}/${existingAnyApproverRule.id}`, {\n body: { ...existingAnyApproverRule, approvals_required: 0 },\n });\n return;\n }\n\n const zeroApproversRule = rules?.find(({ name }) => name === ruleName);\n if (!zeroApproversRule) {\n await gitlabApi.postJson(url, {\n body: {\n name: ruleName,\n approvals_required: 0,\n },\n });\n }\n } catch (err) {\n logger.warn({ err }, 'GitLab: Error adding approval rule');\n }\n}\n\nasync function tryPrAutomerge(\n pr: number,\n platformPrOptions: PlatformPrOptions | undefined,\n): Promise<void> {\n try {\n if (platformPrOptions?.gitLabIgnoreApprovals) {\n await ignoreApprovals(pr);\n }\n\n if (platformPrOptions?.usePlatformAutomerge) {\n // https://docs.gitlab.com/ee/api/merge_requests.html#merge-status\n const desiredDetailedMergeStatus = [\n 'mergeable',\n 'ci_still_running',\n 'not_approved',\n ];\n const desiredPipelineStatus = [\n 'failed', // don't lose time if pipeline failed\n 'running', // pipeline is running, no need to wait for it\n ];\n const desiredStatus = 'can_be_merged';\n const env = getEnv();\n // The default value of 5 attempts results in max. 13.75 seconds timeout if no pipeline created.\n const retryTimes = parseInteger(\n env.RENOVATE_X_GITLAB_AUTO_MERGEABLE_CHECK_ATTEMPS,\n 5,\n );\n\n const mergeDelay = parseInteger(\n env.RENOVATE_X_GITLAB_MERGE_REQUEST_DELAY,\n 250,\n );\n\n // Check for correct merge request status before setting `merge_when_pipeline_succeeds` to `true`.\n for (let attempt = 1; attempt <= retryTimes; attempt += 1) {\n const { body } = await gitlabApi.getJsonUnchecked<{\n merge_status: string;\n detailed_merge_status?: string;\n merge_when_pipeline_succeeds?: boolean;\n pipeline: {\n status: string;\n };\n }>(`projects/${config.repository}/merge_requests/${pr}`, {\n memCache: false,\n });\n\n // Exit early if merge_when_pipeline_succeeds is already set\n if (body.merge_when_pipeline_succeeds === true) {\n logger.debug(\n 'Skipping automerge retry - merge_when_pipeline_succeeds already enabled',\n );\n return;\n }\n // detailed_merge_status is available with Gitlab >=15.6.0\n const use_detailed_merge_status = !!body.detailed_merge_status;\n const detailed_merge_status_check =\n use_detailed_merge_status &&\n desiredDetailedMergeStatus.includes(body.detailed_merge_status!);\n // merge_status is deprecated with Gitlab >= 15.6\n const deprecated_merge_status_check =\n !use_detailed_merge_status && body.merge_status === desiredStatus;\n\n // Only continue if the merge request can be merged and has a pipeline.\n if (\n (detailed_merge_status_check || deprecated_merge_status_check) &&\n body.pipeline !== null &&\n desiredPipelineStatus.includes(body.pipeline.status)\n ) {\n break;\n }\n logger.debug(`PR not yet in mergeable state. Retrying ${attempt}`);\n await setTimeout(mergeDelay * attempt ** 2); // exponential backoff\n }\n\n // Even if Gitlab returns a \"merge-able\" merge request status, enabling auto-merge sometimes\n // returns a 405 Method Not Allowed. It seems to be a timing issue within Gitlab.\n for (let attempt = 1; attempt <= retryTimes; attempt += 1) {\n try {\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${pr}/merge`,\n {\n body: {\n should_remove_source_branch: true,\n merge_when_pipeline_succeeds: true,\n },\n },\n );\n break;\n } catch (err) {\n logger.debug(\n { err },\n `Automerge on PR creation failed. Retrying ${attempt}`,\n );\n }\n await setTimeout(mergeDelay * attempt ** 2); // exponential backoff\n }\n }\n } catch (err) /* v8 ignore next */ {\n logger.debug({ err }, 'Automerge on PR creation failed');\n }\n}\n\nasync function approveMr(mrNumber: number): Promise<void> {\n const env = getEnv();\n const opts: GitlabHttpOptions = {};\n if (env.RENOVATE_X_GITLAB_AUTO_APPROVE_TOKEN) {\n opts.token = env.RENOVATE_X_GITLAB_AUTO_APPROVE_TOKEN;\n }\n logger.debug(`approveMr(${mrNumber})`);\n try {\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_requests/${mrNumber}/approve`,\n opts,\n );\n } catch (err) {\n logger.warn({ err }, 'GitLab: Error approving merge request');\n }\n}\n\nexport async function createPr({\n sourceBranch,\n targetBranch,\n prTitle,\n prBody: rawDescription,\n draftPR,\n labels,\n platformPrOptions,\n}: CreatePRConfig): Promise<Pr> {\n let title = prTitle;\n if (draftPR) {\n title = draftPrefix + title;\n }\n const description = sanitize(rawDescription);\n logger.debug(`Creating Merge Request: ${title}`);\n const res = await gitlabApi.postJson<GitLabMergeRequest>(\n `projects/${config.repository}/merge_requests`,\n {\n body: {\n source_branch: sourceBranch,\n target_branch: targetBranch,\n remove_source_branch: true,\n title,\n description,\n labels: (labels ?? []).join(','),\n squash: config.squash,\n },\n },\n );\n\n const pr = prInfo(res.body);\n await GitlabPrCache.setPr(\n gitlabApi,\n config.repository,\n botUserName,\n pr,\n !!config.ignorePrAuthor,\n );\n\n if (platformPrOptions?.autoApprove) {\n await approveMr(pr.number);\n }\n\n await tryPrAutomerge(pr.number, platformPrOptions);\n\n return pr;\n}\n\nexport async function getPr(iid: number): Promise<GitlabPr> {\n logger.debug(`getPr(${iid})`);\n const mr = await getMR(config.repository, iid);\n\n // Harmonize fields with GitHub\n return prInfo(mr);\n}\n\nexport async function updatePr({\n number: iid,\n prTitle,\n prBody: description,\n addLabels,\n removeLabels,\n state,\n platformPrOptions,\n targetBranch,\n}: UpdatePrConfig): Promise<void> {\n let title = prTitle;\n if ((await getPrList()).find((pr) => pr.number === iid)?.isDraft) {\n title = draftPrefix + title;\n }\n const newState = {\n ['closed']: 'close',\n ['open']: 'reopen',\n // TODO: null check (#22198)\n }[state!];\n\n const body: any = {\n title,\n description: sanitize(description),\n ...(newState && { state_event: newState }),\n };\n if (targetBranch) {\n body.target_branch = targetBranch;\n }\n\n if (addLabels) {\n body.add_labels = addLabels;\n }\n\n if (removeLabels) {\n body.remove_labels = removeLabels;\n }\n\n const updatedPrInfo = (\n await gitlabApi.putJson<GitLabMergeRequest>(\n `projects/${config.repository}/merge_requests/${iid}`,\n { body },\n )\n ).body;\n\n const updatedPr = prInfo(updatedPrInfo);\n await GitlabPrCache.setPr(\n gitlabApi,\n config.repository,\n botUserName,\n updatedPr,\n !!config.ignorePrAuthor,\n );\n\n if (platformPrOptions?.autoApprove) {\n await approveMr(iid);\n }\n}\n\nexport async function reattemptPlatformAutomerge({\n number: iid,\n platformPrOptions,\n}: ReattemptPlatformAutomergeConfig): Promise<void> {\n await tryPrAutomerge(iid, platformPrOptions);\n\n logger.debug(`PR platform automerge re-attempted...prNo: ${iid}`);\n}\n\nexport async function mergePr({ id }: MergePRConfig): Promise<boolean> {\n try {\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${id}/merge`,\n {\n body: {\n should_remove_source_branch: true,\n },\n },\n );\n return true;\n } catch (err) /* v8 ignore next */ {\n if (err.statusCode === 401) {\n logger.debug('No permissions to merge PR');\n return false;\n }\n if (err.statusCode === 406) {\n logger.debug({ err }, 'PR not acceptable for merging');\n return false;\n }\n logger.debug({ err }, 'merge PR error');\n logger.debug('PR merge failed');\n return false;\n }\n}\n\nexport function massageMarkdown(input: string): string {\n const desc = input\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/\\bPR: #/g), 'MR: !')\n .replace(regEx(/\\bPR\\b/g), 'MR')\n .replace(regEx(/\\bPRs\\b/g), 'MRs')\n .replace(regEx(/\\]\\(\\.\\.\\/pull\\//g), '](!')\n .replace(regEx(/\\]\\(\\.\\.\\/issues\\//g), '](#')\n // Strip unicode null characters as GitLab markdown does not permit them\n .replace(regEx(/\\u0000/g), ''); // eslint-disable-line no-control-regex\n return smartTruncate(desc, maxBodyLength());\n}\n\nexport function maxBodyLength(): number {\n if (semver.lt(defaults.version, '13.4.0')) {\n logger.debug(\n { version: defaults.version },\n 'GitLab versions earlier than 13.4 have issues with long descriptions, truncating to 25K characters',\n );\n return 25000;\n } else {\n return 1000000;\n }\n}\n\n/* v8 ignore next: no need to test */\nexport function labelCharLimit(): number {\n return 255;\n}\n\n// Branch\n\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 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 MR list\n const response = await gitlabApi.getJsonUnchecked<GitLabMergeRequest[]>(\n `projects/${config.repository}/merge_requests?source_branch=${branchName}&state=opened`,\n );\n\n const { body: mrList } = response;\n if (!mrList.length) {\n logger.debug(`No MR found for branch ${branchName}`);\n return null;\n }\n\n return prInfo(mrList[0]);\n }\n\n const prList = await getPrList();\n return (\n prList.find(\n (p: { sourceBranch: string; title: string; state: string }) =>\n p.sourceBranch === branchName &&\n (!prTitle || p.title.toUpperCase() === prTitle.toUpperCase()) &&\n matchesState(p.state, state),\n ) ?? null\n );\n}\n\n// Returns the Pull Request for a branch. Null if not exists.\nexport async function getBranchPr(\n branchName: string,\n): Promise<GitlabPr | 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\nexport async function getBranchStatusCheck(\n branchName: string,\n context: string,\n): Promise<BranchStatus | null> {\n // cache-bust in case we have rebased\n const res = await getStatus(branchName, false);\n logger.debug(`Got res with ${res.length} results`);\n for (const check of res) {\n if (check.name === context) {\n return gitlabToRenovateStatusMapping[check.status] || 'yellow';\n }\n }\n return null;\n}\n\nexport async function setBranchStatus({\n branchName,\n context,\n description,\n state: renovateState,\n url: targetUrl,\n}: BranchStatusConfig): Promise<void> {\n // First, get the branch commit SHA\n const branchSha = git.getBranchCommit(branchName);\n if (!branchSha) {\n logger.warn('Failed to get the branch commit SHA');\n return;\n }\n // Now, check the statuses for that commit\n const url = `projects/${config.repository}/statuses/${branchSha}`;\n let state = 'success';\n if (renovateState === 'yellow') {\n state = 'pending';\n } else if (renovateState === 'red') {\n state = 'failed';\n }\n const options: any = {\n state,\n description,\n context,\n };\n\n // v8 ignore else -- TODO: add test #40625\n if (targetUrl) {\n options.target_url = targetUrl;\n }\n\n const env = getEnv();\n const retryTimes = parseInteger(\n env.RENOVATE_X_GITLAB_BRANCH_STATUS_CHECK_ATTEMPTS,\n 2,\n );\n\n try {\n for (let attempt = 1; attempt <= retryTimes + 1; attempt += 1) {\n const commitUrl = `projects/${config.repository}/repository/commits/${branchSha}`;\n await gitlabApi\n .getJsonSafe(commitUrl, { memCache: false }, LastPipelineId)\n .onValue((pipelineId) => {\n options.pipeline_id = pipelineId;\n });\n if (options.pipeline_id !== undefined) {\n break;\n }\n if (attempt >= retryTimes + 1) {\n logger.debug(`Pipeline not yet created after ${attempt} attempts`);\n } else {\n logger.debug(`Pipeline not yet created. Retrying ${attempt}`);\n }\n // give gitlab some time to create pipelines for the sha\n await setTimeout(\n parseInteger(env.RENOVATE_X_GITLAB_BRANCH_STATUS_DELAY, 1000),\n );\n }\n } catch (err) {\n logger.debug({ err });\n logger.warn('Failed to retrieve commit pipeline');\n }\n\n try {\n await gitlabApi.postJson(url, { body: options });\n\n // update status cache\n await getStatus(branchName, false);\n } catch (err) /* v8 ignore next */ {\n if (\n err.body?.message?.startsWith(\n 'Cannot transition status via :enqueue from :pending',\n )\n ) {\n // https://gitlab.com/gitlab-org/gitlab-foss/issues/25807\n logger.debug('Ignoring status transition error');\n } else {\n logger.debug({ err });\n logger.warn('Failed to set branch status');\n }\n }\n}\n\n// Issue\n\nexport async function getIssueList(): Promise<GitlabIssue[]> {\n // v8 ignore else -- TODO: add test #40625\n if (!config.issueList) {\n const searchParams: Record<string, string> = {\n per_page: '100',\n state: 'opened',\n };\n // v8 ignore else -- TODO: add test #40625\n if (!config.ignorePrAuthor) {\n searchParams.scope = 'created_by_me';\n }\n const query = getQueryString(searchParams);\n const res = await gitlabApi.getJsonUnchecked<\n { iid: number; title: string; labels: string[] }[]\n >(`projects/${config.repository}/issues?${query}`, {\n memCache: false,\n paginate: true,\n });\n /* v8 ignore next */\n if (!isArray(res.body)) {\n logger.warn({ responseBody: res.body }, 'Could not retrieve issue list');\n return [];\n }\n config.issueList = res.body.map((i) => ({\n iid: i.iid,\n title: i.title,\n labels: i.labels,\n }));\n }\n return config.issueList;\n}\n\nexport async function getIssue(\n number: number,\n useCache = true,\n): Promise<Issue | null> {\n try {\n const opts: GitlabHttpOptions = {};\n /* v8 ignore next: temporary code */\n if (useCache) {\n opts.cacheProvider = memCacheProvider;\n } else {\n opts.memCache = false;\n }\n const issueBody = (\n await gitlabApi.getJsonUnchecked<{ description: string }>(\n `projects/${config.repository}/issues/${number}`,\n opts,\n )\n ).body.description;\n return {\n number,\n body: issueBody,\n };\n } catch (err) /* v8 ignore next */ {\n logger.debug({ err, number }, 'Error getting issue');\n return null;\n }\n}\n\nexport async function findIssue(title: string): Promise<Issue | null> {\n logger.debug(`findIssue(${title})`);\n try {\n const issueList = await getIssueList();\n const issue = issueList.find((i) => i.title === title);\n if (!issue) {\n return null;\n }\n return await getIssue(issue.iid);\n } catch /* v8 ignore next */ {\n logger.warn('Error finding issue');\n return null;\n }\n}\n\nexport async function ensureIssue({\n title,\n reuseTitle,\n body,\n labels,\n confidential,\n}: EnsureIssueConfig): Promise<'updated' | 'created' | null> {\n logger.debug(`ensureIssue()`);\n const description = massageMarkdown(sanitize(body));\n try {\n const issueList = await getIssueList();\n let issue = issueList.find((i) => i.title === title);\n issue ??= issueList.find((i) => i.title === reuseTitle);\n if (issue) {\n const existingDescription = (\n await gitlabApi.getJsonUnchecked<{ description: string }>(\n `projects/${config.repository}/issues/${issue.iid}`,\n )\n ).body.description;\n if (issue.title !== title || existingDescription !== description) {\n logger.debug('Updating issue');\n await gitlabApi.putJson(\n `projects/${config.repository}/issues/${issue.iid}`,\n {\n body: {\n title,\n description,\n labels: (labels ?? issue.labels ?? []).join(','),\n confidential: confidential ?? false,\n },\n },\n );\n return 'updated';\n }\n } else {\n await gitlabApi.postJson(`projects/${config.repository}/issues`, {\n body: {\n title,\n description,\n labels: (labels ?? []).join(','),\n confidential: confidential ?? false,\n },\n });\n logger.info('Issue created');\n // delete issueList so that it will be refetched as necessary\n delete config.issueList;\n return 'created';\n }\n } catch (err) /* v8 ignore next */ {\n if (err.message.startsWith('Issues are disabled for this repo')) {\n logger.debug(`Could not create issue: ${(err as Error).message}`);\n } else {\n logger.warn({ err }, 'Could not ensure issue');\n }\n }\n return null;\n}\n\nexport async function ensureIssueClosing(title: string): Promise<void> {\n logger.debug(`ensureIssueClosing()`);\n const issueList = await getIssueList();\n for (const issue of issueList) {\n if (issue.title === title) {\n logger.debug({ issue }, 'Closing issue');\n await gitlabApi.putJson(\n `projects/${config.repository}/issues/${issue.iid}`,\n {\n body: { state_event: 'close' },\n },\n );\n }\n }\n}\n\nexport async function addAssignees(\n iid: number,\n assignees: string[],\n): Promise<void> {\n try {\n logger.debug(`Adding assignees '${assignees.join(', ')}' to #${iid}`);\n const assigneeIds: number[] = [];\n for (const assignee of assignees) {\n try {\n const userId = await getUserID(assignee);\n assigneeIds.push(userId);\n } catch (err) {\n logger.debug({ assignee, err }, 'getUserID() error');\n logger.warn({ assignee }, 'Failed to add assignee - could not get ID');\n }\n }\n const url = `projects/${\n config.repository\n }/merge_requests/${iid}?${getQueryString({\n 'assignee_ids[]': assigneeIds,\n })}`;\n await gitlabApi.putJson(url);\n } catch (err) {\n logger.debug({ err }, 'addAssignees error');\n logger.warn({ iid, assignees }, 'Failed to add assignees');\n }\n}\n\nexport async function addReviewers(\n iid: number,\n reviewers: string[],\n): Promise<void> {\n logger.debug(`Adding reviewers '${reviewers.join(', ')}' to #${iid}`);\n\n if (semver.lt(defaults.version, '13.9.0')) {\n logger.warn(\n { version: defaults.version },\n 'Adding reviewers is only available in GitLab 13.9 and onwards',\n );\n return;\n }\n\n let mr: GitLabMergeRequest;\n try {\n mr = await getMR(config.repository, iid);\n } catch (err) {\n logger.warn({ err }, 'Failed to get existing reviewers');\n return;\n }\n\n mr.reviewers = coerceArray(mr.reviewers);\n const existingReviewers = mr.reviewers.map((r) => r.username);\n const existingReviewerIDs = mr.reviewers.map((r) => r.id);\n\n // Figure out which reviewers (of the ones we want to add) are not already on the MR as a reviewer\n const newReviewers = reviewers.filter((r) => !existingReviewers.includes(r));\n\n // Gather the IDs for all the reviewers we want to add\n let newReviewerIDs: number[];\n newReviewerIDs = (\n await p.all(\n newReviewers.map((r) => async () => {\n try {\n return [await getUserID(r)];\n } catch {\n // Unable to fetch userId, try resolve as a group\n return getMemberUserIDs(r);\n }\n }),\n )\n ).flat();\n\n if (isNonEmptyArray(newReviewers) && isEmptyArray(newReviewerIDs)) {\n logger.warn('Failed to get IDs of the new reviewers');\n return;\n }\n\n // Multiple groups may have the same members, so\n // filter out non-distinct values\n newReviewerIDs = [...new Set(newReviewerIDs)];\n\n try {\n await updateMR(config.repository, iid, {\n reviewer_ids: [...existingReviewerIDs, ...newReviewerIDs],\n });\n } catch (err) {\n logger.warn({ err }, 'Failed to add reviewers');\n }\n}\n\nexport async function deleteLabel(\n issueNo: number,\n label: string,\n): Promise<void> {\n logger.debug(`Deleting label ${label} from #${issueNo}`);\n try {\n const pr = await getPr(issueNo);\n const labels = coerceArray(pr.labels)\n .filter((l: string) => l !== label)\n .join(',');\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${issueNo}`,\n {\n body: { labels },\n },\n );\n } catch (err) /* v8 ignore next */ {\n logger.warn({ err, issueNo, label }, 'Failed to delete label');\n }\n}\n\nasync function getComments(issueNo: number): Promise<GitlabComment[]> {\n // GET projects/:owner/:repo/merge_requests/:number/notes\n logger.debug(`Getting comments for #${issueNo}`);\n const url = `projects/${config.repository}/merge_requests/${issueNo}/notes`;\n const comments = (\n await gitlabApi.getJsonUnchecked<GitlabComment[]>(url, { paginate: true })\n ).body;\n logger.debug(`Found ${comments.length} comments`);\n return comments;\n}\n\nasync function addComment(issueNo: number, body: string): Promise<void> {\n // POST projects/:owner/:repo/merge_requests/:number/notes\n await gitlabApi.postJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes`,\n {\n body: { body },\n },\n );\n}\n\nasync function editComment(\n issueNo: number,\n commentId: number,\n body: string,\n): Promise<void> {\n // PUT projects/:owner/:repo/merge_requests/:number/notes/:id\n await gitlabApi.putJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}`,\n {\n body: { body },\n },\n );\n}\n\nasync function deleteComment(\n issueNo: number,\n commentId: number,\n): Promise<void> {\n // DELETE projects/:owner/:repo/merge_requests/:number/notes/:id\n await gitlabApi.deleteJson(\n `projects/${config.repository}/merge_requests/${issueNo}/notes/${commentId}`,\n );\n}\n\nexport async function ensureComment({\n number,\n topic,\n content,\n}: EnsureCommentConfig): Promise<boolean> {\n const sanitizedContent = sanitize(content);\n const massagedTopic = topic\n ? topic\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/PR/g), 'MR')\n : topic;\n const comments = await getComments(number);\n let body: string;\n let commentId: number | undefined;\n let commentNeedsUpdating: boolean | undefined;\n // TODO: types (#22198)\n if (topic) {\n logger.debug(`Ensuring comment \"${massagedTopic!}\" in #${number}`);\n body = `### ${topic}\\n\\n${sanitizedContent}`;\n body = smartTruncate(\n body\n .replace(regEx(/Pull Request/g), 'Merge Request')\n .replace(regEx(/PR/g), 'MR'),\n maxBodyLength(),\n );\n comments.forEach((comment: { body: string; id: number }) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body.startsWith(`### ${massagedTopic!}\\n\\n`)) {\n commentId = comment.id;\n commentNeedsUpdating = comment.body !== body;\n }\n });\n } else {\n logger.debug(`Ensuring content-only comment in #${number}`);\n body = smartTruncate(`${sanitizedContent}`, maxBodyLength());\n comments.forEach((comment: { body: string; id: number }) => {\n // v8 ignore else -- TODO: add test #40625\n if (comment.body === body) {\n commentId = comment.id;\n commentNeedsUpdating = false;\n }\n });\n }\n if (!commentId) {\n await addComment(number, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Added comment',\n );\n } else if (commentNeedsUpdating) {\n await editComment(number, commentId, body);\n logger.debug(\n { repository: config.repository, issueNo: number },\n 'Updated comment',\n );\n } else {\n logger.debug('Comment is already update-to-date');\n }\n return true;\n}\n\nexport async function ensureCommentRemoval(\n deleteConfig: EnsureCommentRemovalConfig,\n): Promise<void> {\n const { number: issueNo } = deleteConfig;\n const key =\n deleteConfig.type === 'by-topic'\n ? deleteConfig.topic\n : deleteConfig.content;\n logger.debug(`Ensuring comment \"${key}\" in #${issueNo} is removed`);\n\n const comments = await getComments(issueNo);\n let commentId: number | null | undefined = null;\n\n // v8 ignore else -- TODO: add test #40625\n if (deleteConfig.type === 'by-topic') {\n const byTopic = (comment: GitlabComment): boolean =>\n comment.body.startsWith(`### ${deleteConfig.topic}\\n\\n`);\n commentId = comments.find(byTopic)?.id;\n } else if (deleteConfig.type === 'by-content') {\n const byContent = (comment: GitlabComment): boolean =>\n comment.body.trim() === deleteConfig.content;\n commentId = comments.find(byContent)?.id;\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (commentId) {\n await deleteComment(issueNo, commentId);\n }\n}\n\nexport async function filterUnavailableUsers(\n users: string[],\n): Promise<string[]> {\n const filteredUsers: string[] = [];\n for (const user of users) {\n if (!(await isUserBusy(user))) {\n filteredUsers.push(user);\n }\n }\n return filteredUsers;\n}\n\nexport async function expandGroupMembers(\n reviewersOrAssignees: string[],\n): Promise<string[]> {\n const expandedReviewersOrAssignees: string[] = [];\n const normalizedReviewersOrAssigneesWithoutEmails: string[] = [];\n\n // Skip passing user emails to Gitlab API, but include them in the final result\n for (const reviewerOrAssignee of reviewersOrAssignees) {\n if (reviewerOrAssignee.indexOf('@') > 0) {\n expandedReviewersOrAssignees.push(reviewerOrAssignee);\n continue;\n }\n\n // Normalize the potential group names before passing to Gitlab API\n normalizedReviewersOrAssigneesWithoutEmails.push(\n noLeadingAtSymbol(reviewerOrAssignee),\n );\n }\n\n for (const reviewerOrAssignee of normalizedReviewersOrAssigneesWithoutEmails) {\n try {\n const members = await getMemberUsernames(reviewerOrAssignee);\n expandedReviewersOrAssignees.push(...members);\n } catch (err) {\n if (err.statusCode !== 404) {\n logger.debug({ err, reviewerOrAssignee }, 'Unable to fetch group');\n }\n expandedReviewersOrAssignees.push(reviewerOrAssignee);\n }\n }\n return expandedReviewersOrAssignees;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,IAAI,SAWA,EAAE;AAEN,SAAgB,gBAAsB;AACpC,UAAS,EAAE;AACX,eAAc;AACd,UAAS,WAAW;AACpB,UAAS,WAAW;AACpB,UAAS,UAAU;AACnB,YAAW,SAAS,SAAS;;AAG/B,MAAa,KAAK;AAElB,IAAI,cAAc;AAClB,IAAI;AAEJ,eAAsB,aAAa,EACjC,UACA,UACA,OACA,aAC0C;AAC1C,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,0DAA0D;AAE5E,KAAI,UAAU;AACZ,WAAS,WAAW,oBAAoB,SAAS;AACjD,aAAW,SAAS,SAAS;OAE7B,QAAO,MAAM,oCAAoC,SAAS,SAAS;CAErE,MAAM,iBAAiC,EACrC,UAAU,SAAS,UACpB;CACD,IAAI;AACJ,KAAI;AACF,MAAI,CAAC,WAAW;GACd,MAAM,QACJ,MAAM,UAAU,iBAKb,QAAQ,EAAE,OAAO,CAAC,EACrB;AACF,kBAAe,YAAY,GAAG,KAAK,KAAK,IACtC,KAAK,gBAAgB,KAAK,MAC3B;AACD,iBAAc,KAAK;;EAErB,MAAM,MAAM,QAAQ;;AAEpB,MAAI,IAAI,4BACN,iBAAgB,IAAI;MAOpB,kBAJE,MAAM,UAAU,iBAAsC,WAAW,EAC/D,OACD,CAAC,EACF,KACsB;AAE1B,SAAO,MAAM,wBAAwB,cAAc;AAEnD,GAAC,iBAAiB,cAAc,MAAM,IAAI;AAC1C,WAAS,UAAU;UACZ,KAAK;AACZ,SAAO,MACL,EAAE,KAAK,EACP,uFACD;AACD,QAAM,IAAI,MAAM,+BAA+B;;AAEjD,eAAc,OAAO,GAAG,SAAS,SAAS,SAAS,GAC/C,0BACA;AAEJ,iBAAgB;AAEhB,QAAO;;AAIT,eAAsB,SAAS,QAAgD;AAC7E,QAAO,MAAM,sCAAsC;CAEnD,MAAM,cAAmC;EACvC,YAAY;EACZ,UAAU;EACV,6BAA6B;EAC7B,kBAAkB;EAClB,UAAU;EACV,GAAI,QAAQ,QAAQ,EAAE,UAAU,OAAO,MAAM;EAC7C,GAAI,QAAQ,SAAS,EAAE,MAAM,OAAO,OAAO;EAC5C;AACD,KAAI,QAAQ,QAAQ,OAClB,aAAY,QAAQ,OAAO,OAAO,KAAK,IAAI;CAG7C,MAAM,OAAO,EAAE;AACf,KAAI,QAAQ,YAAY,QAAQ;AAC9B,cAAY,cAAc;AAC1B,cAAY,oBAAoB;AAChC,OAAK,KACH,GAAG,OAAO,WAAW,KAClB,cACC,UAAU,UAAU,UAAU,CAAC,YAAY,eACzC,YACD,GACJ,CACF;OAED,MAAK,KAAK,cAAc,eAAe,YAAY,CAAC;AAGtD,KAAI;EACF,MAAM,SACJ,MAAM,KACJ,OACC,QACC,UAAU,iBAAiC,KAAK,EAC9C,UAAU,MACX,CAAC,EACJ,EACE,aAAa,GACd,CACF,EACD,SAAS,aAAa,SAAS,KAAK;AAEtC,SAAO,MAAM,cAAc,MAAM,OAAO,aAAa;AACrD,SAAO,MACJ,QAAQ,SAAS,CAAC,KAAK,UAAU,QAAQ,eAAe,CACxD,KAAK,SAAS,KAAK,oBAAoB;UACnC,KAAK;AACZ,SAAO,MAAM,EAAE,KAAK,EAAE,wBAAwB;AAC9C,QAAM;;;AAMV,SAAS,UAAU,KAA6C;AAC9D,QAAO,KAAK,QAAQ,MAAM,MAAM,EAAE,MAAM;;AAG1C,eAAsB,WACpB,UACA,UACA,aACwB;CACxB,MAAM,kBAAkB,UAAU,SAAS;CAE3C,MAAM,MACJ,YAFW,UAAU,SAAS,IAAI,OAAO,WAExB,oBAAoB,gBAAgB,UACpD,eAAe;CAIlB,MAAM,OAHM,MAAM,UAAU,iBAAsC,KAAK,EACrE,eAAe,kBAChB,CAAC,EACc,KAAK;AAErB,QADY,OAAO,KAAK,KAAK,SAAS,CAAC,UAAU;;AAInD,eAAsB,YACpB,UACA,UACA,aACc;AAEd,QAAO,UADK,MAAM,WAAW,UAAU,UAAU,YAAY,EACvC,SAAS;;AAIjC,eAAsB,SAAS,EAC7B,YACA,iBACA,uBACA,UACkC;AAClC,UAAS,EAAE;AACX,QAAO,aAAa,UAAU,WAAW;AACzC,QAAO,kBAAkB;AACzB,QAAO,wBAAwB;AAC/B,QAAO,iBAAiB,aAAa,IAAI,iBAAiB;CAE1D,IAAI;AACJ,KAAI;AACF,QAAM,MAAM,UAAU,iBACpB,YAAY,OAAO,aACpB;AACD,MAAI,IAAI,KAAK,UAAU;AACrB,UAAO,MACL,8DACD;AACD,SAAM,IAAI,MAAM,oBAAoB;;AAGtC,MAAI,IAAI,KAAK,UAAU,aAAa,IAAI,iBAAiB,KAAK,MAAM;AAClE,UAAO,MACL,8DACD;AACD,SAAM,IAAI,MAAM,oBAAoB;;AAEtC,MAAI,IAAI,KAAK,4BAA4B,YAAY;AACnD,UAAO,MACL,iFACD;AACD,SAAM,IAAI,MAAM,oBAAoB;;AAEtC,MAAI,IAAI,KAAK,gCAAgC,YAAY;AACvD,UAAO,MACL,wEACD;AACD,SAAM,IAAI,MAAM,oBAAoB;;AAEtC,MAAI,IAAI,KAAK,mBAAmB,QAAQ,IAAI,KAAK,WAC/C,OAAM,IAAI,MAAM,iBAAiB;AAEnC,SAAO,gBAAgB,IAAI,KAAK;;AAEhC,MAAI,CAAC,OAAO,eAAe;AACzB,UAAO,KAAK,EAAE,SAAS,IAAI,MAAM,EAAE,gCAAgC;AACnE,SAAM,IAAI,MAAM,gBAAgB;;AAElC,SAAO,cAAc,IAAI,KAAK,gBAAgB;AAC9C,SAAO,qBAAqB,IAAI,KAAK,wBAAwB;AAC7D,MAAI,IAAI,KAAK,cACX,QAAO,SACL,IAAI,KAAK,kBAAkB,YAC3B,IAAI,KAAK,kBAAkB;AAE/B,SAAO,MAAM,GAAG,WAAW,oBAAoB,OAAO,gBAAgB;AACtE,SAAO,MAAM,kBAAkB;EAC/B,MAAM,MAAM,WAAW,YAAY,QAAQ,IAAI;AAC/C,QAAMA,WAAa;GACjB,GAAG;GACH;GACD,CAAC;UACK,2BAA0B;AACjC,SAAO,MAAM,EAAE,KAAK,EAAE,wBAAwB;AAC9C,MAAI,IAAI,QAAQ,SAAS,6BAA6B,CACpD,OAAM,IAAI,MAAM,iBAAiB;AAEnC,MAAI,CAAC,qBAAqB,iBAAiB,CAAC,SAAS,IAAI,QAAQ,CAC/D,OAAM;AAER,MAAI,IAAI,eAAe,IACrB,OAAM,IAAI,MAAM,4BAA4B;AAE9C,MAAI,IAAI,eAAe,IACrB,OAAM,IAAI,MAAM,qBAAqB;AAEvC,MAAI,IAAI,YAAY,oBAClB,OAAM;AAER,SAAO,MAAM,EAAE,KAAK,EAAE,gCAAgC;AACtD,QAAM;;AAOR,QAL+B;EAC7B,eAAe,OAAO;EACtB,QAAQ,CAAC,CAAC,IAAI,KAAK;EACnB,iBAAiB,gBAAgB,IAAI,KAAK,IAAI,SAAS,SAAS;EACjE;;AAIH,SAAgB,uBAAyC;CACvD,MAAM,cACJ,QAAQ,gBAAgB,WAAW,CAAC,OAAO;AAC7C,KAAI,YACF,QAAO,KAAK,MACV,kBAAkB,OAAO,YAAY,kDACtC;AAEH,QAAO,QAAQ,QAAQ,YAAY;;AAqBrC,eAAe,UACb,YACA,WAAW,MACoB;CAC/B,MAAM,YAAYC,gBAAoB,WAAW;AACjD,KAAI;EAEF,MAAM,MAAM,YACV,OAAO,WACR,sBAAsB,UAAW;EAElC,MAAM,OAA0B,EAAE,UAAU,MAAM;AAClD,MAAI,SACF,MAAK,gBAAgB;MAErB,MAAK,WAAW;AAGlB,UAAQ,MAAM,UAAU,iBAAuC,KAAK,KAAK,EACtE;UACI,2BAA0B;AACjC,SAAO,MAAM,EAAE,KAAK,EAAE,8BAA8B;AACpD,MAAI,IAAI,UAAU,eAAe,IAC/B,OAAM,IAAI,MAAM,mBAAmB;AAErC,QAAM;;;AAIV,MAAM,gCAAmE;CACvE,SAAS;CACT,SAAS;CACT,QAAQ;CACR,SAAS;CACT,sBAAsB;CACtB,SAAS;CACT,QAAQ;CACR,UAAU;CACV,SAAS;CACT,WAAW;CACZ;AAGD,eAAsB,gBACpB,YACA,yBACuB;AACvB,QAAO,MAAM,mBAAmB,WAAW,GAAG;AAE9C,KAAI,CAACC,aAAiB,WAAW,CAC/B,OAAM,IAAI,MAAM,mBAAmB;CAGrC,MAAM,iBAAiB,MAAM,UAAU,WAAW;;AAElD,KAAI,CAAC,QAAQ,eAAe,EAAE;AAC5B,SAAO,KACL;GAAE;GAAY;GAAgB,EAC9B,sCACD;AACD,SAAO;;AAET,QAAO,MAAM,gBAAgB,eAAe,OAAO,UAAU;CAE7D,MAAM,KAAK,MAAM,YAAY,WAAW;AACxC,KAAI,MAAM,GAAG,QAAQ,GAAG,mBAAmB,GAAG,oBAAoB;AAChE,SAAO,MACL,4FACD;AACD,iBAAe,KAAK;GAClB,QAAQ,GAAG;GACX,MAAM;GACP,CAAC;;CAGJ,MAAM,MAAM,eAAe,QAAQ,UAAU,MAAM,WAAW,UAAU;AACxE,KAAI,IAAI,WAAW,EAEjB,QAAO;AAET,KACE,CAAC,2BACD,eAAe,OACZ,UACC,MAAM,MAAM,WAAW,YAAY,IACnC,8BAA8B,MAAM,YAAY,QACnD,EACD;AACA,SAAO,MACL,8FACD;AACD,SAAO;;CAET,IAAI,SAAuB;AAC3B,KACG,QAAQ,UAAU,CAAC,MAAM,cAAc,CACvC,SAAS,UAAU;;AAElB,MAAI,WAAW,OAAO;GAEpB,IAAI,eACF,8BAA8B,MAAM;AACtC,OAAI,CAAC,cAAc;AACjB,WAAO,KACL,EAAE,OAAO,EACT,uDACD;AACD,mBAAe;;AAEjB,OAAI,iBAAiB,SAAS;AAC5B,WAAO,MAAM,EAAE,OAAO,EAAE,wBAAwB;AAChD,aAAS;;;GAGb;AACJ,QAAO;;AAIT,eAAsB,YAA2B;AAC/C,QAAO,MAAM,cAAc,OACzB,WACA,OAAO,YACP,aACA,CAAC,CAAC,OAAO,eACV;;AAGH,eAAe,gBAAgB,IAA2B;AACxD,KAAI;EACF,MAAM,MAAM,YAAY,OAAO,WAAW,kBAAkB,GAAG;EAC/D,MAAM,EAAE,MAAM,UAAU,MAAM,UAAU,iBAMtC,IAAI;EAEN,MAAM,WAAW;EAEjB,MAAM,0BAA0B,OAAO,MACpC,EAAE,gBAAgB,cAAc,eAClC;EACD,MAAM,+BAA+B,OAAO,QACzC,EAAE,WAAW,WACZ,cAAc,kBACd,SAAS,YACT,cAAc,qBACd,cAAc,aACjB;AAED,MAAI,8BAA8B,OAChC,OAAMC,IACJ,6BAA6B,KAAK,SAAS,YAA2B;AACpE,SAAM,UAAU,WAAW,GAAG,IAAI,GAAG,KAAK,KAAK;IAC/C,CACH;AAGH,MAAI,yBAAyB;AAC3B,SAAM,UAAU,QAAQ,GAAG,IAAI,GAAG,wBAAwB,MAAM,EAC9D,MAAM;IAAE,GAAG;IAAyB,oBAAoB;IAAG,EAC5D,CAAC;AACF;;AAIF,MAAI,CADsB,OAAO,MAAM,EAAE,WAAW,SAAS,SAAS,CAEpE,OAAM,UAAU,SAAS,KAAK,EAC5B,MAAM;GACJ,MAAM;GACN,oBAAoB;GACrB,EACF,CAAC;UAEG,KAAK;AACZ,SAAO,KAAK,EAAE,KAAK,EAAE,qCAAqC;;;AAI9D,eAAe,eACb,IACA,mBACe;AACf,KAAI;AACF,MAAI,mBAAmB,sBACrB,OAAM,gBAAgB,GAAG;AAG3B,MAAI,mBAAmB,sBAAsB;GAE3C,MAAM,6BAA6B;IACjC;IACA;IACA;IACD;GACD,MAAM,wBAAwB,CAC5B,UACA,UACD;GACD,MAAM,gBAAgB;GACtB,MAAM,MAAM,QAAQ;GAEpB,MAAM,aAAa,aACjB,IAAI,gDACJ,EACD;GAED,MAAM,aAAa,aACjB,IAAI,uCACJ,IACD;AAGD,QAAK,IAAI,UAAU,GAAG,WAAW,YAAY,WAAW,GAAG;IACzD,MAAM,EAAE,SAAS,MAAM,UAAU,iBAO9B,YAAY,OAAO,WAAW,kBAAkB,MAAM,EACvD,UAAU,OACX,CAAC;AAGF,QAAI,KAAK,iCAAiC,MAAM;AAC9C,YAAO,MACL,0EACD;AACD;;IAGF,MAAM,4BAA4B,CAAC,CAAC,KAAK;IACzC,MAAM,8BACJ,6BACA,2BAA2B,SAAS,KAAK,sBAAuB;IAElE,MAAM,gCACJ,CAAC,6BAA6B,KAAK,iBAAiB;AAGtD,SACG,+BAA+B,kCAChC,KAAK,aAAa,QAClB,sBAAsB,SAAS,KAAK,SAAS,OAAO,CAEpD;AAEF,WAAO,MAAM,2CAA2C,UAAU;AAClE,UAAM,WAAW,aAAa,WAAW,EAAE;;AAK7C,QAAK,IAAI,UAAU,GAAG,WAAW,YAAY,WAAW,GAAG;AACzD,QAAI;AACF,WAAM,UAAU,QACd,YAAY,OAAO,WAAW,kBAAkB,GAAG,SACnD,EACE,MAAM;MACJ,6BAA6B;MAC7B,8BAA8B;MAC/B,EACF,CACF;AACD;aACO,KAAK;AACZ,YAAO,MACL,EAAE,KAAK,EACP,6CAA6C,UAC9C;;AAEH,UAAM,WAAW,aAAa,WAAW,EAAE;;;UAGxC,2BAA0B;AACjC,SAAO,MAAM,EAAE,KAAK,EAAE,kCAAkC;;;AAI5D,eAAe,UAAU,UAAiC;CACxD,MAAM,MAAM,QAAQ;CACpB,MAAM,OAA0B,EAAE;AAClC,KAAI,IAAI,qCACN,MAAK,QAAQ,IAAI;AAEnB,QAAO,MAAM,aAAa,SAAS,GAAG;AACtC,KAAI;AACF,QAAM,UAAU,SACd,YAAY,OAAO,WAAW,kBAAkB,SAAS,WACzD,KACD;UACM,KAAK;AACZ,SAAO,KAAK,EAAE,KAAK,EAAE,wCAAwC;;;AAIjE,eAAsB,SAAS,EAC7B,cACA,cACA,SACA,QAAQ,gBACR,SACA,QACA,qBAC8B;CAC9B,IAAI,QAAQ;AACZ,KAAI,QACF,SAAQ,cAAc;CAExB,MAAM,cAAc,SAAS,eAAe;AAC5C,QAAO,MAAM,2BAA2B,QAAQ;CAgBhD,MAAM,KAAK,QAfC,MAAM,UAAU,SAC1B,YAAY,OAAO,WAAW,kBAC9B,EACE,MAAM;EACJ,eAAe;EACf,eAAe;EACf,sBAAsB;EACtB;EACA;EACA,SAAS,UAAU,EAAE,EAAE,KAAK,IAAI;EAChC,QAAQ,OAAO;EAChB,EACF,CACF,EAEqB,KAAK;AAC3B,OAAM,cAAc,MAClB,WACA,OAAO,YACP,aACA,IACA,CAAC,CAAC,OAAO,eACV;AAED,KAAI,mBAAmB,YACrB,OAAM,UAAU,GAAG,OAAO;AAG5B,OAAM,eAAe,GAAG,QAAQ,kBAAkB;AAElD,QAAO;;AAGT,eAAsB,MAAM,KAAgC;AAC1D,QAAO,MAAM,SAAS,IAAI,GAAG;AAI7B,QAAO,OAHI,MAAM,MAAM,OAAO,YAAY,IAAI,CAG7B;;AAGnB,eAAsB,SAAS,EAC7B,QAAQ,KACR,SACA,QAAQ,aACR,WACA,cACA,OACA,mBACA,gBACgC;CAChC,IAAI,QAAQ;AACZ,MAAK,MAAM,WAAW,EAAE,MAAM,OAAO,GAAG,WAAW,IAAI,EAAE,QACvD,SAAQ,cAAc;CAExB,MAAM,WAAW;GACd,WAAW;GACX,SAAS;EAEX,CAAC;CAEF,MAAM,OAAY;EAChB;EACA,aAAa,SAAS,YAAY;EAClC,GAAI,YAAY,EAAE,aAAa,UAAU;EAC1C;AACD,KAAI,aACF,MAAK,gBAAgB;AAGvB,KAAI,UACF,MAAK,aAAa;AAGpB,KAAI,aACF,MAAK,gBAAgB;CAGvB,MAAM,iBACJ,MAAM,UAAU,QACd,YAAY,OAAO,WAAW,kBAAkB,OAChD,EAAE,MAAM,CACT,EACD;CAEF,MAAM,YAAY,OAAO,cAAc;AACvC,OAAM,cAAc,MAClB,WACA,OAAO,YACP,aACA,WACA,CAAC,CAAC,OAAO,eACV;AAED,KAAI,mBAAmB,YACrB,OAAM,UAAU,IAAI;;AAIxB,eAAsB,2BAA2B,EAC/C,QAAQ,KACR,qBACkD;AAClD,OAAM,eAAe,KAAK,kBAAkB;AAE5C,QAAO,MAAM,8CAA8C,MAAM;;AAGnE,eAAsB,QAAQ,EAAE,MAAuC;AACrE,KAAI;AACF,QAAM,UAAU,QACd,YAAY,OAAO,WAAW,kBAAkB,GAAG,SACnD,EACE,MAAM,EACJ,6BAA6B,MAC9B,EACF,CACF;AACD,SAAO;UACA,2BAA0B;AACjC,MAAI,IAAI,eAAe,KAAK;AAC1B,UAAO,MAAM,6BAA6B;AAC1C,UAAO;;AAET,MAAI,IAAI,eAAe,KAAK;AAC1B,UAAO,MAAM,EAAE,KAAK,EAAE,gCAAgC;AACtD,UAAO;;AAET,SAAO,MAAM,EAAE,KAAK,EAAE,iBAAiB;AACvC,SAAO,MAAM,kBAAkB;AAC/B,SAAO;;;AAIX,SAAgB,gBAAgB,OAAuB;AAUrD,QAAO,cATM,MACV,QAAQ,MAAM,gBAAgB,EAAE,gBAAgB,CAChD,QAAQ,MAAM,WAAW,EAAE,QAAQ,CACnC,QAAQ,MAAM,UAAU,EAAE,KAAK,CAC/B,QAAQ,MAAM,WAAW,EAAE,MAAM,CACjC,QAAQ,MAAM,oBAAoB,EAAE,MAAM,CAC1C,QAAQ,MAAM,sBAAsB,EAAE,MAAM,CAE5C,QAAQ,MAAM,UAAU,EAAE,GAAG,EACL,eAAe,CAAC;;AAG7C,SAAgB,gBAAwB;AACtC,KAAI,OAAO,GAAG,SAAS,SAAS,SAAS,EAAE;AACzC,SAAO,MACL,EAAE,SAAS,SAAS,SAAS,EAC7B,qGACD;AACD,SAAO;OAEP,QAAO;;;AAKX,SAAgB,iBAAyB;AACvC,QAAO;;AAKT,SAAS,aAAa,OAAe,cAA+B;AAClE,KAAI,iBAAiB,MACnB,QAAO;AAET,KAAI,aAAa,WAAW,IAAI,CAC9B,QAAO,UAAU,aAAa,UAAU,EAAE;AAE5C,QAAO,UAAU;;AAGnB,eAAsB,OAAO,EAC3B,YACA,SACA,QAAQ,OACR,uBACmC;AACnC,QAAO,MAAM,UAAU,WAAW,IAAI,QAAS,IAAI,MAAM,GAAG;AAE5D,KAAI,qBAAqB;EAMvB,MAAM,EAAE,MAAM,WAJG,MAAM,UAAU,iBAC/B,YAAY,OAAO,WAAW,gCAAgC,WAAW,eAC1E;AAGD,MAAI,CAAC,OAAO,QAAQ;AAClB,UAAO,MAAM,0BAA0B,aAAa;AACpD,UAAO;;AAGT,SAAO,OAAO,OAAO,GAAG;;AAI1B,SADe,MAAM,WAAW,EAEvB,MACJ,MACC,EAAE,iBAAiB,eAClB,CAAC,WAAW,EAAE,MAAM,aAAa,KAAK,QAAQ,aAAa,KAC5D,aAAa,EAAE,OAAO,MAAM,CAC/B,IAAI;;AAKT,eAAsB,YACpB,YAC0B;AAC1B,QAAO,MAAM,eAAe,WAAW,GAAG;CAC1C,MAAM,aAAa,MAAM,OAAO;EAC9B;EACA,OAAO;EACR,CAAC;AACF,QAAO,aAAa,MAAM,WAAW,OAAO,GAAG;;AAGjD,eAAsB,qBACpB,YACA,SAC8B;CAE9B,MAAM,MAAM,MAAM,UAAU,YAAY,MAAM;AAC9C,QAAO,MAAM,gBAAgB,IAAI,OAAO,UAAU;AAClD,MAAK,MAAM,SAAS,IAClB,KAAI,MAAM,SAAS,QACjB,QAAO,8BAA8B,MAAM,WAAW;AAG1D,QAAO;;AAGT,eAAsB,gBAAgB,EACpC,YACA,SACA,aACA,OAAO,eACP,KAAK,aAC+B;CAEpC,MAAM,YAAYF,gBAAoB,WAAW;AACjD,KAAI,CAAC,WAAW;AACd,SAAO,KAAK,sCAAsC;AAClD;;CAGF,MAAM,MAAM,YAAY,OAAO,WAAW,YAAY;CACtD,IAAI,QAAQ;AACZ,KAAI,kBAAkB,SACpB,SAAQ;UACC,kBAAkB,MAC3B,SAAQ;CAEV,MAAM,UAAe;EACnB;EACA;EACA;EACD;;AAGD,KAAI,UACF,SAAQ,aAAa;CAGvB,MAAM,MAAM,QAAQ;CACpB,MAAM,aAAa,aACjB,IAAI,gDACJ,EACD;AAED,KAAI;AACF,OAAK,IAAI,UAAU,GAAG,WAAW,aAAa,GAAG,WAAW,GAAG;GAC7D,MAAM,YAAY,YAAY,OAAO,WAAW,sBAAsB;AACtE,SAAM,UACH,YAAY,WAAW,EAAE,UAAU,OAAO,EAAE,eAAe,CAC3D,SAAS,eAAe;AACvB,YAAQ,cAAc;KACtB;AACJ,OAAI,QAAQ,gBAAgB,OAC1B;AAEF,OAAI,WAAW,aAAa,EAC1B,QAAO,MAAM,kCAAkC,QAAQ,WAAW;OAElE,QAAO,MAAM,sCAAsC,UAAU;AAG/D,SAAM,WACJ,aAAa,IAAI,uCAAuC,IAAK,CAC9D;;UAEI,KAAK;AACZ,SAAO,MAAM,EAAE,KAAK,CAAC;AACrB,SAAO,KAAK,qCAAqC;;AAGnD,KAAI;AACF,QAAM,UAAU,SAAS,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhD,QAAM,UAAU,YAAY,MAAM;UAC3B,2BAA0B;AACjC,MACE,IAAI,MAAM,SAAS,WACjB,sDACD,CAGD,QAAO,MAAM,mCAAmC;OAC3C;AACL,UAAO,MAAM,EAAE,KAAK,CAAC;AACrB,UAAO,KAAK,8BAA8B;;;;AAOhD,eAAsB,eAAuC;;AAE3D,KAAI,CAAC,OAAO,WAAW;EACrB,MAAM,eAAuC;GAC3C,UAAU;GACV,OAAO;GACR;;AAED,MAAI,CAAC,OAAO,eACV,cAAa,QAAQ;EAEvB,MAAM,QAAQ,eAAe,aAAa;EAC1C,MAAM,MAAM,MAAM,UAAU,iBAE1B,YAAY,OAAO,WAAW,UAAU,SAAS;GACjD,UAAU;GACV,UAAU;GACX,CAAC;;AAEF,MAAI,CAAC,QAAQ,IAAI,KAAK,EAAE;AACtB,UAAO,KAAK,EAAE,cAAc,IAAI,MAAM,EAAE,gCAAgC;AACxE,UAAO,EAAE;;AAEX,SAAO,YAAY,IAAI,KAAK,KAAK,OAAO;GACtC,KAAK,EAAE;GACP,OAAO,EAAE;GACT,QAAQ,EAAE;GACX,EAAE;;AAEL,QAAO,OAAO;;AAGhB,eAAsB,SACpB,QACA,WAAW,MACY;AACvB,KAAI;EACF,MAAM,OAA0B,EAAE;;AAElC,MAAI,SACF,MAAK,gBAAgB;MAErB,MAAK,WAAW;AAQlB,SAAO;GACL;GACA,OAPA,MAAM,UAAU,iBACd,YAAY,OAAO,WAAW,UAAU,UACxC,KACD,EACD,KAAK;GAIN;UACM,2BAA0B;AACjC,SAAO,MAAM;GAAE;GAAK;GAAQ,EAAE,sBAAsB;AACpD,SAAO;;;AAIX,eAAsB,UAAU,OAAsC;AACpE,QAAO,MAAM,aAAa,MAAM,GAAG;AACnC,KAAI;EAEF,MAAM,SADY,MAAM,cAAc,EACd,MAAM,MAAM,EAAE,UAAU,MAAM;AACtD,MAAI,CAAC,MACH,QAAO;AAET,SAAO,MAAM,SAAS,MAAM,IAAI;+BACL;AAC3B,SAAO,KAAK,sBAAsB;AAClC,SAAO;;;AAIX,eAAsB,YAAY,EAChC,OACA,YACA,MACA,QACA,gBAC2D;AAC3D,QAAO,MAAM,gBAAgB;CAC7B,MAAM,cAAc,gBAAgB,SAAS,KAAK,CAAC;AACnD,KAAI;EACF,MAAM,YAAY,MAAM,cAAc;EACtC,IAAI,QAAQ,UAAU,MAAM,MAAM,EAAE,UAAU,MAAM;AACpD,YAAU,UAAU,MAAM,MAAM,EAAE,UAAU,WAAW;AACvD,MAAI,OAAO;GACT,MAAM,uBACJ,MAAM,UAAU,iBACd,YAAY,OAAO,WAAW,UAAU,MAAM,MAC/C,EACD,KAAK;AACP,OAAI,MAAM,UAAU,SAAS,wBAAwB,aAAa;AAChE,WAAO,MAAM,iBAAiB;AAC9B,UAAM,UAAU,QACd,YAAY,OAAO,WAAW,UAAU,MAAM,OAC9C,EACE,MAAM;KACJ;KACA;KACA,SAAS,UAAU,MAAM,UAAU,EAAE,EAAE,KAAK,IAAI;KAChD,cAAc,gBAAgB;KAC/B,EACF,CACF;AACD,WAAO;;SAEJ;AACL,SAAM,UAAU,SAAS,YAAY,OAAO,WAAW,UAAU,EAC/D,MAAM;IACJ;IACA;IACA,SAAS,UAAU,EAAE,EAAE,KAAK,IAAI;IAChC,cAAc,gBAAgB;IAC/B,EACF,CAAC;AACF,UAAO,KAAK,gBAAgB;AAE5B,UAAO,OAAO;AACd,UAAO;;UAEF,2BAA0B;AACjC,MAAI,IAAI,QAAQ,WAAW,oCAAoC,CAC7D,QAAO,MAAM,2BAA4B,IAAc,UAAU;MAEjE,QAAO,KAAK,EAAE,KAAK,EAAE,yBAAyB;;AAGlD,QAAO;;AAGT,eAAsB,mBAAmB,OAA8B;AACrE,QAAO,MAAM,uBAAuB;CACpC,MAAM,YAAY,MAAM,cAAc;AACtC,MAAK,MAAM,SAAS,UAClB,KAAI,MAAM,UAAU,OAAO;AACzB,SAAO,MAAM,EAAE,OAAO,EAAE,gBAAgB;AACxC,QAAM,UAAU,QACd,YAAY,OAAO,WAAW,UAAU,MAAM,OAC9C,EACE,MAAM,EAAE,aAAa,SAAS,EAC/B,CACF;;;AAKP,eAAsB,aACpB,KACA,WACe;AACf,KAAI;AACF,SAAO,MAAM,qBAAqB,UAAU,KAAK,KAAK,CAAC,QAAQ,MAAM;EACrE,MAAM,cAAwB,EAAE;AAChC,OAAK,MAAM,YAAY,UACrB,KAAI;GACF,MAAM,SAAS,MAAM,UAAU,SAAS;AACxC,eAAY,KAAK,OAAO;WACjB,KAAK;AACZ,UAAO,MAAM;IAAE;IAAU;IAAK,EAAE,oBAAoB;AACpD,UAAO,KAAK,EAAE,UAAU,EAAE,4CAA4C;;EAG1E,MAAM,MAAM,YACV,OAAO,WACR,kBAAkB,IAAI,GAAG,eAAe,EACvC,kBAAkB,aACnB,CAAC;AACF,QAAM,UAAU,QAAQ,IAAI;UACrB,KAAK;AACZ,SAAO,MAAM,EAAE,KAAK,EAAE,qBAAqB;AAC3C,SAAO,KAAK;GAAE;GAAK;GAAW,EAAE,0BAA0B;;;AAI9D,eAAsB,aACpB,KACA,WACe;AACf,QAAO,MAAM,qBAAqB,UAAU,KAAK,KAAK,CAAC,QAAQ,MAAM;AAErE,KAAI,OAAO,GAAG,SAAS,SAAS,SAAS,EAAE;AACzC,SAAO,KACL,EAAE,SAAS,SAAS,SAAS,EAC7B,gEACD;AACD;;CAGF,IAAI;AACJ,KAAI;AACF,OAAK,MAAM,MAAM,OAAO,YAAY,IAAI;UACjC,KAAK;AACZ,SAAO,KAAK,EAAE,KAAK,EAAE,mCAAmC;AACxD;;AAGF,IAAG,YAAY,YAAY,GAAG,UAAU;CACxC,MAAM,oBAAoB,GAAG,UAAU,KAAK,MAAM,EAAE,SAAS;CAC7D,MAAM,sBAAsB,GAAG,UAAU,KAAK,MAAM,EAAE,GAAG;CAGzD,MAAM,eAAe,UAAU,QAAQ,MAAM,CAAC,kBAAkB,SAAS,EAAE,CAAC;CAG5E,IAAI;AACJ,mBACE,MAAME,IACJ,aAAa,KAAK,MAAM,YAAY;AAClC,MAAI;AACF,UAAO,CAAC,MAAM,UAAU,EAAE,CAAC;UACrB;AAEN,UAAO,iBAAiB,EAAE;;GAE5B,CACH,EACD,MAAM;AAER,KAAI,gBAAgB,aAAa,IAAI,aAAa,eAAe,EAAE;AACjE,SAAO,KAAK,yCAAyC;AACrD;;AAKF,kBAAiB,CAAC,GAAG,IAAI,IAAI,eAAe,CAAC;AAE7C,KAAI;AACF,QAAM,SAAS,OAAO,YAAY,KAAK,EACrC,cAAc,CAAC,GAAG,qBAAqB,GAAG,eAAe,EAC1D,CAAC;UACK,KAAK;AACZ,SAAO,KAAK,EAAE,KAAK,EAAE,0BAA0B;;;AAInD,eAAsB,YACpB,SACA,OACe;AACf,QAAO,MAAM,kBAAkB,MAAM,SAAS,UAAU;AACxD,KAAI;EAEF,MAAM,SAAS,aADJ,MAAM,MAAM,QAAQ,EACD,OAAO,CAClC,QAAQ,MAAc,MAAM,MAAM,CAClC,KAAK,IAAI;AACZ,QAAM,UAAU,QACd,YAAY,OAAO,WAAW,kBAAkB,WAChD,EACE,MAAM,EAAE,QAAQ,EACjB,CACF;UACM,2BAA0B;AACjC,SAAO,KAAK;GAAE;GAAK;GAAS;GAAO,EAAE,yBAAyB;;;AAIlE,eAAe,YAAY,SAA2C;AAEpE,QAAO,MAAM,yBAAyB,UAAU;CAChD,MAAM,MAAM,YAAY,OAAO,WAAW,kBAAkB,QAAQ;CACpE,MAAM,YACJ,MAAM,UAAU,iBAAkC,KAAK,EAAE,UAAU,MAAM,CAAC,EAC1E;AACF,QAAO,MAAM,SAAS,SAAS,OAAO,WAAW;AACjD,QAAO;;AAGT,eAAe,WAAW,SAAiB,MAA6B;AAEtE,OAAM,UAAU,SACd,YAAY,OAAO,WAAW,kBAAkB,QAAQ,SACxD,EACE,MAAM,EAAE,MAAM,EACf,CACF;;AAGH,eAAe,YACb,SACA,WACA,MACe;AAEf,OAAM,UAAU,QACd,YAAY,OAAO,WAAW,kBAAkB,QAAQ,SAAS,aACjE,EACE,MAAM,EAAE,MAAM,EACf,CACF;;AAGH,eAAe,cACb,SACA,WACe;AAEf,OAAM,UAAU,WACd,YAAY,OAAO,WAAW,kBAAkB,QAAQ,SAAS,YAClE;;AAGH,eAAsB,cAAc,EAClC,QACA,OACA,WACwC;CACxC,MAAM,mBAAmB,SAAS,QAAQ;CAC1C,MAAM,gBAAgB,QAClB,MACG,QAAQ,MAAM,gBAAgB,EAAE,gBAAgB,CAChD,QAAQ,MAAM,MAAM,EAAE,KAAK,GAC9B;CACJ,MAAM,WAAW,MAAM,YAAY,OAAO;CAC1C,IAAI;CACJ,IAAI;CACJ,IAAI;AAEJ,KAAI,OAAO;AACT,SAAO,MAAM,qBAAqB,cAAe,QAAQ,SAAS;AAClE,SAAO,OAAO,MAAM,MAAM;AAC1B,SAAO,cACL,KACG,QAAQ,MAAM,gBAAgB,EAAE,gBAAgB,CAChD,QAAQ,MAAM,MAAM,EAAE,KAAK,EAC9B,eAAe,CAChB;AACD,WAAS,SAAS,YAA0C;;AAE1D,OAAI,QAAQ,KAAK,WAAW,OAAO,cAAe,MAAM,EAAE;AACxD,gBAAY,QAAQ;AACpB,2BAAuB,QAAQ,SAAS;;IAE1C;QACG;AACL,SAAO,MAAM,qCAAqC,SAAS;AAC3D,SAAO,cAAc,GAAG,oBAAoB,eAAe,CAAC;AAC5D,WAAS,SAAS,YAA0C;;AAE1D,OAAI,QAAQ,SAAS,MAAM;AACzB,gBAAY,QAAQ;AACpB,2BAAuB;;IAEzB;;AAEJ,KAAI,CAAC,WAAW;AACd,QAAM,WAAW,QAAQ,KAAK;AAC9B,SAAO,MACL;GAAE,YAAY,OAAO;GAAY,SAAS;GAAQ,EAClD,gBACD;YACQ,sBAAsB;AAC/B,QAAM,YAAY,QAAQ,WAAW,KAAK;AAC1C,SAAO,MACL;GAAE,YAAY,OAAO;GAAY,SAAS;GAAQ,EAClD,kBACD;OAED,QAAO,MAAM,oCAAoC;AAEnD,QAAO;;AAGT,eAAsB,qBACpB,cACe;CACf,MAAM,EAAE,QAAQ,YAAY;CAC5B,MAAM,MACJ,aAAa,SAAS,aAClB,aAAa,QACb,aAAa;AACnB,QAAO,MAAM,qBAAqB,IAAI,QAAQ,QAAQ,aAAa;CAEnE,MAAM,WAAW,MAAM,YAAY,QAAQ;CAC3C,IAAI,YAAuC;;AAG3C,KAAI,aAAa,SAAS,YAAY;EACpC,MAAM,WAAW,YACf,QAAQ,KAAK,WAAW,OAAO,aAAa,MAAM,MAAM;AAC1D,cAAY,SAAS,KAAK,QAAQ,EAAE;YAC3B,aAAa,SAAS,cAAc;EAC7C,MAAM,aAAa,YACjB,QAAQ,KAAK,MAAM,KAAK,aAAa;AACvC,cAAY,SAAS,KAAK,UAAU,EAAE;;;AAIxC,KAAI,UACF,OAAM,cAAc,SAAS,UAAU;;AAI3C,eAAsB,uBACpB,OACmB;CACnB,MAAM,gBAA0B,EAAE;AAClC,MAAK,MAAM,QAAQ,MACjB,KAAI,CAAE,MAAM,WAAW,KAAK,CAC1B,eAAc,KAAK,KAAK;AAG5B,QAAO;;AAGT,eAAsB,mBACpB,sBACmB;CACnB,MAAM,+BAAyC,EAAE;CACjD,MAAM,8CAAwD,EAAE;AAGhE,MAAK,MAAM,sBAAsB,sBAAsB;AACrD,MAAI,mBAAmB,QAAQ,IAAI,GAAG,GAAG;AACvC,gCAA6B,KAAK,mBAAmB;AACrD;;AAIF,8CAA4C,KAC1C,kBAAkB,mBAAmB,CACtC;;AAGH,MAAK,MAAM,sBAAsB,4CAC/B,KAAI;EACF,MAAM,UAAU,MAAM,mBAAmB,mBAAmB;AAC5D,+BAA6B,KAAK,GAAG,QAAQ;UACtC,KAAK;AACZ,MAAI,IAAI,eAAe,IACrB,QAAO,MAAM;GAAE;GAAK;GAAoB,EAAE,wBAAwB;AAEpE,+BAA6B,KAAK,mBAAmB;;AAGzD,QAAO"}
@@ -55,8 +55,10 @@ function getDepWarningsPR(packageFiles, config, dependencyDashboard) {
55
55
  if (!warnings.length) return "";
56
56
  warningText = emojify(`\n---\n\n> :warning: **Warning**\n> \n`);
57
57
  warningText += "> Some dependencies could not be looked up. ";
58
- if (dependencyDashboard) warningText += `Check the Dependency Dashboard for more information.\n\n`;
59
- else warningText += `Check the warning logs for more information.\n\n`;
58
+ if (dependencyDashboard) {
59
+ const depDashboardMd = config.dependencyDashboardIssue ? `[Dependency Dashboard](../issues/${config.dependencyDashboardIssue})` : "Dependency Dashboard";
60
+ warningText += `Check the ${depDashboardMd} for more information.\n\n`;
61
+ } else warningText += `Check the warning logs for more information.\n\n`;
60
62
  return warningText;
61
63
  }
62
64
  function getDepWarningsDashboard(packageFiles, config) {
@@ -1 +1 @@
1
- {"version":3,"file":"errors-warnings.js","names":[],"sources":["../../../lib/workers/repository/errors-warnings.ts"],"sourcesContent":["// TODO #22198\nimport type { RenovateConfig } from '../../config/types.ts';\nimport { logger } from '../../logger/index.ts';\nimport type { PackageFile } from '../../modules/manager/types.ts';\nimport { coerceArray } from '../../util/array.ts';\nimport { emojify } from '../../util/emoji.ts';\nimport { regEx } from '../../util/regex.ts';\nimport type { DepWarnings } from '../types.ts';\n\nexport function getWarnings(config: RenovateConfig): string {\n if (!config.warnings?.length) {\n return '';\n }\n let warningText = `\\n# Warnings (${config.warnings.length})\\n\\n`;\n warningText += `Please correct - or verify that you can safely ignore - these warnings before you merge this PR.\\n\\n`;\n for (const w of config.warnings) {\n warningText += `- \\`${w.topic}\\`: ${w.message}\\n`;\n }\n warningText += '\\n---\\n';\n return warningText;\n}\n\nexport function getErrors(config: RenovateConfig): string {\n if (!config.errors?.length) {\n return '';\n }\n let errorText = `\\n# Errors (${config.errors.length})\\n\\n`;\n errorText += `Renovate has found errors that you should fix (in this branch) before finishing this PR.\\n\\n`;\n for (const e of config.errors) {\n errorText += `- \\`${e.topic}\\`: ${e.message}\\n`;\n }\n errorText += '\\n---\\n';\n return errorText;\n}\n\nfunction getDepWarnings(\n packageFiles: Record<string, PackageFile[]>,\n): DepWarnings {\n const warnings: string[] = [];\n const warningFiles: string[] = [];\n for (const files of Object.values(packageFiles ?? {})) {\n for (const file of files ?? []) {\n // TODO: remove condition when type is fixed (#22198)\n if (file.packageFile) {\n for (const dep of coerceArray(file.deps)) {\n for (const w of coerceArray(dep.warnings)) {\n const message = w.message;\n if (!warnings.includes(message)) {\n warnings.push(message);\n }\n if (!warningFiles.includes(file.packageFile)) {\n warningFiles.push(file.packageFile);\n }\n }\n }\n }\n }\n }\n if (warnings.length) {\n logger.warn({ warnings, files: warningFiles }, 'Package lookup failures');\n }\n return { warnings, warningFiles };\n}\n\nexport function getDepWarningsOnboardingPR(\n packageFiles: Record<string, PackageFile[]>,\n config: RenovateConfig,\n): string {\n const { warnings, warningFiles } = getDepWarnings(packageFiles);\n if (config.suppressNotifications?.includes('dependencyLookupWarnings')) {\n return '';\n }\n let warningText = '';\n if (!warnings.length) {\n return '';\n }\n warningText = emojify(`\\n---\\n> \\n> :warning: **Warning**\\n> \\n`);\n warningText += `> Please correct - or verify that you can safely ignore - these dependency lookup failures before you merge this PR.\\n> \\n`;\n for (const w of warnings) {\n warningText += `> - \\`${w}\\`\\n`;\n }\n warningText +=\n '> \\n> Files affected: ' +\n warningFiles.map((f) => '`' + f + '`').join(', ') +\n '\\n\\n';\n return warningText;\n}\n\nexport function getDepWarningsPR(\n packageFiles: Record<string, PackageFile[]>,\n config: RenovateConfig,\n dependencyDashboard?: boolean,\n): string {\n const { warnings } = getDepWarnings(packageFiles);\n if (config.suppressNotifications?.includes('dependencyLookupWarnings')) {\n return '';\n }\n let warningText = '';\n if (!warnings.length) {\n return '';\n }\n warningText = emojify(`\\n---\\n\\n> :warning: **Warning**\\n> \\n`);\n warningText += '> Some dependencies could not be looked up. ';\n if (dependencyDashboard) {\n warningText += `Check the Dependency Dashboard for more information.\\n\\n`;\n } else {\n warningText += `Check the warning logs for more information.\\n\\n`;\n }\n return warningText;\n}\n\nexport function getDepWarningsDashboard(\n packageFiles: Record<string, PackageFile[]>,\n config: RenovateConfig,\n): string {\n if (config.suppressNotifications?.includes('dependencyLookupWarnings')) {\n return '';\n }\n const { warnings, warningFiles } = getDepWarnings(packageFiles);\n if (!warnings.length) {\n return '';\n }\n\n const depWarnings = warnings\n .map((w) =>\n w.replace(regEx(/^Failed to look up(?: [-\\w]+)? dependency /), ''),\n )\n .map((dep) => '`' + dep + '`')\n .join(', ');\n\n let warningText = emojify(\n `\\n---\\n\\n> :warning: **Warning**\\n> \\n> Renovate failed to look up the following dependencies: `,\n );\n warningText += depWarnings;\n warningText += '.\\n> \\n> Files affected: ';\n warningText += warningFiles.map((f) => '`' + f + '`').join(', ');\n warningText += '\\n\\n---\\n\\n';\n return warningText;\n}\n"],"mappings":";;;;;;AASA,SAAgB,YAAY,QAAgC;AAC1D,KAAI,CAAC,OAAO,UAAU,OACpB,QAAO;CAET,IAAI,cAAc,iBAAiB,OAAO,SAAS,OAAO;AAC1D,gBAAe;AACf,MAAK,MAAM,KAAK,OAAO,SACrB,gBAAe,SAAS,EAAE,MAAM,MAAM,EAAE,QAAQ;AAElD,gBAAe;AACf,QAAO;;AAGT,SAAgB,UAAU,QAAgC;AACxD,KAAI,CAAC,OAAO,QAAQ,OAClB,QAAO;CAET,IAAI,YAAY,eAAe,OAAO,OAAO,OAAO;AACpD,cAAa;AACb,MAAK,MAAM,KAAK,OAAO,OACrB,cAAa,SAAS,EAAE,MAAM,MAAM,EAAE,QAAQ;AAEhD,cAAa;AACb,QAAO;;AAGT,SAAS,eACP,cACa;CACb,MAAM,WAAqB,EAAE;CAC7B,MAAM,eAAyB,EAAE;AACjC,MAAK,MAAM,SAAS,OAAO,OAAO,gBAAgB,EAAE,CAAC,CACnD,MAAK,MAAM,QAAQ,SAAS,EAAE,CAE5B,KAAI,KAAK,YACP,MAAK,MAAM,OAAO,YAAY,KAAK,KAAK,CACtC,MAAK,MAAM,KAAK,YAAY,IAAI,SAAS,EAAE;EACzC,MAAM,UAAU,EAAE;AAClB,MAAI,CAAC,SAAS,SAAS,QAAQ,CAC7B,UAAS,KAAK,QAAQ;AAExB,MAAI,CAAC,aAAa,SAAS,KAAK,YAAY,CAC1C,cAAa,KAAK,KAAK,YAAY;;AAO/C,KAAI,SAAS,OACX,QAAO,KAAK;EAAE;EAAU,OAAO;EAAc,EAAE,0BAA0B;AAE3E,QAAO;EAAE;EAAU;EAAc;;AAGnC,SAAgB,2BACd,cACA,QACQ;CACR,MAAM,EAAE,UAAU,iBAAiB,eAAe,aAAa;AAC/D,KAAI,OAAO,uBAAuB,SAAS,2BAA2B,CACpE,QAAO;CAET,IAAI,cAAc;AAClB,KAAI,CAAC,SAAS,OACZ,QAAO;AAET,eAAc,QAAQ,2CAA2C;AACjE,gBAAe;AACf,MAAK,MAAM,KAAK,SACd,gBAAe,WAAW,EAAE;AAE9B,gBACE,2BACA,aAAa,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,GACjD;AACF,QAAO;;AAGT,SAAgB,iBACd,cACA,QACA,qBACQ;CACR,MAAM,EAAE,aAAa,eAAe,aAAa;AACjD,KAAI,OAAO,uBAAuB,SAAS,2BAA2B,CACpE,QAAO;CAET,IAAI,cAAc;AAClB,KAAI,CAAC,SAAS,OACZ,QAAO;AAET,eAAc,QAAQ,yCAAyC;AAC/D,gBAAe;AACf,KAAI,oBACF,gBAAe;KAEf,gBAAe;AAEjB,QAAO;;AAGT,SAAgB,wBACd,cACA,QACQ;AACR,KAAI,OAAO,uBAAuB,SAAS,2BAA2B,CACpE,QAAO;CAET,MAAM,EAAE,UAAU,iBAAiB,eAAe,aAAa;AAC/D,KAAI,CAAC,SAAS,OACZ,QAAO;CAGT,MAAM,cAAc,SACjB,KAAK,MACJ,EAAE,QAAQ,MAAM,6CAA6C,EAAE,GAAG,CACnE,CACA,KAAK,QAAQ,MAAM,MAAM,IAAI,CAC7B,KAAK,KAAK;CAEb,IAAI,cAAc,QAChB,kGACD;AACD,gBAAe;AACf,gBAAe;AACf,gBAAe,aAAa,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK;AAChE,gBAAe;AACf,QAAO"}
1
+ {"version":3,"file":"errors-warnings.js","names":[],"sources":["../../../lib/workers/repository/errors-warnings.ts"],"sourcesContent":["// TODO #22198\nimport type { RenovateConfig } from '../../config/types.ts';\nimport { logger } from '../../logger/index.ts';\nimport type { PackageFile } from '../../modules/manager/types.ts';\nimport { coerceArray } from '../../util/array.ts';\nimport { emojify } from '../../util/emoji.ts';\nimport { regEx } from '../../util/regex.ts';\nimport type { DepWarnings } from '../types.ts';\n\nexport function getWarnings(config: RenovateConfig): string {\n if (!config.warnings?.length) {\n return '';\n }\n let warningText = `\\n# Warnings (${config.warnings.length})\\n\\n`;\n warningText += `Please correct - or verify that you can safely ignore - these warnings before you merge this PR.\\n\\n`;\n for (const w of config.warnings) {\n warningText += `- \\`${w.topic}\\`: ${w.message}\\n`;\n }\n warningText += '\\n---\\n';\n return warningText;\n}\n\nexport function getErrors(config: RenovateConfig): string {\n if (!config.errors?.length) {\n return '';\n }\n let errorText = `\\n# Errors (${config.errors.length})\\n\\n`;\n errorText += `Renovate has found errors that you should fix (in this branch) before finishing this PR.\\n\\n`;\n for (const e of config.errors) {\n errorText += `- \\`${e.topic}\\`: ${e.message}\\n`;\n }\n errorText += '\\n---\\n';\n return errorText;\n}\n\nfunction getDepWarnings(\n packageFiles: Record<string, PackageFile[]>,\n): DepWarnings {\n const warnings: string[] = [];\n const warningFiles: string[] = [];\n for (const files of Object.values(packageFiles ?? {})) {\n for (const file of files ?? []) {\n // TODO: remove condition when type is fixed (#22198)\n if (file.packageFile) {\n for (const dep of coerceArray(file.deps)) {\n for (const w of coerceArray(dep.warnings)) {\n const message = w.message;\n if (!warnings.includes(message)) {\n warnings.push(message);\n }\n if (!warningFiles.includes(file.packageFile)) {\n warningFiles.push(file.packageFile);\n }\n }\n }\n }\n }\n }\n if (warnings.length) {\n logger.warn({ warnings, files: warningFiles }, 'Package lookup failures');\n }\n return { warnings, warningFiles };\n}\n\nexport function getDepWarningsOnboardingPR(\n packageFiles: Record<string, PackageFile[]>,\n config: RenovateConfig,\n): string {\n const { warnings, warningFiles } = getDepWarnings(packageFiles);\n if (config.suppressNotifications?.includes('dependencyLookupWarnings')) {\n return '';\n }\n let warningText = '';\n if (!warnings.length) {\n return '';\n }\n warningText = emojify(`\\n---\\n> \\n> :warning: **Warning**\\n> \\n`);\n warningText += `> Please correct - or verify that you can safely ignore - these dependency lookup failures before you merge this PR.\\n> \\n`;\n for (const w of warnings) {\n warningText += `> - \\`${w}\\`\\n`;\n }\n warningText +=\n '> \\n> Files affected: ' +\n warningFiles.map((f) => '`' + f + '`').join(', ') +\n '\\n\\n';\n return warningText;\n}\n\nexport function getDepWarningsPR(\n packageFiles: Record<string, PackageFile[]>,\n config: RenovateConfig,\n dependencyDashboard?: boolean,\n): string {\n const { warnings } = getDepWarnings(packageFiles);\n if (config.suppressNotifications?.includes('dependencyLookupWarnings')) {\n return '';\n }\n let warningText = '';\n if (!warnings.length) {\n return '';\n }\n warningText = emojify(`\\n---\\n\\n> :warning: **Warning**\\n> \\n`);\n warningText += '> Some dependencies could not be looked up. ';\n if (dependencyDashboard) {\n const depDashboardMd = config.dependencyDashboardIssue\n ? `[Dependency Dashboard](../issues/${config.dependencyDashboardIssue})`\n : 'Dependency Dashboard';\n warningText += `Check the ${depDashboardMd} for more information.\\n\\n`;\n } else {\n warningText += `Check the warning logs for more information.\\n\\n`;\n }\n return warningText;\n}\n\nexport function getDepWarningsDashboard(\n packageFiles: Record<string, PackageFile[]>,\n config: RenovateConfig,\n): string {\n if (config.suppressNotifications?.includes('dependencyLookupWarnings')) {\n return '';\n }\n const { warnings, warningFiles } = getDepWarnings(packageFiles);\n if (!warnings.length) {\n return '';\n }\n\n const depWarnings = warnings\n .map((w) =>\n w.replace(regEx(/^Failed to look up(?: [-\\w]+)? dependency /), ''),\n )\n .map((dep) => '`' + dep + '`')\n .join(', ');\n\n let warningText = emojify(\n `\\n---\\n\\n> :warning: **Warning**\\n> \\n> Renovate failed to look up the following dependencies: `,\n );\n warningText += depWarnings;\n warningText += '.\\n> \\n> Files affected: ';\n warningText += warningFiles.map((f) => '`' + f + '`').join(', ');\n warningText += '\\n\\n---\\n\\n';\n return warningText;\n}\n"],"mappings":";;;;;;AASA,SAAgB,YAAY,QAAgC;AAC1D,KAAI,CAAC,OAAO,UAAU,OACpB,QAAO;CAET,IAAI,cAAc,iBAAiB,OAAO,SAAS,OAAO;AAC1D,gBAAe;AACf,MAAK,MAAM,KAAK,OAAO,SACrB,gBAAe,SAAS,EAAE,MAAM,MAAM,EAAE,QAAQ;AAElD,gBAAe;AACf,QAAO;;AAGT,SAAgB,UAAU,QAAgC;AACxD,KAAI,CAAC,OAAO,QAAQ,OAClB,QAAO;CAET,IAAI,YAAY,eAAe,OAAO,OAAO,OAAO;AACpD,cAAa;AACb,MAAK,MAAM,KAAK,OAAO,OACrB,cAAa,SAAS,EAAE,MAAM,MAAM,EAAE,QAAQ;AAEhD,cAAa;AACb,QAAO;;AAGT,SAAS,eACP,cACa;CACb,MAAM,WAAqB,EAAE;CAC7B,MAAM,eAAyB,EAAE;AACjC,MAAK,MAAM,SAAS,OAAO,OAAO,gBAAgB,EAAE,CAAC,CACnD,MAAK,MAAM,QAAQ,SAAS,EAAE,CAE5B,KAAI,KAAK,YACP,MAAK,MAAM,OAAO,YAAY,KAAK,KAAK,CACtC,MAAK,MAAM,KAAK,YAAY,IAAI,SAAS,EAAE;EACzC,MAAM,UAAU,EAAE;AAClB,MAAI,CAAC,SAAS,SAAS,QAAQ,CAC7B,UAAS,KAAK,QAAQ;AAExB,MAAI,CAAC,aAAa,SAAS,KAAK,YAAY,CAC1C,cAAa,KAAK,KAAK,YAAY;;AAO/C,KAAI,SAAS,OACX,QAAO,KAAK;EAAE;EAAU,OAAO;EAAc,EAAE,0BAA0B;AAE3E,QAAO;EAAE;EAAU;EAAc;;AAGnC,SAAgB,2BACd,cACA,QACQ;CACR,MAAM,EAAE,UAAU,iBAAiB,eAAe,aAAa;AAC/D,KAAI,OAAO,uBAAuB,SAAS,2BAA2B,CACpE,QAAO;CAET,IAAI,cAAc;AAClB,KAAI,CAAC,SAAS,OACZ,QAAO;AAET,eAAc,QAAQ,2CAA2C;AACjE,gBAAe;AACf,MAAK,MAAM,KAAK,SACd,gBAAe,WAAW,EAAE;AAE9B,gBACE,2BACA,aAAa,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,GACjD;AACF,QAAO;;AAGT,SAAgB,iBACd,cACA,QACA,qBACQ;CACR,MAAM,EAAE,aAAa,eAAe,aAAa;AACjD,KAAI,OAAO,uBAAuB,SAAS,2BAA2B,CACpE,QAAO;CAET,IAAI,cAAc;AAClB,KAAI,CAAC,SAAS,OACZ,QAAO;AAET,eAAc,QAAQ,yCAAyC;AAC/D,gBAAe;AACf,KAAI,qBAAqB;EACvB,MAAM,iBAAiB,OAAO,2BAC1B,oCAAoC,OAAO,yBAAyB,KACpE;AACJ,iBAAe,aAAa,eAAe;OAE3C,gBAAe;AAEjB,QAAO;;AAGT,SAAgB,wBACd,cACA,QACQ;AACR,KAAI,OAAO,uBAAuB,SAAS,2BAA2B,CACpE,QAAO;CAET,MAAM,EAAE,UAAU,iBAAiB,eAAe,aAAa;AAC/D,KAAI,CAAC,SAAS,OACZ,QAAO;CAGT,MAAM,cAAc,SACjB,KAAK,MACJ,EAAE,QAAQ,MAAM,6CAA6C,EAAE,GAAG,CACnE,CACA,KAAK,QAAQ,MAAM,MAAM,IAAI,CAC7B,KAAK,KAAK;CAEb,IAAI,cAAc,QAChB,kGACD;AACD,gBAAe;AACf,gBAAe;AACf,gBAAe,aAAa,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK;AAChE,gBAAe;AACf,QAAO"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "renovate",
3
3
  "description": "Automated dependency updates. Flexible so you don't need to be.",
4
- "version": "43.28.0",
4
+ "version": "43.29.1",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "renovate": "dist/renovate.js",
@@ -1,7 +1,7 @@
1
1
  {
2
- "title": "JSON schema for Renovate 43.28.0 config files (https://renovatebot.com/)",
2
+ "title": "JSON schema for Renovate 43.29.1 config files (https://renovatebot.com/)",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
- "x-renovate-version": "43.28.0",
4
+ "x-renovate-version": "43.29.1",
5
5
  "allowComments": true,
6
6
  "type": "object",
7
7
  "properties": {