renovate 43.45.0 → 43.45.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/platform/gitlab/index.js +4 -0
- package/dist/modules/platform/gitlab/index.js.map +1 -1
- package/dist/workers/repository/update/branch/auto-replace.js +22 -1
- package/dist/workers/repository/update/branch/auto-replace.js.map +1 -1
- package/dist/workers/repository/update/branch/index.js +7 -3
- package/dist/workers/repository/update/branch/index.js.map +1 -1
- package/package.json +1 -1
- package/renovate-schema.json +2 -2
|
@@ -503,6 +503,10 @@ async function setBranchStatus({ branchName, context, description, state: renova
|
|
|
503
503
|
logger.debug({ err });
|
|
504
504
|
logger.warn("Failed to retrieve commit pipeline");
|
|
505
505
|
}
|
|
506
|
+
if (options.pipeline_id === void 0 && env.RENOVATE_X_GITLAB_SKIP_STATUS_WITHOUT_PIPELINE === "true") {
|
|
507
|
+
logger.debug("Skipping branch status update because no pipeline was found");
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
506
510
|
try {
|
|
507
511
|
await gitlabApi.postJson(url, { body: options });
|
|
508
512
|
await getStatus(branchName, false);
|
|
@@ -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 .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 up-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 if (\n options.pipeline_id === undefined &&\n env.RENOVATE_X_GITLAB_SKIP_STATUS_WITHOUT_PIPELINE === 'true'\n ) {\n logger.debug('Skipping branch status update because no pipeline was found');\n return;\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 up-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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"}
|
|
@@ -127,10 +127,31 @@ async function checkExistingBranch(upgrade, existingContent) {
|
|
|
127
127
|
logger.debug(`Branch dep ${depName} in ${packageFile} is already updated`);
|
|
128
128
|
return existingContent;
|
|
129
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Check if an update from `current` to `newString` should be performed and return 1 if so.
|
|
132
|
+
*
|
|
133
|
+
* @remarks
|
|
134
|
+
* Useful for counting the number of updates to do.
|
|
135
|
+
*
|
|
136
|
+
* @param current The current value (if undefined then no update is required)
|
|
137
|
+
* @param newString The new value (if undefined then no update is required)
|
|
138
|
+
*
|
|
139
|
+
* @returns 1 if `current !== newString` and 0 if they are equal or at least one is undefined.
|
|
140
|
+
*/
|
|
141
|
+
function updatedToInt(current, newString) {
|
|
142
|
+
if (current && newString && newString !== current) return 1;
|
|
143
|
+
else return 0;
|
|
144
|
+
}
|
|
130
145
|
async function doAutoReplace(upgrade, existingContent, reuseExistingBranch, firstUpdate = true) {
|
|
131
146
|
const { packageFile, depName, depNameTemplate, newName, currentValue, currentValueTemplate, newValue, currentDigest, currentDigestShort, newDigest, autoReplaceGlobalMatch, autoReplaceStringTemplate } = upgrade;
|
|
132
147
|
if (reuseExistingBranch) return await checkExistingBranch(upgrade, existingContent);
|
|
133
|
-
const
|
|
148
|
+
const changedCount = updatedToInt(depName, newName) + updatedToInt(currentValue, newValue) + updatedToInt(currentDigest, newDigest);
|
|
149
|
+
if (changedCount > 1) logger.debug({
|
|
150
|
+
packageFile,
|
|
151
|
+
depName,
|
|
152
|
+
changedCount
|
|
153
|
+
}, "Multiple changed values, might need special handling (#36461)");
|
|
154
|
+
const replaceWithoutReplaceString = isString(newName) && newName !== depName && (isUndefined(upgrade.replaceString) || !upgrade.replaceString?.includes(depName)) || isUndefined(upgrade.replaceString) && changedCount > 1;
|
|
134
155
|
const replaceString = upgrade.replaceString ?? currentValue ?? currentDigest;
|
|
135
156
|
logger.trace({
|
|
136
157
|
depName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-replace.js","names":[],"sources":["../../../../../lib/workers/repository/update/branch/auto-replace.ts"],"sourcesContent":["// TODO #22198\nimport { isNumber, isString, isUndefined } from '@sindresorhus/is';\nimport { WORKER_FILE_UPDATE_FAILED } from '../../../../constants/error-messages.ts';\nimport { logger } from '../../../../logger/index.ts';\nimport { extractPackageFile } from '../../../../modules/manager/index.ts';\nimport type { PackageDependency } from '../../../../modules/manager/types.ts';\nimport { writeLocalFile } from '../../../../util/fs/index.ts';\nimport { escapeRegExp, regEx } from '../../../../util/regex.ts';\nimport { matchAt, replaceAt } from '../../../../util/string.ts';\nimport { compile } from '../../../../util/template/index.ts';\nimport type { BranchUpgradeConfig } from '../../../types.ts';\n\nexport async function confirmIfDepUpdated(\n upgrade: BranchUpgradeConfig,\n newContent: string,\n): Promise<boolean> {\n const { manager, packageFile, depIndex } = upgrade;\n let newUpgrade: PackageDependency;\n try {\n const newExtract = await extractPackageFile(\n manager,\n newContent,\n packageFile!,\n upgrade,\n );\n // istanbul ignore if\n if (!newExtract) {\n // TODO: fix types (#22198)\n logger.debug(\n `Could not extract ${packageFile!} (manager=${manager}) after autoreplace. Did the autoreplace make the file unparseable?`,\n );\n logger.trace(\n { packageFile, content: newContent },\n 'packageFile content after autoreplace',\n );\n return false;\n }\n // istanbul ignore if\n if (!newExtract.deps?.length) {\n logger.debug(\n `Extracted ${packageFile!} after autoreplace has no deps array. Did the autoreplace make the file unparseable?`,\n );\n return false;\n }\n // istanbul ignore if\n if (isNumber(depIndex) && depIndex >= newExtract.deps.length) {\n logger.debug(\n `Extracted ${packageFile!} after autoreplace has fewer deps than expected.`,\n );\n return false;\n }\n newUpgrade = newExtract.deps[depIndex!];\n } catch (err) {\n /* istanbul ignore next */\n logger.debug({ manager, packageFile, err }, 'Failed to parse newContent');\n }\n\n if (!newUpgrade!) {\n logger.debug(`No newUpgrade in ${packageFile!}`);\n return false;\n }\n\n if (\n upgrade.depName !== newUpgrade.depName &&\n upgrade.newName !== newUpgrade.depName\n ) {\n logger.debug(\n {\n manager,\n packageFile,\n currentDepName: upgrade.depName,\n newDepName: newUpgrade.depName,\n },\n 'depName mismatch',\n );\n return false;\n }\n\n if (upgrade.newName && upgrade.newName !== newUpgrade.depName) {\n logger.debug(\n {\n manager,\n packageFile,\n currentDepName: upgrade.depName,\n newDepName: newUpgrade.depName,\n },\n 'depName is not updated',\n );\n return false;\n }\n\n if (upgrade.newValue && upgrade.newValue !== newUpgrade.currentValue) {\n logger.debug(\n {\n depName: upgrade.depName,\n manager,\n packageFile,\n expectedValue: upgrade.newValue,\n foundValue: newUpgrade.currentValue,\n },\n 'Value is not updated',\n );\n return false;\n }\n\n if (\n upgrade.newDigest &&\n (upgrade.isPinDigest === true || upgrade.currentDigest) &&\n upgrade.newDigest !== newUpgrade.currentDigest\n ) {\n logger.debug(\n {\n depName: upgrade.depName,\n manager,\n packageFile,\n expectedValue: upgrade.newDigest,\n foundValue: newUpgrade.currentDigest,\n },\n 'Digest is not updated',\n );\n return false;\n }\n\n return true;\n}\n\nfunction getDepsSignature(deps: PackageDependency[]): string {\n // TODO: types (#22198)\n return deps\n .map(\n (dep) =>\n `${(dep.depName ?? dep.packageName)!}${(dep.packageName ??\n dep.depName)!}`,\n )\n .join(',');\n}\n\nfunction firstIndexOf(\n existingContent: string,\n depName: string,\n currentValue: string,\n position = 0,\n): number {\n const depIndex = existingContent.indexOf(depName, position);\n const valIndex = existingContent.indexOf(currentValue, position);\n const index = depIndex < valIndex ? depIndex : valIndex;\n if (index < 0) {\n return position === 0 ? -1 : existingContent.length;\n }\n return index;\n}\n\nexport async function checkBranchDepsMatchBaseDeps(\n upgrade: BranchUpgradeConfig,\n branchContent: string,\n): Promise<boolean> {\n const { baseDeps, manager, packageFile } = upgrade;\n try {\n const res = await extractPackageFile(\n manager,\n branchContent,\n packageFile!,\n upgrade,\n )!;\n const branchDeps = res!.deps;\n return getDepsSignature(baseDeps!) === getDepsSignature(branchDeps);\n } catch /* istanbul ignore next */ {\n logger.info(\n { manager, packageFile },\n 'Failed to parse branchContent - rebasing',\n );\n return false;\n }\n}\n\nasync function checkExistingBranch(\n upgrade: BranchUpgradeConfig,\n existingContent: string,\n): Promise<string | null> {\n const { packageFile, depName } = upgrade;\n if (!(await checkBranchDepsMatchBaseDeps(upgrade, existingContent))) {\n logger.debug(\n { packageFile, depName },\n 'Rebasing branch after deps list has changed',\n );\n return null;\n }\n if (!(await confirmIfDepUpdated(upgrade, existingContent))) {\n logger.debug(\n { packageFile, depName },\n 'Rebasing after outdated branch dep found',\n );\n return null;\n }\n // TODO: fix types (#22198)\n logger.debug(`Branch dep ${depName!} in ${packageFile!} is already updated`);\n return existingContent;\n}\n\nexport async function doAutoReplace(\n upgrade: BranchUpgradeConfig,\n existingContent: string,\n reuseExistingBranch: boolean,\n firstUpdate = true,\n): Promise<string | null> {\n const {\n packageFile,\n depName,\n depNameTemplate,\n newName,\n currentValue,\n currentValueTemplate,\n newValue,\n currentDigest,\n currentDigestShort,\n newDigest,\n autoReplaceGlobalMatch,\n autoReplaceStringTemplate,\n } = upgrade;\n /*\n If replacement support for more managers is added,\n please also update the list in docs/usage/configuration-options.md\n at replacementName and replacementVersion\n */\n if (reuseExistingBranch) {\n return await checkExistingBranch(upgrade, existingContent);\n }\n const replaceWithoutReplaceString =\n isString(newName) &&\n newName !== depName &&\n (isUndefined(upgrade.replaceString) ||\n !upgrade.replaceString?.includes(depName!));\n const replaceString = upgrade.replaceString ?? currentValue ?? currentDigest;\n logger.trace({ depName, replaceString }, 'autoReplace replaceString');\n let searchIndex: number;\n if (replaceWithoutReplaceString) {\n searchIndex = firstIndexOf(existingContent, depName!, currentValue!);\n } else {\n searchIndex = existingContent.indexOf(replaceString!);\n }\n if (searchIndex === -1) {\n logger.info(\n { packageFile, depName, existingContent, replaceString },\n 'Cannot find replaceString in current file content. Was it already updated?',\n );\n return existingContent;\n }\n try {\n let newString: string;\n if (autoReplaceStringTemplate && !newName) {\n newString = compile(autoReplaceStringTemplate, upgrade, false);\n } else {\n newString = replaceString!;\n\n const autoReplaceRegExpFlag = autoReplaceGlobalMatch ? 'g' : '';\n if (currentValue && newValue && currentValue !== newValue) {\n if (!newString.includes(currentValue)) {\n logger.debug(\n { stringToReplace: newString, currentValue, currentValueTemplate },\n 'currentValue not found in string to replace',\n );\n }\n newString = newString.replace(\n regEx(escapeRegExp(currentValue), autoReplaceRegExpFlag),\n newValue,\n );\n }\n if (depName && newName && depName !== newName) {\n if (!newString.includes(depName)) {\n logger.debug(\n { stringToReplace: newString, depName, depNameTemplate },\n 'depName not found in string to replace',\n );\n }\n newString = newString.replace(\n regEx(escapeRegExp(depName), autoReplaceRegExpFlag),\n newName,\n );\n }\n if (currentDigest && newDigest && currentDigest !== newDigest) {\n if (!newString.includes(currentDigest)) {\n logger.debug(\n { stringToReplace: newString, currentDigest },\n 'currentDigest not found in string to replace',\n );\n }\n newString = newString.replace(\n regEx(escapeRegExp(currentDigest), autoReplaceRegExpFlag),\n newDigest,\n );\n } else if (\n currentDigestShort &&\n newDigest &&\n currentDigestShort !== newDigest &&\n // Only use short digest replacement when there's no full currentDigest\n // that already matches newDigest (otherwise we'd incorrectly replace\n // part of an already-correct digest)\n !(currentDigest && currentDigest === newDigest)\n ) {\n if (!newString.includes(currentDigestShort)) {\n logger.debug(\n { stringToReplace: newString, currentDigestShort },\n 'currentDigestShort not found in string to replace',\n );\n }\n newString = newString.replace(\n regEx(escapeRegExp(currentDigestShort), autoReplaceRegExpFlag),\n newDigest,\n );\n }\n }\n if (!firstUpdate && (await confirmIfDepUpdated(upgrade, existingContent))) {\n logger.debug(\n { packageFile, depName },\n 'Package file is already updated - no work to do',\n );\n return existingContent;\n }\n logger.debug(\n { packageFile, depName },\n `Starting search at index ${searchIndex}`,\n );\n let newContent = existingContent;\n let nameReplaced = !newName;\n let valueReplaced = !newValue;\n let digestReplaced = !newDigest;\n let startIndex = searchIndex;\n // Iterate through the rest of the file\n for (; searchIndex < newContent.length; searchIndex += 1) {\n // First check if we have a hit for the old version\n if (replaceWithoutReplaceString) {\n // look for depName and currentValue\n if (newName && matchAt(newContent, searchIndex, depName!)) {\n logger.debug(\n { packageFile, depName },\n `Found depName at index ${searchIndex}`,\n );\n if (nameReplaced) {\n startIndex = firstIndexOf(\n existingContent,\n depName!,\n currentValue!,\n startIndex + 1,\n );\n searchIndex = startIndex - 1;\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n nameReplaced = !newName;\n valueReplaced = !newValue;\n digestReplaced = !newDigest;\n continue;\n }\n // replace with newName\n newContent = replaceAt(newContent, searchIndex, depName!, newName);\n await writeLocalFile(upgrade.packageFile!, newContent);\n nameReplaced = true;\n searchIndex += newName.length - 1;\n } else if (\n newValue &&\n matchAt(newContent, searchIndex, currentValue!)\n ) {\n logger.debug(\n { packageFile, currentValue },\n `Found currentValue at index ${searchIndex}`,\n );\n if (valueReplaced) {\n startIndex = firstIndexOf(\n existingContent,\n depName!,\n currentValue!,\n startIndex + 1,\n );\n searchIndex = startIndex - 1;\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n nameReplaced = !newName;\n valueReplaced = !newValue;\n digestReplaced = !newDigest;\n continue;\n }\n // Now test if the result matches\n newContent = replaceAt(\n newContent,\n searchIndex,\n currentValue!,\n newValue,\n );\n await writeLocalFile(upgrade.packageFile!, newContent);\n valueReplaced = true;\n searchIndex += newValue.length - 1;\n } else if (\n newDigest &&\n matchAt(newContent, searchIndex, currentDigest!)\n ) {\n logger.debug(\n { packageFile, currentDigest },\n `Found currentDigest at index ${searchIndex}`,\n );\n if (digestReplaced) {\n startIndex = firstIndexOf(\n existingContent,\n depName!,\n currentValue!,\n startIndex + 1,\n );\n searchIndex = startIndex - 1;\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n nameReplaced = !newName;\n valueReplaced = !newValue;\n digestReplaced = !newDigest;\n continue;\n }\n // Now test if the result matches\n newContent = replaceAt(\n newContent,\n searchIndex,\n currentDigest!,\n newDigest,\n );\n await writeLocalFile(upgrade.packageFile!, newContent);\n digestReplaced = true;\n searchIndex += newDigest.length - 1;\n }\n if (nameReplaced && valueReplaced && digestReplaced) {\n if (await confirmIfDepUpdated(upgrade, newContent)) {\n return newContent;\n }\n startIndex = firstIndexOf(\n existingContent,\n depName!,\n currentValue!,\n startIndex + 1,\n );\n searchIndex = startIndex - 1;\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n nameReplaced = !newName;\n valueReplaced = !newValue;\n digestReplaced = !newDigest;\n }\n } else if (matchAt(newContent, searchIndex, replaceString!)) {\n logger.debug(\n { packageFile, depName },\n `Found match at index ${searchIndex}`,\n );\n // Now test if the result matches\n newContent = replaceAt(\n newContent,\n searchIndex,\n replaceString!,\n newString,\n );\n await writeLocalFile(upgrade.packageFile!, newContent);\n if (await confirmIfDepUpdated(upgrade, newContent)) {\n return newContent;\n }\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n }\n }\n } catch (err) {\n /* istanbul ignore next */\n logger.debug({ packageFile, depName, err }, 'doAutoReplace error');\n }\n // istanbul ignore next\n throw new Error(WORKER_FILE_UPDATE_FAILED);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"auto-replace.js","names":[],"sources":["../../../../../lib/workers/repository/update/branch/auto-replace.ts"],"sourcesContent":["// TODO #22198\nimport { isNumber, isString, isUndefined } from '@sindresorhus/is';\nimport { WORKER_FILE_UPDATE_FAILED } from '../../../../constants/error-messages.ts';\nimport { logger } from '../../../../logger/index.ts';\nimport { extractPackageFile } from '../../../../modules/manager/index.ts';\nimport type { PackageDependency } from '../../../../modules/manager/types.ts';\nimport { writeLocalFile } from '../../../../util/fs/index.ts';\nimport { escapeRegExp, regEx } from '../../../../util/regex.ts';\nimport { matchAt, replaceAt } from '../../../../util/string.ts';\nimport { compile } from '../../../../util/template/index.ts';\nimport type { BranchUpgradeConfig } from '../../../types.ts';\n\nexport async function confirmIfDepUpdated(\n upgrade: BranchUpgradeConfig,\n newContent: string,\n): Promise<boolean> {\n const { manager, packageFile, depIndex } = upgrade;\n let newUpgrade: PackageDependency;\n try {\n const newExtract = await extractPackageFile(\n manager,\n newContent,\n packageFile!,\n upgrade,\n );\n // istanbul ignore if\n if (!newExtract) {\n // TODO: fix types (#22198)\n logger.debug(\n `Could not extract ${packageFile!} (manager=${manager}) after autoreplace. Did the autoreplace make the file unparseable?`,\n );\n logger.trace(\n { packageFile, content: newContent },\n 'packageFile content after autoreplace',\n );\n return false;\n }\n // istanbul ignore if\n if (!newExtract.deps?.length) {\n logger.debug(\n `Extracted ${packageFile!} after autoreplace has no deps array. Did the autoreplace make the file unparseable?`,\n );\n return false;\n }\n // istanbul ignore if\n if (isNumber(depIndex) && depIndex >= newExtract.deps.length) {\n logger.debug(\n `Extracted ${packageFile!} after autoreplace has fewer deps than expected.`,\n );\n return false;\n }\n newUpgrade = newExtract.deps[depIndex!];\n } catch (err) {\n /* istanbul ignore next */\n logger.debug({ manager, packageFile, err }, 'Failed to parse newContent');\n }\n\n if (!newUpgrade!) {\n logger.debug(`No newUpgrade in ${packageFile!}`);\n return false;\n }\n\n if (\n upgrade.depName !== newUpgrade.depName &&\n upgrade.newName !== newUpgrade.depName\n ) {\n logger.debug(\n {\n manager,\n packageFile,\n currentDepName: upgrade.depName,\n newDepName: newUpgrade.depName,\n },\n 'depName mismatch',\n );\n return false;\n }\n\n if (upgrade.newName && upgrade.newName !== newUpgrade.depName) {\n logger.debug(\n {\n manager,\n packageFile,\n currentDepName: upgrade.depName,\n newDepName: newUpgrade.depName,\n },\n 'depName is not updated',\n );\n return false;\n }\n\n if (upgrade.newValue && upgrade.newValue !== newUpgrade.currentValue) {\n logger.debug(\n {\n depName: upgrade.depName,\n manager,\n packageFile,\n expectedValue: upgrade.newValue,\n foundValue: newUpgrade.currentValue,\n },\n 'Value is not updated',\n );\n return false;\n }\n\n if (\n upgrade.newDigest &&\n (upgrade.isPinDigest === true || upgrade.currentDigest) &&\n upgrade.newDigest !== newUpgrade.currentDigest\n ) {\n logger.debug(\n {\n depName: upgrade.depName,\n manager,\n packageFile,\n expectedValue: upgrade.newDigest,\n foundValue: newUpgrade.currentDigest,\n },\n 'Digest is not updated',\n );\n return false;\n }\n\n return true;\n}\n\nfunction getDepsSignature(deps: PackageDependency[]): string {\n // TODO: types (#22198)\n return deps\n .map(\n (dep) =>\n `${(dep.depName ?? dep.packageName)!}${(dep.packageName ??\n dep.depName)!}`,\n )\n .join(',');\n}\n\nfunction firstIndexOf(\n existingContent: string,\n depName: string,\n currentValue: string,\n position = 0,\n): number {\n const depIndex = existingContent.indexOf(depName, position);\n const valIndex = existingContent.indexOf(currentValue, position);\n const index = depIndex < valIndex ? depIndex : valIndex;\n if (index < 0) {\n return position === 0 ? -1 : existingContent.length;\n }\n return index;\n}\n\nexport async function checkBranchDepsMatchBaseDeps(\n upgrade: BranchUpgradeConfig,\n branchContent: string,\n): Promise<boolean> {\n const { baseDeps, manager, packageFile } = upgrade;\n try {\n const res = await extractPackageFile(\n manager,\n branchContent,\n packageFile!,\n upgrade,\n )!;\n const branchDeps = res!.deps;\n return getDepsSignature(baseDeps!) === getDepsSignature(branchDeps);\n } catch /* istanbul ignore next */ {\n logger.info(\n { manager, packageFile },\n 'Failed to parse branchContent - rebasing',\n );\n return false;\n }\n}\n\nasync function checkExistingBranch(\n upgrade: BranchUpgradeConfig,\n existingContent: string,\n): Promise<string | null> {\n const { packageFile, depName } = upgrade;\n if (!(await checkBranchDepsMatchBaseDeps(upgrade, existingContent))) {\n logger.debug(\n { packageFile, depName },\n 'Rebasing branch after deps list has changed',\n );\n return null;\n }\n if (!(await confirmIfDepUpdated(upgrade, existingContent))) {\n logger.debug(\n { packageFile, depName },\n 'Rebasing after outdated branch dep found',\n );\n return null;\n }\n // TODO: fix types (#22198)\n logger.debug(`Branch dep ${depName!} in ${packageFile!} is already updated`);\n return existingContent;\n}\n\n/**\n * Check if an update from `current` to `newString` should be performed and return 1 if so.\n *\n * @remarks\n * Useful for counting the number of updates to do.\n *\n * @param current The current value (if undefined then no update is required)\n * @param newString The new value (if undefined then no update is required)\n *\n * @returns 1 if `current !== newString` and 0 if they are equal or at least one is undefined.\n */\nfunction updatedToInt(\n current: string | undefined,\n newString: string | undefined,\n): number {\n if (current && newString && newString !== current) {\n return 1;\n } else {\n return 0;\n }\n}\n\nexport async function doAutoReplace(\n upgrade: BranchUpgradeConfig,\n existingContent: string,\n reuseExistingBranch: boolean,\n firstUpdate = true,\n): Promise<string | null> {\n const {\n packageFile,\n depName,\n depNameTemplate,\n newName,\n currentValue,\n currentValueTemplate,\n newValue,\n currentDigest,\n currentDigestShort,\n newDigest,\n autoReplaceGlobalMatch,\n autoReplaceStringTemplate,\n } = upgrade;\n /*\n If replacement support for more managers is added,\n please also update the list in docs/usage/configuration-options.md\n at replacementName and replacementVersion\n */\n if (reuseExistingBranch) {\n return await checkExistingBranch(upgrade, existingContent);\n }\n\n // count how many strings need to be updated\n const changedCount =\n updatedToInt(depName, newName) +\n updatedToInt(currentValue, newValue) +\n updatedToInt(currentDigest, newDigest);\n if (changedCount > 1) {\n logger.debug(\n { packageFile, depName, changedCount },\n 'Multiple changed values, might need special handling (#36461)',\n );\n }\n\n const replaceWithoutReplaceString =\n (isString(newName) &&\n newName !== depName &&\n (isUndefined(upgrade.replaceString) ||\n !upgrade.replaceString?.includes(depName!))) ||\n // for jsonata manager, fixes #36461\n (isUndefined(upgrade.replaceString) && changedCount > 1);\n const replaceString = upgrade.replaceString ?? currentValue ?? currentDigest;\n logger.trace({ depName, replaceString }, 'autoReplace replaceString');\n let searchIndex: number;\n if (replaceWithoutReplaceString) {\n searchIndex = firstIndexOf(existingContent, depName!, currentValue!);\n } else {\n searchIndex = existingContent.indexOf(replaceString!);\n }\n if (searchIndex === -1) {\n logger.info(\n { packageFile, depName, existingContent, replaceString },\n 'Cannot find replaceString in current file content. Was it already updated?',\n );\n return existingContent;\n }\n try {\n let newString: string;\n if (autoReplaceStringTemplate && !newName) {\n newString = compile(autoReplaceStringTemplate, upgrade, false);\n } else {\n newString = replaceString!;\n\n const autoReplaceRegExpFlag = autoReplaceGlobalMatch ? 'g' : '';\n if (currentValue && newValue && currentValue !== newValue) {\n if (!newString.includes(currentValue)) {\n logger.debug(\n { stringToReplace: newString, currentValue, currentValueTemplate },\n 'currentValue not found in string to replace',\n );\n }\n newString = newString.replace(\n regEx(escapeRegExp(currentValue), autoReplaceRegExpFlag),\n newValue,\n );\n }\n if (depName && newName && depName !== newName) {\n if (!newString.includes(depName)) {\n logger.debug(\n { stringToReplace: newString, depName, depNameTemplate },\n 'depName not found in string to replace',\n );\n }\n newString = newString.replace(\n regEx(escapeRegExp(depName), autoReplaceRegExpFlag),\n newName,\n );\n }\n if (currentDigest && newDigest && currentDigest !== newDigest) {\n if (!newString.includes(currentDigest)) {\n logger.debug(\n { stringToReplace: newString, currentDigest },\n 'currentDigest not found in string to replace',\n );\n }\n newString = newString.replace(\n regEx(escapeRegExp(currentDigest), autoReplaceRegExpFlag),\n newDigest,\n );\n } else if (\n currentDigestShort &&\n newDigest &&\n currentDigestShort !== newDigest &&\n // Only use short digest replacement when there's no full currentDigest\n // that already matches newDigest (otherwise we'd incorrectly replace\n // part of an already-correct digest)\n !(currentDigest && currentDigest === newDigest)\n ) {\n if (!newString.includes(currentDigestShort)) {\n logger.debug(\n { stringToReplace: newString, currentDigestShort },\n 'currentDigestShort not found in string to replace',\n );\n }\n newString = newString.replace(\n regEx(escapeRegExp(currentDigestShort), autoReplaceRegExpFlag),\n newDigest,\n );\n }\n }\n if (!firstUpdate && (await confirmIfDepUpdated(upgrade, existingContent))) {\n logger.debug(\n { packageFile, depName },\n 'Package file is already updated - no work to do',\n );\n return existingContent;\n }\n logger.debug(\n { packageFile, depName },\n `Starting search at index ${searchIndex}`,\n );\n let newContent = existingContent;\n let nameReplaced = !newName;\n let valueReplaced = !newValue;\n let digestReplaced = !newDigest;\n let startIndex = searchIndex;\n // Iterate through the rest of the file\n for (; searchIndex < newContent.length; searchIndex += 1) {\n // First check if we have a hit for the old version\n if (replaceWithoutReplaceString) {\n // look for depName and currentValue\n if (newName && matchAt(newContent, searchIndex, depName!)) {\n logger.debug(\n { packageFile, depName },\n `Found depName at index ${searchIndex}`,\n );\n if (nameReplaced) {\n startIndex = firstIndexOf(\n existingContent,\n depName!,\n currentValue!,\n startIndex + 1,\n );\n searchIndex = startIndex - 1;\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n nameReplaced = !newName;\n valueReplaced = !newValue;\n digestReplaced = !newDigest;\n continue;\n }\n // replace with newName\n newContent = replaceAt(newContent, searchIndex, depName!, newName);\n await writeLocalFile(upgrade.packageFile!, newContent);\n nameReplaced = true;\n searchIndex += newName.length - 1;\n } else if (\n newValue &&\n matchAt(newContent, searchIndex, currentValue!)\n ) {\n logger.debug(\n { packageFile, currentValue },\n `Found currentValue at index ${searchIndex}`,\n );\n if (valueReplaced) {\n startIndex = firstIndexOf(\n existingContent,\n depName!,\n currentValue!,\n startIndex + 1,\n );\n searchIndex = startIndex - 1;\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n nameReplaced = !newName;\n valueReplaced = !newValue;\n digestReplaced = !newDigest;\n continue;\n }\n // Now test if the result matches\n newContent = replaceAt(\n newContent,\n searchIndex,\n currentValue!,\n newValue,\n );\n await writeLocalFile(upgrade.packageFile!, newContent);\n valueReplaced = true;\n searchIndex += newValue.length - 1;\n } else if (\n newDigest &&\n matchAt(newContent, searchIndex, currentDigest!)\n ) {\n logger.debug(\n { packageFile, currentDigest },\n `Found currentDigest at index ${searchIndex}`,\n );\n if (digestReplaced) {\n startIndex = firstIndexOf(\n existingContent,\n depName!,\n currentValue!,\n startIndex + 1,\n );\n searchIndex = startIndex - 1;\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n nameReplaced = !newName;\n valueReplaced = !newValue;\n digestReplaced = !newDigest;\n continue;\n }\n // Now test if the result matches\n newContent = replaceAt(\n newContent,\n searchIndex,\n currentDigest!,\n newDigest,\n );\n await writeLocalFile(upgrade.packageFile!, newContent);\n digestReplaced = true;\n searchIndex += newDigest.length - 1;\n }\n if (nameReplaced && valueReplaced && digestReplaced) {\n if (await confirmIfDepUpdated(upgrade, newContent)) {\n return newContent;\n }\n startIndex = firstIndexOf(\n existingContent,\n depName!,\n currentValue!,\n startIndex + 1,\n );\n searchIndex = startIndex - 1;\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n nameReplaced = !newName;\n valueReplaced = !newValue;\n digestReplaced = !newDigest;\n }\n } else if (matchAt(newContent, searchIndex, replaceString!)) {\n logger.debug(\n { packageFile, depName },\n `Found match at index ${searchIndex}`,\n );\n // Now test if the result matches\n newContent = replaceAt(\n newContent,\n searchIndex,\n replaceString!,\n newString,\n );\n await writeLocalFile(upgrade.packageFile!, newContent);\n if (await confirmIfDepUpdated(upgrade, newContent)) {\n return newContent;\n }\n await writeLocalFile(upgrade.packageFile!, existingContent);\n newContent = existingContent;\n }\n }\n } catch (err) {\n /* istanbul ignore next */\n logger.debug({ packageFile, depName, err }, 'doAutoReplace error');\n }\n // istanbul ignore next\n throw new Error(WORKER_FILE_UPDATE_FAILED);\n}\n"],"mappings":"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"}
|
|
@@ -31,6 +31,11 @@ import { isNonEmptyString } from "@sindresorhus/is";
|
|
|
31
31
|
import { DateTime } from "luxon";
|
|
32
32
|
|
|
33
33
|
//#region lib/workers/repository/update/branch/index.ts
|
|
34
|
+
async function setBranchStatusChecks(config) {
|
|
35
|
+
await setArtifactErrorStatus(config);
|
|
36
|
+
await setStability(config);
|
|
37
|
+
await setConfidence(config);
|
|
38
|
+
}
|
|
34
39
|
async function rebaseCheck(config, branchPr) {
|
|
35
40
|
if (branchPr.title?.startsWith("rebase!")) {
|
|
36
41
|
logger.debug(`Manual rebase requested via PR title for #${branchPr.number}`);
|
|
@@ -446,9 +451,7 @@ async function processBranch(branchConfig, forceRebase = false) {
|
|
|
446
451
|
const action = branchExists ? "updated" : "created";
|
|
447
452
|
logger.info({ commitSha }, `Branch ${action}`);
|
|
448
453
|
}
|
|
449
|
-
await
|
|
450
|
-
await setStability(config);
|
|
451
|
-
await setConfidence(config);
|
|
454
|
+
await setBranchStatusChecks(config);
|
|
452
455
|
if (!branchPr && !config.artifactErrors?.length && !userRebaseRequested && commitSha && config.prCreation !== "immediate") {
|
|
453
456
|
logger.debug(`Branch status pending, current sha: ${commitSha}`);
|
|
454
457
|
return {
|
|
@@ -619,6 +622,7 @@ async function processBranch(branchConfig, forceRebase = false) {
|
|
|
619
622
|
if (ensurePrResult.type === "with-pr") {
|
|
620
623
|
const { pr } = ensurePrResult;
|
|
621
624
|
branchPr = pr;
|
|
625
|
+
await setBranchStatusChecks(config);
|
|
622
626
|
if (config.artifactErrors?.length) {
|
|
623
627
|
logger.warn({ artifactErrors: config.artifactErrors }, "artifactErrors");
|
|
624
628
|
let content = `Renovate failed to update `;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["template.compile"],"sources":["../../../../../lib/workers/repository/update/branch/index.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { DateTime } from 'luxon';\nimport { GlobalConfig } from '../../../../config/global.ts';\nimport {\n type MinimumReleaseAgeBehaviour,\n type RenovateConfig,\n type UpdateType,\n} from '../../../../config/types.ts';\nimport {\n CONFIG_VALIDATION,\n MANAGER_LOCKFILE_ERROR,\n PLATFORM_AUTHENTICATION_ERROR,\n PLATFORM_BAD_CREDENTIALS,\n PLATFORM_INTEGRATION_UNAUTHORIZED,\n PLATFORM_RATE_LIMIT_EXCEEDED,\n REPOSITORY_CHANGED,\n SYSTEM_INSUFFICIENT_DISK_SPACE,\n TEMPORARY_ERROR,\n WORKER_FILE_UPDATE_FAILED,\n} from '../../../../constants/error-messages.ts';\nimport { logger, removeMeta } from '../../../../logger/index.ts';\nimport { getAdditionalFiles } from '../../../../modules/manager/npm/post-update/index.ts';\nimport {\n ensureComment,\n ensureCommentRemoval,\n} from '../../../../modules/platform/comment.ts';\nimport type { Pr } from '../../../../modules/platform/index.ts';\nimport { platform } from '../../../../modules/platform/index.ts';\nimport { scm } from '../../../../modules/platform/scm.ts';\nimport { ExternalHostError } from '../../../../types/errors/external-host-error.ts';\nimport { getElapsedMs } from '../../../../util/date.ts';\nimport { emojify } from '../../../../util/emoji.ts';\nimport {\n getMergeConfidenceLevel,\n isActiveConfidenceLevel,\n satisfiesConfidenceLevel,\n} from '../../../../util/merge-confidence/index.ts';\nimport { coerceNumber } from '../../../../util/number.ts';\nimport { toMs } from '../../../../util/pretty-time.ts';\nimport * as template from '../../../../util/template/index.ts';\nimport { getCount, isLimitReached } from '../../../global/limits.ts';\nimport type {\n BranchConfig,\n BranchResult,\n PrBlockedBy,\n} from '../../../types.ts';\nimport { embedChangelogs } from '../../changelog/index.ts';\nimport { checkAutoMerge } from '../pr/automerge.ts';\nimport { ensurePr, getPlatformPrOptions } from '../pr/index.ts';\nimport { setArtifactErrorStatus } from './artifacts.ts';\nimport { tryBranchAutomerge } from './automerge.ts';\nimport { bumpVersions } from './bump-versions.ts';\nimport { prAlreadyExisted } from './check-existing.ts';\nimport { commitFilesToBranch } from './commit.ts';\nimport executePostUpgradeCommands from './execute-post-upgrade-commands.ts';\nimport { getUpdatedPackageFiles } from './get-updated.ts';\nimport { handleClosedPr, handleModifiedPr } from './handle-existing.ts';\nimport { shouldReuseExistingBranch } from './reuse.ts';\nimport { isScheduledNow } from './schedule.ts';\nimport { setConfidence, setStability } from './status-checks.ts';\n\nasync function rebaseCheck(\n config: RenovateConfig,\n branchPr: Pr,\n): Promise<boolean> {\n const titleRebase = branchPr.title?.startsWith('rebase!');\n if (titleRebase) {\n logger.debug(\n `Manual rebase requested via PR title for #${branchPr.number}`,\n );\n return true;\n }\n const labelRebase = !!branchPr.labels?.includes(config.rebaseLabel!);\n if (labelRebase) {\n logger.debug(\n `Manual rebase requested via PR labels for #${branchPr.number}`,\n );\n /* v8 ignore next -- needs test */\n if (GlobalConfig.get('dryRun')) {\n logger.info(\n `DRY-RUN: Would delete label ${config.rebaseLabel!} from #${\n branchPr.number\n }`,\n );\n } else {\n await platform.deleteLabel(branchPr.number, config.rebaseLabel!);\n }\n return true;\n }\n const prRebaseChecked = !!branchPr.bodyStruct?.rebaseRequested;\n if (prRebaseChecked) {\n logger.debug(\n `Manual rebase requested via PR checkbox for #${branchPr.number}`,\n );\n return true;\n }\n\n return false;\n}\n\nasync function deleteBranchSilently(branchName: string): Promise<void> {\n try {\n await scm.deleteBranch(branchName);\n } catch (err) {\n /* v8 ignore next -- needs test */\n logger.debug({ branchName, err }, 'Branch auto-remove failed');\n }\n}\n\nfunction userChangedTargetBranch(pr: Pr): boolean {\n const oldTargetBranch = pr.bodyStruct?.debugData?.targetBranch;\n if (oldTargetBranch && pr.targetBranch) {\n return pr.targetBranch !== oldTargetBranch;\n }\n return false;\n}\n\nexport interface ProcessBranchResult {\n branchExists: boolean;\n updatesVerified?: boolean;\n prBlockedBy?: PrBlockedBy;\n prNo?: number;\n result: BranchResult;\n commitSha?: string | null;\n}\n\nexport async function processBranch(\n branchConfig: BranchConfig,\n forceRebase = false,\n): Promise<ProcessBranchResult> {\n let commitSha: string | null = null;\n let config: BranchConfig = { ...branchConfig };\n logger.trace({ config }, 'processBranch()');\n let branchExists = await scm.branchExists(config.branchName);\n const dependencyDashboardCheck =\n config.dependencyDashboardChecks?.[config.branchName];\n let updatesVerified = false;\n if (!branchExists && config.branchPrefix !== config.branchPrefixOld) {\n const branchName = config.branchName.replace(\n config.branchPrefix!,\n config.branchPrefixOld!,\n );\n branchExists = await scm.branchExists(branchName);\n if (branchExists) {\n config.branchName = branchName;\n logger.debug('Found existing branch with branchPrefixOld');\n }\n }\n\n if (\n !branchExists &&\n branchConfig.minimumGroupSize &&\n branchConfig.minimumGroupSize > branchConfig.upgrades.length &&\n !dependencyDashboardCheck\n ) {\n logger.debug(\n `Skipping branch creation as minimumGroupSize: ${branchConfig.minimumGroupSize} is not met`,\n );\n return {\n branchExists: false,\n result: 'minimum-group-size-not-met',\n };\n }\n\n let branchPr = await platform.getBranchPr(\n config.branchName,\n config.baseBranch,\n );\n logger.debug(`branchExists=${branchExists}`);\n logger.debug(`dependencyDashboardCheck=${dependencyDashboardCheck!}`);\n if (branchPr) {\n config.rebaseRequested = await rebaseCheck(config, branchPr);\n logger.debug(`PR rebase requested=${config.rebaseRequested}`);\n }\n const keepUpdatedLabel = config.keepUpdatedLabel;\n const artifactErrorTopic = emojify(':warning: Artifact update problem');\n const artifactNoticeTopic = emojify(\n ':information_source: Artifact update notice',\n );\n try {\n // Check if branch already existed\n const existingPr =\n !branchPr || config.automerge\n ? await prAlreadyExisted(config)\n : undefined;\n if (existingPr?.state === 'merged') {\n logger.debug(`Matching PR #${existingPr.number} was merged previously`);\n if (config.automerge) {\n logger.debug('Disabling automerge because PR was merged previously');\n config.automerge = false;\n config.automergedPreviously = true;\n }\n } else if (!branchPr && existingPr && !dependencyDashboardCheck) {\n logger.debug(\n { prTitle: config.prTitle },\n `Closed PR #${existingPr.number} already exists. Skipping branch.`,\n );\n await handleClosedPr(config, existingPr);\n return {\n branchExists: false,\n prNo: existingPr.number,\n result: 'already-existed',\n };\n }\n if (\n !branchExists &&\n branchConfig.pendingChecks &&\n !dependencyDashboardCheck\n ) {\n logger.debug(\n `Branch ${config.branchName} creation is disabled because internalChecksFilter was not met`,\n );\n return {\n branchExists: false,\n result: 'pending',\n };\n }\n if (!branchExists) {\n if (config.mode === 'silent' && !dependencyDashboardCheck) {\n logger.debug(\n `Branch ${config.branchName} creation is disabled because mode=silent`,\n );\n return {\n branchExists,\n result: 'needs-approval',\n };\n }\n if (config.dependencyDashboardApproval && !dependencyDashboardCheck) {\n logger.debug(\n `Branch ${config.branchName} creation is disabled because dependencyDashboardApproval=true`,\n );\n return {\n branchExists,\n result: 'needs-approval',\n };\n }\n }\n\n logger.debug(\n `Open PR Count: ${getCount('ConcurrentPRs')}, Existing Branch Count: ${getCount('Branches')}, Hourly PR Count: ${getCount('HourlyPRs')}, Hourly Commit Count: ${getCount('HourlyCommits')}`,\n );\n\n if (\n !branchExists &&\n isLimitReached('Branches', branchConfig) &&\n !dependencyDashboardCheck &&\n !config.isVulnerabilityAlert\n ) {\n logger.debug('Reached branch limit - skipping branch creation');\n return {\n branchExists,\n result: 'branch-limit-reached',\n };\n }\n if (\n !branchConfig.rebaseRequested &&\n isLimitReached('Commits') &&\n !dependencyDashboardCheck &&\n !config.isVulnerabilityAlert\n ) {\n logger.debug('Reached commits per run limit - skipping branch');\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'commit-per-run-limit-reached',\n };\n }\n if (\n !branchConfig.rebaseRequested &&\n isLimitReached('HourlyCommits', branchConfig) &&\n !dependencyDashboardCheck &&\n !config.isVulnerabilityAlert\n ) {\n logger.debug('Reached hourly commits limit - skipping branch');\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'commit-hourly-limit-reached',\n };\n }\n if (branchExists) {\n // check if branch is labelled to stop\n config.stopUpdating = branchPr?.labels?.includes(\n config.stopUpdatingLabel!,\n );\n\n const prRebaseChecked = !!branchPr?.bodyStruct?.rebaseRequested;\n\n if (branchExists && !dependencyDashboardCheck && !prRebaseChecked) {\n if (config.stopUpdating) {\n logger.info(\n 'Branch updating is skipped because stopUpdatingLabel is present in config',\n );\n return {\n branchExists: true,\n prNo: branchPr?.number,\n result: 'no-work',\n };\n }\n\n if (config.pendingChecks) {\n logger.info(\n 'Branch updating is skipped because internalChecksFilter was not met',\n );\n return {\n branchExists: true,\n prNo: branchPr?.number,\n result: 'pending',\n };\n }\n }\n\n logger.debug('Checking if PR has been edited');\n const branchIsModified = await scm.isBranchModified(\n config.branchName,\n config.baseBranch,\n );\n if (branchPr) {\n logger.debug(`Found existing branch PR #${branchPr.number}`);\n if (branchPr.state !== 'open') {\n logger.debug(\n 'PR has been closed or merged since this run started - aborting',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n if (branchIsModified || userChangedTargetBranch(branchPr)) {\n logger.debug(`PR has been edited, PrNo:${branchPr.number}`);\n await handleModifiedPr(config, branchPr);\n if (!(!!dependencyDashboardCheck || config.rebaseRequested)) {\n return {\n branchExists,\n prNo: branchPr.number,\n result: 'pr-edited',\n };\n }\n }\n } else if (branchIsModified) {\n const oldPr = await platform.findPr({\n branchName: config.branchName,\n state: '!open',\n targetBranch: config.baseBranch,\n });\n if (!oldPr) {\n logger.debug('Branch has been edited but found no PR - skipping');\n return {\n branchExists,\n result: 'pr-edited',\n };\n }\n const branchSha = await scm.getBranchCommit(config.branchName);\n const oldPrSha = oldPr?.sha;\n if (!oldPrSha || oldPrSha === branchSha) {\n logger.debug(\n { oldPrNumber: oldPr.number, oldPrSha, branchSha },\n 'Found old PR matching this branch - will override it',\n );\n } else {\n logger.debug(\n { oldPrNumber: oldPr.number, oldPrSha, branchSha },\n 'Found old PR but the SHA is different',\n );\n return {\n branchExists,\n result: 'pr-edited',\n };\n }\n }\n }\n\n // Check schedule\n config.isScheduledNow = isScheduledNow(config, 'schedule');\n if (!config.isScheduledNow && !dependencyDashboardCheck) {\n if (!branchExists) {\n logger.debug('Skipping branch creation as not within schedule');\n return {\n branchExists,\n result: 'not-scheduled',\n };\n }\n if (config.updateNotScheduled === false && !config.rebaseRequested) {\n logger.debug('Skipping branch update as not within schedule');\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'update-not-scheduled',\n };\n }\n if (\n !branchPr &&\n !(config.automerge && config.automergeType === 'branch') // if branch is configured for automerge there's no need for a PR\n ) {\n logger.debug('Skipping PR creation out of schedule');\n return {\n branchExists,\n result: 'not-scheduled',\n };\n }\n logger.debug(\n 'Branch + PR exists but is not scheduled -- will update if necessary',\n );\n }\n //stability checks\n if (\n config.upgrades.some(\n (upgrade) =>\n isNonEmptyString(upgrade.minimumReleaseAge) ||\n isActiveConfidenceLevel(upgrade.minimumConfidence!),\n )\n ) {\n const depNamesWithoutReleaseTimestamp: Record<\n MinimumReleaseAgeBehaviour,\n {\n depName: string;\n updateType: UpdateType;\n }[]\n > = {\n 'timestamp-required': [],\n 'timestamp-optional': [],\n };\n\n // Only set a stability status check if one or more of the updates contain\n // both a minimumReleaseAge setting and a releaseTimestamp\n config.stabilityStatus = 'green';\n // Default to 'success' but set 'pending' if any update is pending\n for (const upgrade of config.upgrades) {\n const minimumReleaseAgeMs = isNonEmptyString(upgrade.minimumReleaseAge)\n ? coerceNumber(toMs(upgrade.minimumReleaseAge), 0)\n : 0;\n\n if (minimumReleaseAgeMs) {\n const minimumReleaseAgeBehaviour: MinimumReleaseAgeBehaviour =\n upgrade.minimumReleaseAgeBehaviour ?? 'timestamp-required';\n\n // regardless of the value of `minimumReleaseAgeBehaviour`, if there is a timestamp, we will process it according to `minimumReleaseAge`\n if (upgrade.releaseTimestamp) {\n const timeElapsed = getElapsedMs(upgrade.releaseTimestamp);\n if (timeElapsed < minimumReleaseAgeMs) {\n logger.debug(\n {\n depName: upgrade.depName,\n timeElapsed,\n minimumReleaseAge: upgrade.minimumReleaseAge,\n },\n 'Update has not passed minimum release age',\n );\n config.stabilityStatus = 'yellow';\n continue;\n }\n } else {\n // if we're set to `minimumReleaseAgeBehaviour=timestamp-required`, and there isn't a timestamp, always mark the update as pending\n if (minimumReleaseAgeBehaviour === 'timestamp-required') {\n depNamesWithoutReleaseTimestamp['timestamp-required'].push({\n depName: upgrade.depName!,\n updateType: upgrade.updateType!,\n });\n config.stabilityStatus = 'yellow';\n continue;\n } else {\n // if there is no timestamp, and we're running in `optional` mode, we can allow it, but make sure to warn the user\n depNamesWithoutReleaseTimestamp['timestamp-optional'].push({\n depName: upgrade.depName!,\n updateType: upgrade.updateType!,\n });\n }\n }\n }\n const datasource = upgrade.datasource!;\n const depName = upgrade.depName!;\n const packageName = upgrade.packageName!;\n const minimumConfidence = upgrade.minimumConfidence!;\n const updateType = upgrade.updateType!;\n const currentVersion = upgrade.currentVersion!;\n const newVersion = upgrade.newVersion!;\n if (isActiveConfidenceLevel(minimumConfidence)) {\n const confidence =\n (await getMergeConfidenceLevel(\n datasource,\n packageName,\n currentVersion,\n newVersion,\n updateType,\n )) ?? 'neutral';\n if (satisfiesConfidenceLevel(confidence, minimumConfidence)) {\n config.confidenceStatus = 'green';\n } else {\n logger.debug(\n { depName, confidence, minimumConfidence },\n 'Update does not meet minimum confidence scores',\n );\n config.confidenceStatus = 'yellow';\n continue;\n }\n }\n }\n\n if (depNamesWithoutReleaseTimestamp['timestamp-required'].length) {\n logger.once.debug(\n { updates: depNamesWithoutReleaseTimestamp['timestamp-required'] },\n `Marking ${depNamesWithoutReleaseTimestamp['timestamp-required'].length} release(s) as pending, as they do not have a releaseTimestamp and we're running with minimumReleaseAgeBehaviour=timestamp-required`,\n );\n }\n if (depNamesWithoutReleaseTimestamp['timestamp-optional'].length) {\n logger.once.warn(\n \"Some upgrade(s) did not have a releaseTimestamp, but as we're running with minimumReleaseAgeBehaviour=timestamp-optional, proceeding. See debug logs for more information\",\n );\n logger.once.debug(\n { updates: depNamesWithoutReleaseTimestamp['timestamp-optional'] },\n `${depNamesWithoutReleaseTimestamp['timestamp-optional'].length} upgrade(s) did not have a releaseTimestamp, but as we're running with minimumReleaseAgeBehaviour=timestamp-optional, proceeding`,\n );\n }\n\n // Don't create a branch if we know it will be status 'pending'\n if (\n !dependencyDashboardCheck &&\n !branchExists &&\n config.stabilityStatus === 'yellow' &&\n ['not-pending', 'status-success'].includes(config.prCreation!)\n ) {\n logger.debug(\n 'Skipping branch creation due to internal status checks not met',\n );\n return {\n branchExists,\n result: 'pending',\n };\n }\n }\n\n let userRebaseRequested =\n dependencyDashboardCheck === 'rebase' ||\n !!config.dependencyDashboardRebaseAllOpen ||\n !!config.rebaseRequested;\n const userApproveAllPendingPR = !!config.dependencyDashboardAllPending;\n const userOpenAllRateLimtedPR = !!config.dependencyDashboardAllRateLimited;\n const userOpenAllSchedulePendingPR =\n !!config.dependencyDashboardAllAwaitingSchedule;\n\n if (forceRebase) {\n logger.debug('Force rebase because branch needs updating');\n config.reuseExistingBranch = false;\n } else if (userRebaseRequested) {\n logger.debug('User has requested rebase');\n config.reuseExistingBranch = false;\n } else if (dependencyDashboardCheck === 'global-config') {\n logger.debug(`Manual create/rebase requested via checkedBranches`);\n config.reuseExistingBranch = false;\n userRebaseRequested = true;\n } else if (userApproveAllPendingPR) {\n logger.debug(\n 'A user manually approved all pending PRs via the Dependency Dashboard.',\n );\n } else if (userOpenAllRateLimtedPR) {\n logger.debug(\n 'A user manually approved all rate-limited PRs via the Dependency Dashboard.',\n );\n } else if (userOpenAllSchedulePendingPR) {\n logger.debug(\n 'A user manually requested all awaiting schedule PRs via the Dependency Dashboard.',\n );\n } else if (\n branchExists &&\n config.rebaseWhen === 'never' &&\n !(keepUpdatedLabel && branchPr?.labels?.includes(keepUpdatedLabel)) &&\n !dependencyDashboardCheck\n ) {\n logger.debug('rebaseWhen=never so skipping branch update check');\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'no-work',\n };\n }\n // if the base branch has been changed by user in renovate config, rebase onto the new baseBranch\n // we have already confirmed earlier that branch isn't modified, so its safe to use targetBranch here\n else if (\n branchPr?.targetBranch &&\n branchPr.targetBranch !== config.baseBranch\n ) {\n logger.debug(\n 'Base branch changed by user, rebasing the branch onto new base',\n );\n config.reuseExistingBranch = false;\n } else if (config.cacheFingerprintMatch === 'no-match') {\n logger.debug(\n 'Cache fingerprint does not match, cannot reuse existing branch',\n );\n config.reuseExistingBranch = false;\n } else {\n config = await shouldReuseExistingBranch(config);\n }\n // TODO: types (#22198)\n logger.debug(`Using reuseExistingBranch: ${config.reuseExistingBranch!}`);\n if (\n !(\n config.reuseExistingBranch && config.cacheFingerprintMatch === 'matched'\n )\n ) {\n await scm.checkoutBranch(config.baseBranch);\n const res = await getUpdatedPackageFiles(config);\n if (res.artifactErrors && config.artifactErrors) {\n res.artifactErrors = config.artifactErrors.concat(res.artifactErrors);\n }\n config = { ...config, ...res };\n if (config.updatedPackageFiles?.length) {\n logger.debug(\n `Updated ${config.updatedPackageFiles.length} package files`,\n );\n if (config.reuseExistingBranch && !forceRebase) {\n logger.debug(\n 'Existing branch needs updating. Restarting processBranch() with a clean branch',\n );\n return processBranch(branchConfig, true);\n }\n } else {\n logger.debug('No package files need updating');\n }\n const additionalFiles = await getAdditionalFiles(\n config,\n branchConfig.packageFiles!,\n );\n config.artifactErrors = (config.artifactErrors ?? []).concat(\n additionalFiles.artifactErrors,\n );\n config.updatedArtifacts = (config.updatedArtifacts ?? []).concat(\n additionalFiles.updatedArtifacts,\n );\n if (config.updatedArtifacts?.length) {\n logger.debug(\n {\n updatedArtifacts: config.updatedArtifacts.map((f) =>\n f.type === 'deletion' ? `${f.path} (delete)` : f.path,\n ),\n },\n `Updated ${config.updatedArtifacts.length} lock files`,\n );\n if (config.reuseExistingBranch && !forceRebase) {\n logger.debug(\n 'Existing branch needs updating. Restarting processBranch() with a clean branch',\n );\n return processBranch(branchConfig, true);\n }\n } else {\n logger.debug('No updated lock files in branch');\n }\n if (config.fetchChangeLogs === 'branch') {\n await embedChangelogs(config.upgrades);\n }\n\n const postUpgradeCommandResults =\n await executePostUpgradeCommands(config);\n\n if (postUpgradeCommandResults !== null) {\n const { updatedArtifacts, artifactErrors } = postUpgradeCommandResults;\n config.updatedArtifacts = updatedArtifacts;\n config.artifactErrors = artifactErrors;\n }\n\n // modifies the file changes in place to allow having a version bump in a packageFile or artifact\n await bumpVersions(config);\n\n removeMeta(['dep']);\n\n if (config.artifactErrors?.length) {\n if (config.releaseTimestamp) {\n logger.debug(`Branch timestamp: ` + config.releaseTimestamp);\n const releaseTimestamp = DateTime.fromISO(config.releaseTimestamp);\n if (releaseTimestamp.plus({ hours: 2 }) < DateTime.local()) {\n logger.debug(\n 'PR is older than 2 hours, raise PR with lock file errors',\n );\n } else if (branchExists) {\n logger.debug(\n 'PR is less than 2 hours old but branchExists so updating anyway',\n );\n } else {\n logger.debug(\n 'PR is less than 2 hours old - raise error instead of PR',\n );\n throw new Error(MANAGER_LOCKFILE_ERROR);\n }\n } else {\n logger.debug('PR has no releaseTimestamp');\n }\n } else if (config.updatedArtifacts?.length && branchPr) {\n // If there are artifacts, no errors, and an existing PR then ensure any artifacts error comment is removed\n if (GlobalConfig.get('dryRun')) {\n logger.info(\n `DRY-RUN: Would ensure comment removal in PR #${branchPr.number}`,\n );\n } else {\n // Remove artifacts error comment only if this run has successfully updated artifacts\n await ensureCommentRemoval({\n type: 'by-topic',\n number: branchPr.number,\n topic: artifactErrorTopic,\n });\n\n if (!config.artifactNotices?.length) {\n await ensureCommentRemoval({\n type: 'by-topic',\n number: branchPr.number,\n topic: artifactNoticeTopic,\n });\n }\n }\n }\n const forcedManually = userRebaseRequested || !branchExists;\n\n config.isConflicted ??=\n branchExists &&\n (await scm.isBranchConflicted(config.baseBranch, config.branchName));\n config.forceCommit = forcedManually || config.isConflicted;\n\n // compile commit message with body, which maybe needs changelogs\n if (config.commitBody) {\n // changelog is on first upgrade\n config.commitMessage = `${config.commitMessage!}\\n\\n${template.compile(\n config.commitBody,\n {\n ...config,\n logJSON: config.upgrades[0].logJSON,\n releases: config.upgrades[0].releases,\n },\n )}`;\n\n logger.trace(`commitMessage: ` + JSON.stringify(config.commitMessage));\n }\n\n commitSha = await commitFilesToBranch(config);\n // Checkout to base branch to ensure that the next branch processing always starts with git being on the baseBranch\n // baseBranch is not checked out at the start of processBranch() due to pull/16246\n await scm.checkoutBranch(config.baseBranch);\n updatesVerified = true;\n }\n\n if (branchPr) {\n const platformPrOptions = getPlatformPrOptions(config);\n if (\n commitSha &&\n platformPrOptions.usePlatformAutomerge &&\n platform.reattemptPlatformAutomerge\n ) {\n if (GlobalConfig.get('dryRun')) {\n logger.info(\n `DRY-RUN: Would reattempt platform automerge for PR #${branchPr.number}`,\n );\n } else {\n await platform.reattemptPlatformAutomerge({\n number: branchPr.number,\n platformPrOptions,\n });\n }\n }\n if (platform.refreshPr) {\n await platform.refreshPr(branchPr.number);\n }\n }\n if (!commitSha && !branchExists) {\n return {\n branchExists,\n result: 'no-work',\n };\n }\n if (commitSha) {\n const action = branchExists ? 'updated' : 'created';\n logger.info({ commitSha }, `Branch ${action}`);\n }\n // Set branch statuses\n await setArtifactErrorStatus(config);\n await setStability(config);\n await setConfidence(config);\n\n // new commit means status check are pretty sure pending but maybe not reported yet\n // if PR has not been created + new commit + prCreation !== immediate skip\n // but do not break when there are artifact errors\n if (\n !branchPr &&\n !config.artifactErrors?.length &&\n !userRebaseRequested &&\n commitSha &&\n config.prCreation !== 'immediate'\n ) {\n logger.debug(`Branch status pending, current sha: ${commitSha}`);\n return {\n branchExists: true,\n updatesVerified,\n result: 'pending',\n commitSha,\n };\n }\n\n // Try to automerge branch and finish if successful, but only if branch already existed before this run\n // skip if we have a non-immediate pr and there is an existing PR,\n // we want to update the PR and skip the Auto merge since status checks aren't done yet\n if (!config.artifactErrors?.length && (!commitSha || config.ignoreTests)) {\n const mergeStatus = await tryBranchAutomerge(config);\n logger.debug(`mergeStatus=${mergeStatus}`);\n if (mergeStatus === 'automerged') {\n if (GlobalConfig.get('dryRun')) {\n logger.info('DRY-RUN: Would delete branch' + config.branchName);\n } else {\n await deleteBranchSilently(config.branchName);\n }\n logger.debug('Branch is automerged - returning');\n return { branchExists: false, result: 'automerged' };\n }\n if (mergeStatus === 'off schedule') {\n if (userRebaseRequested) {\n config.forcePr = true;\n } else {\n logger.debug(\n 'Branch cannot automerge now because automergeSchedule is off schedule - skipping',\n );\n return {\n branchExists,\n result: 'not-scheduled',\n commitSha,\n };\n }\n }\n if (\n mergeStatus === 'stale' &&\n ['conflicted', 'never'].includes(config.rebaseWhen!) &&\n /* v8 ignore next -- needs test */\n !(keepUpdatedLabel && branchPr?.labels?.includes(keepUpdatedLabel))\n ) {\n logger.warn(\n 'Branch cannot automerge because it is behind base branch and rebaseWhen setting disallows rebasing - raising a PR instead',\n );\n config.forcePr = true;\n config.branchAutomergeFailureMessage = mergeStatus;\n }\n if (\n mergeStatus === 'automerge aborted - PR exists' ||\n mergeStatus === 'branch status error' ||\n mergeStatus === 'failed'\n ) {\n logger.debug(\n `Branch automerge not possible, mergeStatus:${mergeStatus}`,\n );\n config.forcePr = true;\n config.branchAutomergeFailureMessage = mergeStatus;\n }\n }\n } catch (err) {\n /* v8 ignore if -- needs test */\n if (err.statusCode === 404) {\n logger.debug({ err }, 'Received a 404 error - aborting run');\n throw new Error(REPOSITORY_CHANGED);\n }\n /* v8 ignore if -- needs test */\n if (err.message === PLATFORM_RATE_LIMIT_EXCEEDED) {\n logger.debug('Passing rate-limit-exceeded error up');\n throw err;\n }\n if (err.message === REPOSITORY_CHANGED) {\n logger.debug('Passing repository-changed error up');\n throw err;\n }\n /* v8 ignore if -- needs test */\n if (err.message?.startsWith('remote: Invalid username or password')) {\n logger.debug('Throwing bad credentials');\n throw new Error(PLATFORM_BAD_CREDENTIALS);\n }\n /* v8 ignore if -- needs test */\n if (\n err.message?.startsWith(\n 'ssh_exchange_identification: Connection closed by remote host',\n )\n ) {\n logger.debug('Throwing bad credentials');\n throw new Error(PLATFORM_BAD_CREDENTIALS);\n }\n /* v8 ignore if -- needs test */\n if (err.message === PLATFORM_BAD_CREDENTIALS) {\n logger.debug('Passing bad-credentials error up');\n throw err;\n }\n /* v8 ignore if -- needs test */\n if (err.message === PLATFORM_INTEGRATION_UNAUTHORIZED) {\n logger.debug('Passing integration-unauthorized error up');\n throw err;\n }\n if (err.message === MANAGER_LOCKFILE_ERROR) {\n logger.debug('Passing lockfile-error up');\n throw err;\n }\n /* v8 ignore if -- needs test */\n if (err.message?.includes('space left on device')) {\n throw new Error(SYSTEM_INSUFFICIENT_DISK_SPACE);\n }\n /* v8 ignore if -- needs test */\n if (err.message === SYSTEM_INSUFFICIENT_DISK_SPACE) {\n logger.debug('Passing disk-space error up');\n throw err;\n }\n /* v8 ignore if -- needs test */\n if (err.message.startsWith('Resource not accessible by integration')) {\n logger.debug('Passing 403 error up');\n throw err;\n }\n /* v8 ignore next -- needs test */\n if (err.message === WORKER_FILE_UPDATE_FAILED) {\n logger.warn('Error updating branch: update failure');\n } else if (err.message.startsWith('bundler-')) {\n // we have already warned inside the bundler artifacts error handling, so just return\n return {\n branchExists: true,\n updatesVerified,\n prNo: branchPr?.number,\n result: 'error',\n commitSha,\n };\n } else if (err.message?.includes('fatal: Authentication failed')) {\n throw new Error(PLATFORM_AUTHENTICATION_ERROR);\n } else if (err.message?.includes('fatal: bad revision')) {\n logger.debug({ err }, 'Aborting job due to bad revision error');\n throw new Error(REPOSITORY_CHANGED);\n } else if (err.message === CONFIG_VALIDATION) {\n logger.debug('Passing config validation error up');\n throw err;\n } else if (err.message === TEMPORARY_ERROR) {\n logger.debug('Passing TEMPORARY_ERROR error up');\n throw err;\n } else if (!(err instanceof ExternalHostError)) {\n logger.warn({ err }, `Error updating branch`);\n }\n // Don't throw here - we don't want to stop the other renovations\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'error',\n commitSha,\n };\n }\n try {\n logger.debug('Ensuring PR');\n logger.debug(\n `There are ${config.errors!.length} errors and ${\n config.warnings!.length\n } warnings`,\n );\n const ensurePrResult = await ensurePr(config);\n if (ensurePrResult.type === 'without-pr') {\n const { prBlockedBy } = ensurePrResult;\n branchPr = null;\n if (prBlockedBy === 'RateLimited' && !config.isVulnerabilityAlert) {\n logger.debug('Reached PR limit - skipping PR creation');\n return {\n branchExists,\n prBlockedBy,\n result: 'pr-limit-reached',\n commitSha,\n };\n }\n // TODO: ensurePr should check for automerge itself (#9719)\n if (prBlockedBy === 'NeedsApproval') {\n return {\n branchExists,\n prBlockedBy,\n result: 'needs-pr-approval',\n commitSha,\n };\n }\n if (prBlockedBy === 'AwaitingTests') {\n return {\n branchExists,\n prBlockedBy,\n result: 'pending',\n commitSha,\n };\n }\n if (prBlockedBy === 'BranchAutomerge') {\n return {\n branchExists,\n prBlockedBy,\n result: 'done',\n commitSha,\n };\n }\n if (prBlockedBy === 'Error') {\n return {\n branchExists,\n prBlockedBy,\n result: 'error',\n commitSha,\n };\n }\n logger.warn({ prBlockedBy }, 'Unknown PrBlockedBy result');\n return {\n branchExists,\n prBlockedBy,\n result: 'error',\n commitSha,\n };\n }\n if (ensurePrResult.type === 'with-pr') {\n const { pr } = ensurePrResult;\n branchPr = pr;\n if (config.artifactErrors?.length) {\n logger.warn(\n { artifactErrors: config.artifactErrors },\n 'artifactErrors',\n );\n let content = `Renovate failed to update `;\n content +=\n config.artifactErrors.length > 1 ? 'artifacts' : 'an artifact';\n content += ' related to this branch. ';\n content += template.compile(\n config.userStrings!.artifactErrorWarning,\n config,\n );\n content += emojify(\n `\\n\\n:recycle: Renovate will retry this branch, including artifacts, only when one of the following happens:\\n\\n`,\n );\n content +=\n ' - any of the package files in this branch needs updating, or \\n';\n content += ' - the branch becomes conflicted, or\\n';\n content +=\n ' - you click the rebase/retry checkbox if found above, or\\n';\n content +=\n ' - you rename this PR\\'s title to start with \"rebase!\" to trigger it manually';\n content += '\\n\\nThe artifact failure details are included below:\\n\\n';\n // TODO: types (#22198)\n config.artifactErrors.forEach((error) => {\n content += `##### File name: ${error.lockFile!}\\n\\n`;\n content += `\\`\\`\\`\\n${error.stderr!}\\n\\`\\`\\`\\n\\n`;\n });\n content = platform.massageMarkdown(content, config.rebaseLabel);\n if (\n !(\n config.suppressNotifications!.includes('artifactErrors') ||\n config.suppressNotifications!.includes('lockFileErrors')\n )\n ) {\n if (GlobalConfig.get('dryRun')) {\n logger.info(\n `DRY-RUN: Would ensure lock file error comment in PR #${pr.number}`,\n );\n } else {\n await ensureComment({\n number: pr.number,\n topic: artifactErrorTopic,\n content,\n });\n }\n }\n } else {\n if (config.artifactNotices?.length) {\n const contentLines: string[] = [];\n for (const notice of config.artifactNotices) {\n contentLines.push(`##### File name: ${notice.file}`);\n contentLines.push(notice.message);\n }\n const content = contentLines.join('\\n\\n');\n await ensureComment({\n number: pr.number,\n topic: artifactNoticeTopic,\n content,\n });\n }\n\n if (config.automerge) {\n logger.debug('PR is configured for automerge');\n // skip automerge if there is a new commit since status checks aren't done yet\n if (config.ignoreTests === true || !commitSha) {\n logger.debug('checking auto-merge');\n const prAutomergeResult = await checkAutoMerge(pr, config);\n if (prAutomergeResult?.automerged) {\n return {\n branchExists,\n result: 'automerged',\n commitSha,\n };\n }\n }\n } else {\n logger.debug('PR is not configured for automerge');\n }\n }\n }\n } catch (err) {\n /* v8 ignore if -- needs test */\n if (\n err instanceof ExternalHostError ||\n [PLATFORM_RATE_LIMIT_EXCEEDED, REPOSITORY_CHANGED].includes(err.message)\n ) {\n logger.debug('Passing PR error up');\n throw err;\n }\n // Otherwise don't throw here - we don't want to stop the other renovations\n logger.error({ err }, `Error ensuring PR`);\n }\n if (!branchExists) {\n return {\n branchExists: true,\n updatesVerified,\n prNo: branchPr?.number,\n result: 'pr-created',\n commitSha,\n };\n }\n return {\n branchExists,\n updatesVerified,\n prNo: branchPr?.number,\n result: 'done',\n commitSha,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["template.compile"],"sources":["../../../../../lib/workers/repository/update/branch/index.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { DateTime } from 'luxon';\nimport { GlobalConfig } from '../../../../config/global.ts';\nimport {\n type MinimumReleaseAgeBehaviour,\n type RenovateConfig,\n type UpdateType,\n} from '../../../../config/types.ts';\nimport {\n CONFIG_VALIDATION,\n MANAGER_LOCKFILE_ERROR,\n PLATFORM_AUTHENTICATION_ERROR,\n PLATFORM_BAD_CREDENTIALS,\n PLATFORM_INTEGRATION_UNAUTHORIZED,\n PLATFORM_RATE_LIMIT_EXCEEDED,\n REPOSITORY_CHANGED,\n SYSTEM_INSUFFICIENT_DISK_SPACE,\n TEMPORARY_ERROR,\n WORKER_FILE_UPDATE_FAILED,\n} from '../../../../constants/error-messages.ts';\nimport { logger, removeMeta } from '../../../../logger/index.ts';\nimport { getAdditionalFiles } from '../../../../modules/manager/npm/post-update/index.ts';\nimport {\n ensureComment,\n ensureCommentRemoval,\n} from '../../../../modules/platform/comment.ts';\nimport type { Pr } from '../../../../modules/platform/index.ts';\nimport { platform } from '../../../../modules/platform/index.ts';\nimport { scm } from '../../../../modules/platform/scm.ts';\nimport { ExternalHostError } from '../../../../types/errors/external-host-error.ts';\nimport { getElapsedMs } from '../../../../util/date.ts';\nimport { emojify } from '../../../../util/emoji.ts';\nimport {\n getMergeConfidenceLevel,\n isActiveConfidenceLevel,\n satisfiesConfidenceLevel,\n} from '../../../../util/merge-confidence/index.ts';\nimport { coerceNumber } from '../../../../util/number.ts';\nimport { toMs } from '../../../../util/pretty-time.ts';\nimport * as template from '../../../../util/template/index.ts';\nimport { getCount, isLimitReached } from '../../../global/limits.ts';\nimport type {\n BranchConfig,\n BranchResult,\n PrBlockedBy,\n} from '../../../types.ts';\nimport { embedChangelogs } from '../../changelog/index.ts';\nimport { checkAutoMerge } from '../pr/automerge.ts';\nimport { ensurePr, getPlatformPrOptions } from '../pr/index.ts';\nimport { setArtifactErrorStatus } from './artifacts.ts';\nimport { tryBranchAutomerge } from './automerge.ts';\nimport { bumpVersions } from './bump-versions.ts';\nimport { prAlreadyExisted } from './check-existing.ts';\nimport { commitFilesToBranch } from './commit.ts';\nimport executePostUpgradeCommands from './execute-post-upgrade-commands.ts';\nimport { getUpdatedPackageFiles } from './get-updated.ts';\nimport { handleClosedPr, handleModifiedPr } from './handle-existing.ts';\nimport { shouldReuseExistingBranch } from './reuse.ts';\nimport { isScheduledNow } from './schedule.ts';\nimport { setConfidence, setStability } from './status-checks.ts';\n\nasync function setBranchStatusChecks(config: BranchConfig): Promise<void> {\n await setArtifactErrorStatus(config);\n await setStability(config);\n await setConfidence(config);\n}\n\nasync function rebaseCheck(\n config: RenovateConfig,\n branchPr: Pr,\n): Promise<boolean> {\n const titleRebase = branchPr.title?.startsWith('rebase!');\n if (titleRebase) {\n logger.debug(\n `Manual rebase requested via PR title for #${branchPr.number}`,\n );\n return true;\n }\n const labelRebase = !!branchPr.labels?.includes(config.rebaseLabel!);\n if (labelRebase) {\n logger.debug(\n `Manual rebase requested via PR labels for #${branchPr.number}`,\n );\n /* v8 ignore next -- needs test */\n if (GlobalConfig.get('dryRun')) {\n logger.info(\n `DRY-RUN: Would delete label ${config.rebaseLabel!} from #${\n branchPr.number\n }`,\n );\n } else {\n await platform.deleteLabel(branchPr.number, config.rebaseLabel!);\n }\n return true;\n }\n const prRebaseChecked = !!branchPr.bodyStruct?.rebaseRequested;\n if (prRebaseChecked) {\n logger.debug(\n `Manual rebase requested via PR checkbox for #${branchPr.number}`,\n );\n return true;\n }\n\n return false;\n}\n\nasync function deleteBranchSilently(branchName: string): Promise<void> {\n try {\n await scm.deleteBranch(branchName);\n } catch (err) {\n /* v8 ignore next -- needs test */\n logger.debug({ branchName, err }, 'Branch auto-remove failed');\n }\n}\n\nfunction userChangedTargetBranch(pr: Pr): boolean {\n const oldTargetBranch = pr.bodyStruct?.debugData?.targetBranch;\n if (oldTargetBranch && pr.targetBranch) {\n return pr.targetBranch !== oldTargetBranch;\n }\n return false;\n}\n\nexport interface ProcessBranchResult {\n branchExists: boolean;\n updatesVerified?: boolean;\n prBlockedBy?: PrBlockedBy;\n prNo?: number;\n result: BranchResult;\n commitSha?: string | null;\n}\n\nexport async function processBranch(\n branchConfig: BranchConfig,\n forceRebase = false,\n): Promise<ProcessBranchResult> {\n let commitSha: string | null = null;\n let config: BranchConfig = { ...branchConfig };\n logger.trace({ config }, 'processBranch()');\n let branchExists = await scm.branchExists(config.branchName);\n const dependencyDashboardCheck =\n config.dependencyDashboardChecks?.[config.branchName];\n let updatesVerified = false;\n if (!branchExists && config.branchPrefix !== config.branchPrefixOld) {\n const branchName = config.branchName.replace(\n config.branchPrefix!,\n config.branchPrefixOld!,\n );\n branchExists = await scm.branchExists(branchName);\n if (branchExists) {\n config.branchName = branchName;\n logger.debug('Found existing branch with branchPrefixOld');\n }\n }\n\n if (\n !branchExists &&\n branchConfig.minimumGroupSize &&\n branchConfig.minimumGroupSize > branchConfig.upgrades.length &&\n !dependencyDashboardCheck\n ) {\n logger.debug(\n `Skipping branch creation as minimumGroupSize: ${branchConfig.minimumGroupSize} is not met`,\n );\n return {\n branchExists: false,\n result: 'minimum-group-size-not-met',\n };\n }\n\n let branchPr = await platform.getBranchPr(\n config.branchName,\n config.baseBranch,\n );\n logger.debug(`branchExists=${branchExists}`);\n logger.debug(`dependencyDashboardCheck=${dependencyDashboardCheck!}`);\n if (branchPr) {\n config.rebaseRequested = await rebaseCheck(config, branchPr);\n logger.debug(`PR rebase requested=${config.rebaseRequested}`);\n }\n const keepUpdatedLabel = config.keepUpdatedLabel;\n const artifactErrorTopic = emojify(':warning: Artifact update problem');\n const artifactNoticeTopic = emojify(\n ':information_source: Artifact update notice',\n );\n try {\n // Check if branch already existed\n const existingPr =\n !branchPr || config.automerge\n ? await prAlreadyExisted(config)\n : undefined;\n if (existingPr?.state === 'merged') {\n logger.debug(`Matching PR #${existingPr.number} was merged previously`);\n if (config.automerge) {\n logger.debug('Disabling automerge because PR was merged previously');\n config.automerge = false;\n config.automergedPreviously = true;\n }\n } else if (!branchPr && existingPr && !dependencyDashboardCheck) {\n logger.debug(\n { prTitle: config.prTitle },\n `Closed PR #${existingPr.number} already exists. Skipping branch.`,\n );\n await handleClosedPr(config, existingPr);\n return {\n branchExists: false,\n prNo: existingPr.number,\n result: 'already-existed',\n };\n }\n if (\n !branchExists &&\n branchConfig.pendingChecks &&\n !dependencyDashboardCheck\n ) {\n logger.debug(\n `Branch ${config.branchName} creation is disabled because internalChecksFilter was not met`,\n );\n return {\n branchExists: false,\n result: 'pending',\n };\n }\n if (!branchExists) {\n if (config.mode === 'silent' && !dependencyDashboardCheck) {\n logger.debug(\n `Branch ${config.branchName} creation is disabled because mode=silent`,\n );\n return {\n branchExists,\n result: 'needs-approval',\n };\n }\n if (config.dependencyDashboardApproval && !dependencyDashboardCheck) {\n logger.debug(\n `Branch ${config.branchName} creation is disabled because dependencyDashboardApproval=true`,\n );\n return {\n branchExists,\n result: 'needs-approval',\n };\n }\n }\n\n logger.debug(\n `Open PR Count: ${getCount('ConcurrentPRs')}, Existing Branch Count: ${getCount('Branches')}, Hourly PR Count: ${getCount('HourlyPRs')}, Hourly Commit Count: ${getCount('HourlyCommits')}`,\n );\n\n if (\n !branchExists &&\n isLimitReached('Branches', branchConfig) &&\n !dependencyDashboardCheck &&\n !config.isVulnerabilityAlert\n ) {\n logger.debug('Reached branch limit - skipping branch creation');\n return {\n branchExists,\n result: 'branch-limit-reached',\n };\n }\n if (\n !branchConfig.rebaseRequested &&\n isLimitReached('Commits') &&\n !dependencyDashboardCheck &&\n !config.isVulnerabilityAlert\n ) {\n logger.debug('Reached commits per run limit - skipping branch');\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'commit-per-run-limit-reached',\n };\n }\n if (\n !branchConfig.rebaseRequested &&\n isLimitReached('HourlyCommits', branchConfig) &&\n !dependencyDashboardCheck &&\n !config.isVulnerabilityAlert\n ) {\n logger.debug('Reached hourly commits limit - skipping branch');\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'commit-hourly-limit-reached',\n };\n }\n if (branchExists) {\n // check if branch is labelled to stop\n config.stopUpdating = branchPr?.labels?.includes(\n config.stopUpdatingLabel!,\n );\n\n const prRebaseChecked = !!branchPr?.bodyStruct?.rebaseRequested;\n\n if (branchExists && !dependencyDashboardCheck && !prRebaseChecked) {\n if (config.stopUpdating) {\n logger.info(\n 'Branch updating is skipped because stopUpdatingLabel is present in config',\n );\n return {\n branchExists: true,\n prNo: branchPr?.number,\n result: 'no-work',\n };\n }\n\n if (config.pendingChecks) {\n logger.info(\n 'Branch updating is skipped because internalChecksFilter was not met',\n );\n return {\n branchExists: true,\n prNo: branchPr?.number,\n result: 'pending',\n };\n }\n }\n\n logger.debug('Checking if PR has been edited');\n const branchIsModified = await scm.isBranchModified(\n config.branchName,\n config.baseBranch,\n );\n if (branchPr) {\n logger.debug(`Found existing branch PR #${branchPr.number}`);\n if (branchPr.state !== 'open') {\n logger.debug(\n 'PR has been closed or merged since this run started - aborting',\n );\n throw new Error(REPOSITORY_CHANGED);\n }\n if (branchIsModified || userChangedTargetBranch(branchPr)) {\n logger.debug(`PR has been edited, PrNo:${branchPr.number}`);\n await handleModifiedPr(config, branchPr);\n if (!(!!dependencyDashboardCheck || config.rebaseRequested)) {\n return {\n branchExists,\n prNo: branchPr.number,\n result: 'pr-edited',\n };\n }\n }\n } else if (branchIsModified) {\n const oldPr = await platform.findPr({\n branchName: config.branchName,\n state: '!open',\n targetBranch: config.baseBranch,\n });\n if (!oldPr) {\n logger.debug('Branch has been edited but found no PR - skipping');\n return {\n branchExists,\n result: 'pr-edited',\n };\n }\n const branchSha = await scm.getBranchCommit(config.branchName);\n const oldPrSha = oldPr?.sha;\n if (!oldPrSha || oldPrSha === branchSha) {\n logger.debug(\n { oldPrNumber: oldPr.number, oldPrSha, branchSha },\n 'Found old PR matching this branch - will override it',\n );\n } else {\n logger.debug(\n { oldPrNumber: oldPr.number, oldPrSha, branchSha },\n 'Found old PR but the SHA is different',\n );\n return {\n branchExists,\n result: 'pr-edited',\n };\n }\n }\n }\n\n // Check schedule\n config.isScheduledNow = isScheduledNow(config, 'schedule');\n if (!config.isScheduledNow && !dependencyDashboardCheck) {\n if (!branchExists) {\n logger.debug('Skipping branch creation as not within schedule');\n return {\n branchExists,\n result: 'not-scheduled',\n };\n }\n if (config.updateNotScheduled === false && !config.rebaseRequested) {\n logger.debug('Skipping branch update as not within schedule');\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'update-not-scheduled',\n };\n }\n if (\n !branchPr &&\n !(config.automerge && config.automergeType === 'branch') // if branch is configured for automerge there's no need for a PR\n ) {\n logger.debug('Skipping PR creation out of schedule');\n return {\n branchExists,\n result: 'not-scheduled',\n };\n }\n logger.debug(\n 'Branch + PR exists but is not scheduled -- will update if necessary',\n );\n }\n //stability checks\n if (\n config.upgrades.some(\n (upgrade) =>\n isNonEmptyString(upgrade.minimumReleaseAge) ||\n isActiveConfidenceLevel(upgrade.minimumConfidence!),\n )\n ) {\n const depNamesWithoutReleaseTimestamp: Record<\n MinimumReleaseAgeBehaviour,\n {\n depName: string;\n updateType: UpdateType;\n }[]\n > = {\n 'timestamp-required': [],\n 'timestamp-optional': [],\n };\n\n // Only set a stability status check if one or more of the updates contain\n // both a minimumReleaseAge setting and a releaseTimestamp\n config.stabilityStatus = 'green';\n // Default to 'success' but set 'pending' if any update is pending\n for (const upgrade of config.upgrades) {\n const minimumReleaseAgeMs = isNonEmptyString(upgrade.minimumReleaseAge)\n ? coerceNumber(toMs(upgrade.minimumReleaseAge), 0)\n : 0;\n\n if (minimumReleaseAgeMs) {\n const minimumReleaseAgeBehaviour: MinimumReleaseAgeBehaviour =\n upgrade.minimumReleaseAgeBehaviour ?? 'timestamp-required';\n\n // regardless of the value of `minimumReleaseAgeBehaviour`, if there is a timestamp, we will process it according to `minimumReleaseAge`\n if (upgrade.releaseTimestamp) {\n const timeElapsed = getElapsedMs(upgrade.releaseTimestamp);\n if (timeElapsed < minimumReleaseAgeMs) {\n logger.debug(\n {\n depName: upgrade.depName,\n timeElapsed,\n minimumReleaseAge: upgrade.minimumReleaseAge,\n },\n 'Update has not passed minimum release age',\n );\n config.stabilityStatus = 'yellow';\n continue;\n }\n } else {\n // if we're set to `minimumReleaseAgeBehaviour=timestamp-required`, and there isn't a timestamp, always mark the update as pending\n if (minimumReleaseAgeBehaviour === 'timestamp-required') {\n depNamesWithoutReleaseTimestamp['timestamp-required'].push({\n depName: upgrade.depName!,\n updateType: upgrade.updateType!,\n });\n config.stabilityStatus = 'yellow';\n continue;\n } else {\n // if there is no timestamp, and we're running in `optional` mode, we can allow it, but make sure to warn the user\n depNamesWithoutReleaseTimestamp['timestamp-optional'].push({\n depName: upgrade.depName!,\n updateType: upgrade.updateType!,\n });\n }\n }\n }\n const datasource = upgrade.datasource!;\n const depName = upgrade.depName!;\n const packageName = upgrade.packageName!;\n const minimumConfidence = upgrade.minimumConfidence!;\n const updateType = upgrade.updateType!;\n const currentVersion = upgrade.currentVersion!;\n const newVersion = upgrade.newVersion!;\n if (isActiveConfidenceLevel(minimumConfidence)) {\n const confidence =\n (await getMergeConfidenceLevel(\n datasource,\n packageName,\n currentVersion,\n newVersion,\n updateType,\n )) ?? 'neutral';\n if (satisfiesConfidenceLevel(confidence, minimumConfidence)) {\n config.confidenceStatus = 'green';\n } else {\n logger.debug(\n { depName, confidence, minimumConfidence },\n 'Update does not meet minimum confidence scores',\n );\n config.confidenceStatus = 'yellow';\n continue;\n }\n }\n }\n\n if (depNamesWithoutReleaseTimestamp['timestamp-required'].length) {\n logger.once.debug(\n { updates: depNamesWithoutReleaseTimestamp['timestamp-required'] },\n `Marking ${depNamesWithoutReleaseTimestamp['timestamp-required'].length} release(s) as pending, as they do not have a releaseTimestamp and we're running with minimumReleaseAgeBehaviour=timestamp-required`,\n );\n }\n if (depNamesWithoutReleaseTimestamp['timestamp-optional'].length) {\n logger.once.warn(\n \"Some upgrade(s) did not have a releaseTimestamp, but as we're running with minimumReleaseAgeBehaviour=timestamp-optional, proceeding. See debug logs for more information\",\n );\n logger.once.debug(\n { updates: depNamesWithoutReleaseTimestamp['timestamp-optional'] },\n `${depNamesWithoutReleaseTimestamp['timestamp-optional'].length} upgrade(s) did not have a releaseTimestamp, but as we're running with minimumReleaseAgeBehaviour=timestamp-optional, proceeding`,\n );\n }\n\n // Don't create a branch if we know it will be status 'pending'\n if (\n !dependencyDashboardCheck &&\n !branchExists &&\n config.stabilityStatus === 'yellow' &&\n ['not-pending', 'status-success'].includes(config.prCreation!)\n ) {\n logger.debug(\n 'Skipping branch creation due to internal status checks not met',\n );\n return {\n branchExists,\n result: 'pending',\n };\n }\n }\n\n let userRebaseRequested =\n dependencyDashboardCheck === 'rebase' ||\n !!config.dependencyDashboardRebaseAllOpen ||\n !!config.rebaseRequested;\n const userApproveAllPendingPR = !!config.dependencyDashboardAllPending;\n const userOpenAllRateLimtedPR = !!config.dependencyDashboardAllRateLimited;\n const userOpenAllSchedulePendingPR =\n !!config.dependencyDashboardAllAwaitingSchedule;\n\n if (forceRebase) {\n logger.debug('Force rebase because branch needs updating');\n config.reuseExistingBranch = false;\n } else if (userRebaseRequested) {\n logger.debug('User has requested rebase');\n config.reuseExistingBranch = false;\n } else if (dependencyDashboardCheck === 'global-config') {\n logger.debug(`Manual create/rebase requested via checkedBranches`);\n config.reuseExistingBranch = false;\n userRebaseRequested = true;\n } else if (userApproveAllPendingPR) {\n logger.debug(\n 'A user manually approved all pending PRs via the Dependency Dashboard.',\n );\n } else if (userOpenAllRateLimtedPR) {\n logger.debug(\n 'A user manually approved all rate-limited PRs via the Dependency Dashboard.',\n );\n } else if (userOpenAllSchedulePendingPR) {\n logger.debug(\n 'A user manually requested all awaiting schedule PRs via the Dependency Dashboard.',\n );\n } else if (\n branchExists &&\n config.rebaseWhen === 'never' &&\n !(keepUpdatedLabel && branchPr?.labels?.includes(keepUpdatedLabel)) &&\n !dependencyDashboardCheck\n ) {\n logger.debug('rebaseWhen=never so skipping branch update check');\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'no-work',\n };\n }\n // if the base branch has been changed by user in renovate config, rebase onto the new baseBranch\n // we have already confirmed earlier that branch isn't modified, so its safe to use targetBranch here\n else if (\n branchPr?.targetBranch &&\n branchPr.targetBranch !== config.baseBranch\n ) {\n logger.debug(\n 'Base branch changed by user, rebasing the branch onto new base',\n );\n config.reuseExistingBranch = false;\n } else if (config.cacheFingerprintMatch === 'no-match') {\n logger.debug(\n 'Cache fingerprint does not match, cannot reuse existing branch',\n );\n config.reuseExistingBranch = false;\n } else {\n config = await shouldReuseExistingBranch(config);\n }\n // TODO: types (#22198)\n logger.debug(`Using reuseExistingBranch: ${config.reuseExistingBranch!}`);\n if (\n !(\n config.reuseExistingBranch && config.cacheFingerprintMatch === 'matched'\n )\n ) {\n await scm.checkoutBranch(config.baseBranch);\n const res = await getUpdatedPackageFiles(config);\n if (res.artifactErrors && config.artifactErrors) {\n res.artifactErrors = config.artifactErrors.concat(res.artifactErrors);\n }\n config = { ...config, ...res };\n if (config.updatedPackageFiles?.length) {\n logger.debug(\n `Updated ${config.updatedPackageFiles.length} package files`,\n );\n if (config.reuseExistingBranch && !forceRebase) {\n logger.debug(\n 'Existing branch needs updating. Restarting processBranch() with a clean branch',\n );\n return processBranch(branchConfig, true);\n }\n } else {\n logger.debug('No package files need updating');\n }\n const additionalFiles = await getAdditionalFiles(\n config,\n branchConfig.packageFiles!,\n );\n config.artifactErrors = (config.artifactErrors ?? []).concat(\n additionalFiles.artifactErrors,\n );\n config.updatedArtifacts = (config.updatedArtifacts ?? []).concat(\n additionalFiles.updatedArtifacts,\n );\n if (config.updatedArtifacts?.length) {\n logger.debug(\n {\n updatedArtifacts: config.updatedArtifacts.map((f) =>\n f.type === 'deletion' ? `${f.path} (delete)` : f.path,\n ),\n },\n `Updated ${config.updatedArtifacts.length} lock files`,\n );\n if (config.reuseExistingBranch && !forceRebase) {\n logger.debug(\n 'Existing branch needs updating. Restarting processBranch() with a clean branch',\n );\n return processBranch(branchConfig, true);\n }\n } else {\n logger.debug('No updated lock files in branch');\n }\n if (config.fetchChangeLogs === 'branch') {\n await embedChangelogs(config.upgrades);\n }\n\n const postUpgradeCommandResults =\n await executePostUpgradeCommands(config);\n\n if (postUpgradeCommandResults !== null) {\n const { updatedArtifacts, artifactErrors } = postUpgradeCommandResults;\n config.updatedArtifacts = updatedArtifacts;\n config.artifactErrors = artifactErrors;\n }\n\n // modifies the file changes in place to allow having a version bump in a packageFile or artifact\n await bumpVersions(config);\n\n removeMeta(['dep']);\n\n if (config.artifactErrors?.length) {\n if (config.releaseTimestamp) {\n logger.debug(`Branch timestamp: ` + config.releaseTimestamp);\n const releaseTimestamp = DateTime.fromISO(config.releaseTimestamp);\n if (releaseTimestamp.plus({ hours: 2 }) < DateTime.local()) {\n logger.debug(\n 'PR is older than 2 hours, raise PR with lock file errors',\n );\n } else if (branchExists) {\n logger.debug(\n 'PR is less than 2 hours old but branchExists so updating anyway',\n );\n } else {\n logger.debug(\n 'PR is less than 2 hours old - raise error instead of PR',\n );\n throw new Error(MANAGER_LOCKFILE_ERROR);\n }\n } else {\n logger.debug('PR has no releaseTimestamp');\n }\n } else if (config.updatedArtifacts?.length && branchPr) {\n // If there are artifacts, no errors, and an existing PR then ensure any artifacts error comment is removed\n if (GlobalConfig.get('dryRun')) {\n logger.info(\n `DRY-RUN: Would ensure comment removal in PR #${branchPr.number}`,\n );\n } else {\n // Remove artifacts error comment only if this run has successfully updated artifacts\n await ensureCommentRemoval({\n type: 'by-topic',\n number: branchPr.number,\n topic: artifactErrorTopic,\n });\n\n if (!config.artifactNotices?.length) {\n await ensureCommentRemoval({\n type: 'by-topic',\n number: branchPr.number,\n topic: artifactNoticeTopic,\n });\n }\n }\n }\n const forcedManually = userRebaseRequested || !branchExists;\n\n config.isConflicted ??=\n branchExists &&\n (await scm.isBranchConflicted(config.baseBranch, config.branchName));\n config.forceCommit = forcedManually || config.isConflicted;\n\n // compile commit message with body, which maybe needs changelogs\n if (config.commitBody) {\n // changelog is on first upgrade\n config.commitMessage = `${config.commitMessage!}\\n\\n${template.compile(\n config.commitBody,\n {\n ...config,\n logJSON: config.upgrades[0].logJSON,\n releases: config.upgrades[0].releases,\n },\n )}`;\n\n logger.trace(`commitMessage: ` + JSON.stringify(config.commitMessage));\n }\n\n commitSha = await commitFilesToBranch(config);\n // Checkout to base branch to ensure that the next branch processing always starts with git being on the baseBranch\n // baseBranch is not checked out at the start of processBranch() due to pull/16246\n await scm.checkoutBranch(config.baseBranch);\n updatesVerified = true;\n }\n\n if (branchPr) {\n const platformPrOptions = getPlatformPrOptions(config);\n if (\n commitSha &&\n platformPrOptions.usePlatformAutomerge &&\n platform.reattemptPlatformAutomerge\n ) {\n if (GlobalConfig.get('dryRun')) {\n logger.info(\n `DRY-RUN: Would reattempt platform automerge for PR #${branchPr.number}`,\n );\n } else {\n await platform.reattemptPlatformAutomerge({\n number: branchPr.number,\n platformPrOptions,\n });\n }\n }\n if (platform.refreshPr) {\n await platform.refreshPr(branchPr.number);\n }\n }\n if (!commitSha && !branchExists) {\n return {\n branchExists,\n result: 'no-work',\n };\n }\n if (commitSha) {\n const action = branchExists ? 'updated' : 'created';\n logger.info({ commitSha }, `Branch ${action}`);\n }\n await setBranchStatusChecks(config);\n // new commit means status check are pretty sure pending but maybe not reported yet\n // if PR has not been created + new commit + prCreation !== immediate skip\n // but do not break when there are artifact errors\n if (\n !branchPr &&\n !config.artifactErrors?.length &&\n !userRebaseRequested &&\n commitSha &&\n config.prCreation !== 'immediate'\n ) {\n logger.debug(`Branch status pending, current sha: ${commitSha}`);\n return {\n branchExists: true,\n updatesVerified,\n result: 'pending',\n commitSha,\n };\n }\n\n // Try to automerge branch and finish if successful, but only if branch already existed before this run\n // skip if we have a non-immediate pr and there is an existing PR,\n // we want to update the PR and skip the Auto merge since status checks aren't done yet\n if (!config.artifactErrors?.length && (!commitSha || config.ignoreTests)) {\n const mergeStatus = await tryBranchAutomerge(config);\n logger.debug(`mergeStatus=${mergeStatus}`);\n if (mergeStatus === 'automerged') {\n if (GlobalConfig.get('dryRun')) {\n logger.info('DRY-RUN: Would delete branch' + config.branchName);\n } else {\n await deleteBranchSilently(config.branchName);\n }\n logger.debug('Branch is automerged - returning');\n return { branchExists: false, result: 'automerged' };\n }\n if (mergeStatus === 'off schedule') {\n if (userRebaseRequested) {\n config.forcePr = true;\n } else {\n logger.debug(\n 'Branch cannot automerge now because automergeSchedule is off schedule - skipping',\n );\n return {\n branchExists,\n result: 'not-scheduled',\n commitSha,\n };\n }\n }\n if (\n mergeStatus === 'stale' &&\n ['conflicted', 'never'].includes(config.rebaseWhen!) &&\n /* v8 ignore next -- needs test */\n !(keepUpdatedLabel && branchPr?.labels?.includes(keepUpdatedLabel))\n ) {\n logger.warn(\n 'Branch cannot automerge because it is behind base branch and rebaseWhen setting disallows rebasing - raising a PR instead',\n );\n config.forcePr = true;\n config.branchAutomergeFailureMessage = mergeStatus;\n }\n if (\n mergeStatus === 'automerge aborted - PR exists' ||\n mergeStatus === 'branch status error' ||\n mergeStatus === 'failed'\n ) {\n logger.debug(\n `Branch automerge not possible, mergeStatus:${mergeStatus}`,\n );\n config.forcePr = true;\n config.branchAutomergeFailureMessage = mergeStatus;\n }\n }\n } catch (err) {\n /* v8 ignore if -- needs test */\n if (err.statusCode === 404) {\n logger.debug({ err }, 'Received a 404 error - aborting run');\n throw new Error(REPOSITORY_CHANGED);\n }\n /* v8 ignore if -- needs test */\n if (err.message === PLATFORM_RATE_LIMIT_EXCEEDED) {\n logger.debug('Passing rate-limit-exceeded error up');\n throw err;\n }\n if (err.message === REPOSITORY_CHANGED) {\n logger.debug('Passing repository-changed error up');\n throw err;\n }\n /* v8 ignore if -- needs test */\n if (err.message?.startsWith('remote: Invalid username or password')) {\n logger.debug('Throwing bad credentials');\n throw new Error(PLATFORM_BAD_CREDENTIALS);\n }\n /* v8 ignore if -- needs test */\n if (\n err.message?.startsWith(\n 'ssh_exchange_identification: Connection closed by remote host',\n )\n ) {\n logger.debug('Throwing bad credentials');\n throw new Error(PLATFORM_BAD_CREDENTIALS);\n }\n /* v8 ignore if -- needs test */\n if (err.message === PLATFORM_BAD_CREDENTIALS) {\n logger.debug('Passing bad-credentials error up');\n throw err;\n }\n /* v8 ignore if -- needs test */\n if (err.message === PLATFORM_INTEGRATION_UNAUTHORIZED) {\n logger.debug('Passing integration-unauthorized error up');\n throw err;\n }\n if (err.message === MANAGER_LOCKFILE_ERROR) {\n logger.debug('Passing lockfile-error up');\n throw err;\n }\n /* v8 ignore if -- needs test */\n if (err.message?.includes('space left on device')) {\n throw new Error(SYSTEM_INSUFFICIENT_DISK_SPACE);\n }\n /* v8 ignore if -- needs test */\n if (err.message === SYSTEM_INSUFFICIENT_DISK_SPACE) {\n logger.debug('Passing disk-space error up');\n throw err;\n }\n /* v8 ignore if -- needs test */\n if (err.message.startsWith('Resource not accessible by integration')) {\n logger.debug('Passing 403 error up');\n throw err;\n }\n /* v8 ignore next -- needs test */\n if (err.message === WORKER_FILE_UPDATE_FAILED) {\n logger.warn('Error updating branch: update failure');\n } else if (err.message.startsWith('bundler-')) {\n // we have already warned inside the bundler artifacts error handling, so just return\n return {\n branchExists: true,\n updatesVerified,\n prNo: branchPr?.number,\n result: 'error',\n commitSha,\n };\n } else if (err.message?.includes('fatal: Authentication failed')) {\n throw new Error(PLATFORM_AUTHENTICATION_ERROR);\n } else if (err.message?.includes('fatal: bad revision')) {\n logger.debug({ err }, 'Aborting job due to bad revision error');\n throw new Error(REPOSITORY_CHANGED);\n } else if (err.message === CONFIG_VALIDATION) {\n logger.debug('Passing config validation error up');\n throw err;\n } else if (err.message === TEMPORARY_ERROR) {\n logger.debug('Passing TEMPORARY_ERROR error up');\n throw err;\n } else if (!(err instanceof ExternalHostError)) {\n logger.warn({ err }, `Error updating branch`);\n }\n // Don't throw here - we don't want to stop the other renovations\n return {\n branchExists,\n prNo: branchPr?.number,\n result: 'error',\n commitSha,\n };\n }\n try {\n logger.debug('Ensuring PR');\n logger.debug(\n `There are ${config.errors!.length} errors and ${\n config.warnings!.length\n } warnings`,\n );\n const ensurePrResult = await ensurePr(config);\n if (ensurePrResult.type === 'without-pr') {\n const { prBlockedBy } = ensurePrResult;\n branchPr = null;\n if (prBlockedBy === 'RateLimited' && !config.isVulnerabilityAlert) {\n logger.debug('Reached PR limit - skipping PR creation');\n return {\n branchExists,\n prBlockedBy,\n result: 'pr-limit-reached',\n commitSha,\n };\n }\n // TODO: ensurePr should check for automerge itself (#9719)\n if (prBlockedBy === 'NeedsApproval') {\n return {\n branchExists,\n prBlockedBy,\n result: 'needs-pr-approval',\n commitSha,\n };\n }\n if (prBlockedBy === 'AwaitingTests') {\n return {\n branchExists,\n prBlockedBy,\n result: 'pending',\n commitSha,\n };\n }\n if (prBlockedBy === 'BranchAutomerge') {\n return {\n branchExists,\n prBlockedBy,\n result: 'done',\n commitSha,\n };\n }\n if (prBlockedBy === 'Error') {\n return {\n branchExists,\n prBlockedBy,\n result: 'error',\n commitSha,\n };\n }\n logger.warn({ prBlockedBy }, 'Unknown PrBlockedBy result');\n return {\n branchExists,\n prBlockedBy,\n result: 'error',\n commitSha,\n };\n }\n if (ensurePrResult.type === 'with-pr') {\n const { pr } = ensurePrResult;\n branchPr = pr;\n // Retry setting branch statuses after PR/MR creation so that\n // platforms using MR pipelines (e.g. GitLab) have a pipeline to\n // associate the status with. The earlier call may have been\n // skipped if no pipeline existed yet.\n await setBranchStatusChecks(config);\n if (config.artifactErrors?.length) {\n logger.warn(\n { artifactErrors: config.artifactErrors },\n 'artifactErrors',\n );\n let content = `Renovate failed to update `;\n content +=\n config.artifactErrors.length > 1 ? 'artifacts' : 'an artifact';\n content += ' related to this branch. ';\n content += template.compile(\n config.userStrings!.artifactErrorWarning,\n config,\n );\n content += emojify(\n `\\n\\n:recycle: Renovate will retry this branch, including artifacts, only when one of the following happens:\\n\\n`,\n );\n content +=\n ' - any of the package files in this branch needs updating, or \\n';\n content += ' - the branch becomes conflicted, or\\n';\n content +=\n ' - you click the rebase/retry checkbox if found above, or\\n';\n content +=\n ' - you rename this PR\\'s title to start with \"rebase!\" to trigger it manually';\n content += '\\n\\nThe artifact failure details are included below:\\n\\n';\n // TODO: types (#22198)\n config.artifactErrors.forEach((error) => {\n content += `##### File name: ${error.lockFile!}\\n\\n`;\n content += `\\`\\`\\`\\n${error.stderr!}\\n\\`\\`\\`\\n\\n`;\n });\n content = platform.massageMarkdown(content, config.rebaseLabel);\n if (\n !(\n config.suppressNotifications!.includes('artifactErrors') ||\n config.suppressNotifications!.includes('lockFileErrors')\n )\n ) {\n if (GlobalConfig.get('dryRun')) {\n logger.info(\n `DRY-RUN: Would ensure lock file error comment in PR #${pr.number}`,\n );\n } else {\n await ensureComment({\n number: pr.number,\n topic: artifactErrorTopic,\n content,\n });\n }\n }\n } else {\n if (config.artifactNotices?.length) {\n const contentLines: string[] = [];\n for (const notice of config.artifactNotices) {\n contentLines.push(`##### File name: ${notice.file}`);\n contentLines.push(notice.message);\n }\n const content = contentLines.join('\\n\\n');\n await ensureComment({\n number: pr.number,\n topic: artifactNoticeTopic,\n content,\n });\n }\n\n if (config.automerge) {\n logger.debug('PR is configured for automerge');\n // skip automerge if there is a new commit since status checks aren't done yet\n if (config.ignoreTests === true || !commitSha) {\n logger.debug('checking auto-merge');\n const prAutomergeResult = await checkAutoMerge(pr, config);\n if (prAutomergeResult?.automerged) {\n return {\n branchExists,\n result: 'automerged',\n commitSha,\n };\n }\n }\n } else {\n logger.debug('PR is not configured for automerge');\n }\n }\n }\n } catch (err) {\n /* v8 ignore if -- needs test */\n if (\n err instanceof ExternalHostError ||\n [PLATFORM_RATE_LIMIT_EXCEEDED, REPOSITORY_CHANGED].includes(err.message)\n ) {\n logger.debug('Passing PR error up');\n throw err;\n }\n // Otherwise don't throw here - we don't want to stop the other renovations\n logger.error({ err }, `Error ensuring PR`);\n }\n if (!branchExists) {\n return {\n branchExists: true,\n updatesVerified,\n prNo: branchPr?.number,\n result: 'pr-created',\n commitSha,\n };\n }\n return {\n branchExists,\n updatesVerified,\n prNo: branchPr?.number,\n result: 'done',\n commitSha,\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
package/renovate-schema.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"title": "JSON schema for Renovate 43.45.
|
|
2
|
+
"title": "JSON schema for Renovate 43.45.2 config files (https://renovatebot.com/)",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
|
-
"x-renovate-version": "43.45.
|
|
4
|
+
"x-renovate-version": "43.45.2",
|
|
5
5
|
"allowComments": true,
|
|
6
6
|
"type": "object",
|
|
7
7
|
"properties": {
|