UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

753 lines • 34.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.updatePr = exports.setBranchStatus = exports.mergePr = exports.initRepo = exports.initPlatform = exports.getRepos = exports.getPrList = exports.massageMarkdown = exports.getPr = exports.getIssueList = exports.getJsonFile = exports.getRawFile = exports.getIssue = exports.getBranchStatusCheck = exports.getBranchStatus = exports.getBranchPr = exports.findPr = exports.findIssue = exports.ensureIssueClosing = exports.ensureIssue = exports.ensureCommentRemoval = exports.ensureComment = exports.deleteLabel = exports.createPr = exports.addReviewers = exports.addAssignees = exports.id = void 0; exports.resetPlatform = resetPlatform; exports.maxBodyLength = maxBodyLength; const tslib_1 = require("tslib"); const is_1 = tslib_1.__importDefault(require("@sindresorhus/is")); const semver_1 = tslib_1.__importDefault(require("semver")); const error_messages_1 = require("../../../constants/error-messages"); const logger_1 = require("../../../logger"); const array_1 = require("../../../util/array"); const common_1 = require("../../../util/common"); const env_1 = require("../../../util/env"); const git = tslib_1.__importStar(require("../../../util/git")); const gitea_1 = require("../../../util/http/gitea"); const promises_1 = require("../../../util/promises"); const sanitize_1 = require("../../../util/sanitize"); const url_1 = require("../../../util/url"); const pr_body_1 = require("../pr-body"); const util_1 = require("../util"); const pr_body_2 = require("../utils/pr-body"); const helper = tslib_1.__importStar(require("./gitea-helper")); const gitea_helper_1 = require("./gitea-helper"); const pr_cache_1 = require("./pr-cache"); const utils_1 = require("./utils"); exports.id = 'gitea'; const defaults = { hostType: 'gitea', endpoint: 'https://gitea.com/', version: '0.0.0', isForgejo: false, }; let config = {}; let botUserID; let botUserName; function resetPlatform() { config = {}; botUserID = undefined; botUserName = undefined; defaults.hostType = 'gitea'; defaults.endpoint = 'https://gitea.com/'; defaults.version = '0.0.0'; defaults.isForgejo = false; (0, gitea_1.setBaseUrl)(defaults.endpoint); } function toRenovateIssue(data) { return { number: data.number, state: data.state, title: data.title, body: data.body, }; } function matchesState(actual, expected) { if (expected === 'all') { return true; } if (expected.startsWith('!')) { return actual !== expected.substring(1); } return actual === expected; } function findCommentByTopic(comments, topic) { return comments.find((c) => c.body.startsWith(`### ${topic}\n\n`)) ?? null; } function findCommentByContent(comments, content) { return comments.find((c) => c.body.trim() === content) ?? null; } function getLabelList() { if (config.labelList === null) { const repoLabels = helper .getRepoLabels(config.repository, { memCache: false, }) .then((labels) => { logger_1.logger.debug(`Retrieved ${labels.length} repo labels`); return labels; }); const orgLabels = helper .getOrgLabels(config.repository.split('/')[0], { memCache: false, }) .then((labels) => { logger_1.logger.debug(`Retrieved ${labels.length} org labels`); return labels; }) .catch((err) => { // Will fail if owner of repo is not org or Gitea version < 1.12 logger_1.logger.debug(`Unable to fetch organization labels`); return []; }); config.labelList = Promise.all([repoLabels, orgLabels]).then((labels) => [].concat(...labels)); } return config.labelList; } async function lookupLabelByName(name) { logger_1.logger.debug(`lookupLabelByName(${name})`); const labelList = await getLabelList(); return labelList.find((l) => l.name === name)?.id ?? null; } async function fetchRepositories({ topic, sort, order, }) { const repos = await helper.searchRepos({ uid: botUserID, archived: false, ...(topic && { topic: true, q: topic, }), ...(sort && { sort, }), ...(order && { order, }), }); return repos.filter(utils_1.usableRepo).map((r) => r.full_name); } const platform = { async initPlatform({ endpoint, token, }) { if (!token) { throw new Error('Init: You must configure a Gitea personal access token'); } if (endpoint) { let baseEndpoint = (0, utils_1.trimTrailingApiPath)(endpoint); baseEndpoint = (0, url_1.ensureTrailingSlash)(baseEndpoint); defaults.endpoint = baseEndpoint; } else { logger_1.logger.debug('Using default Gitea endpoint: ' + defaults.endpoint); } (0, gitea_1.setBaseUrl)(defaults.endpoint); let gitAuthor; try { const user = await helper.getCurrentUser({ token }); gitAuthor = `${user.full_name ?? user.username} <${user.email}>`; botUserID = user.id; botUserName = user.username; const env = (0, env_1.getEnv)(); /* v8 ignore start: experimental feature */ if (semver_1.default.valid(env.RENOVATE_X_PLATFORM_VERSION)) { defaults.version = env.RENOVATE_X_PLATFORM_VERSION; } /* v8 ignore stop */ else { defaults.version = await helper.getVersion({ token }); } if (defaults.version?.includes('gitea-')) { defaults.isForgejo = true; } logger_1.logger.debug(`${defaults.isForgejo ? 'Forgejo' : 'Gitea'} version: ${defaults.version}`); } catch (err) { logger_1.logger.debug({ err }, 'Error authenticating with Gitea. Check your token'); throw new Error('Init: Authentication failure'); } return { endpoint: defaults.endpoint, gitAuthor, }; }, async getRawFile(fileName, repoName, branchOrTag) { const repo = repoName ?? config.repository; const contents = await helper.getRepoContents(repo, fileName, branchOrTag); return contents.contentString ?? null; }, async getJsonFile(fileName, repoName, branchOrTag) { // TODO #22198 const raw = await platform.getRawFile(fileName, repoName, branchOrTag); return (0, common_1.parseJson)(raw, fileName); }, async initRepo({ repository, cloneSubmodules, cloneSubmodulesFilter, gitUrl, ignorePrAuthor, }) { let repo; config = {}; config.repository = repository; config.cloneSubmodules = !!cloneSubmodules; config.cloneSubmodulesFilter = cloneSubmodulesFilter; config.ignorePrAuthor = !!ignorePrAuthor; // Try to fetch information about repository try { repo = await helper.getRepo(repository); } catch (err) { logger_1.logger.debug({ err }, 'Unknown Gitea initRepo error'); throw err; } // Ensure appropriate repository state and permissions if (repo.archived) { logger_1.logger.debug('Repository is archived - aborting renovation'); throw new Error(error_messages_1.REPOSITORY_ARCHIVED); } if (repo.mirror) { logger_1.logger.debug('Repository is a mirror - aborting renovation'); throw new Error(error_messages_1.REPOSITORY_MIRRORED); } if (repo.permissions.pull === false || repo.permissions.push === false) { logger_1.logger.debug('Repository does not permit pull or push - aborting renovation'); throw new Error(error_messages_1.REPOSITORY_ACCESS_FORBIDDEN); } if (repo.empty) { logger_1.logger.debug('Repository is empty - aborting renovation'); throw new Error(error_messages_1.REPOSITORY_EMPTY); } if (repo.has_pull_requests === false) { logger_1.logger.debug('Repo has disabled pull requests - aborting renovation'); throw new Error(error_messages_1.REPOSITORY_BLOCKED); } if (repo.allow_rebase) { config.mergeMethod = 'rebase'; } else if (repo.allow_rebase_explicit) { config.mergeMethod = 'rebase-merge'; } else if (repo.allow_squash_merge) { config.mergeMethod = 'squash'; } else if (repo.allow_merge_commits) { config.mergeMethod = 'merge'; } else if (repo.allow_fast_forward_only_merge) { config.mergeMethod = 'fast-forward'; } else { logger_1.logger.debug('Repository has no allowed merge methods - aborting renovation'); throw new Error(error_messages_1.REPOSITORY_BLOCKED); } // Determine author email and branches config.defaultBranch = repo.default_branch; logger_1.logger.debug(`${repository} default branch = ${config.defaultBranch}`); const url = (0, utils_1.getRepoUrl)(repo, gitUrl, defaults.endpoint); // Initialize Git storage await git.initRepo({ ...config, url, }); // Reset cached resources config.issueList = null; config.labelList = null; config.hasIssuesEnabled = !repo.external_tracker && repo.has_issues; return { defaultBranch: config.defaultBranch, isFork: !!repo.fork, repoFingerprint: (0, util_1.repoFingerprint)(repo.id, defaults.endpoint), }; }, async getRepos(config) { logger_1.logger.debug('Auto-discovering Gitea repositories'); try { if (config?.topics) { logger_1.logger.debug({ topics: config.topics }, 'Auto-discovering by topics'); const fetchRepoArgs = config.topics.map((topic) => { return { topic, sort: config.sort, order: config.order, }; }); const repos = await (0, promises_1.map)(fetchRepoArgs, fetchRepositories); return (0, array_1.deduplicateArray)(repos.flat()); } else if (config?.namespaces) { logger_1.logger.debug({ namespaces: config.namespaces }, 'Auto-discovering by organization'); const repos = await (0, promises_1.map)(config.namespaces, async (organization) => { const orgRepos = await helper.orgListRepos(organization); return orgRepos .filter((r) => !r.mirror && !r.archived) .map((r) => r.full_name); }); return (0, array_1.deduplicateArray)(repos.flat()); } else { return await fetchRepositories({ sort: config?.sort, order: config?.order, }); } } catch (err) { logger_1.logger.error({ err }, 'Gitea getRepos() error'); throw err; } }, async setBranchStatus({ branchName, context, description, state, url: target_url, }) { try { // Create new status for branch commit const branchCommit = git.getBranchCommit(branchName); // TODO: check branchCommit await helper.createCommitStatus(config.repository, branchCommit, { state: helper.renovateToGiteaStatusMapping[state] || 'pending', context, description, ...(target_url && { target_url }), }); // Refresh caches by re-fetching commit status for branch await helper.getCombinedCommitStatus(config.repository, branchName, { memCache: false, }); } catch (err) { logger_1.logger.warn({ err }, 'Failed to set branch status'); } }, async getBranchStatus(branchName, internalChecksAsSuccess) { let ccs; try { ccs = await helper.getCombinedCommitStatus(config.repository, branchName); } catch (err) { if (err.statusCode === 404) { logger_1.logger.debug('Received 404 when checking branch status, assuming branch deletion'); throw new Error(error_messages_1.REPOSITORY_CHANGED); } logger_1.logger.debug('Unknown error when checking branch status'); throw err; } logger_1.logger.debug({ ccs }, 'Branch status check result'); if (!internalChecksAsSuccess && ccs.worstStatus === 'success' && ccs.statuses.every((status) => status.context?.startsWith('renovate/'))) { logger_1.logger.debug('Successful checks are all internal renovate/ checks, so returning "pending" branch status'); return 'yellow'; } /* v8 ignore next */ return helper.giteaToRenovateStatusMapping[ccs.worstStatus] ?? 'yellow'; }, async getBranchStatusCheck(branchName, context) { const ccs = await helper.getCombinedCommitStatus(config.repository, branchName); const cs = ccs.statuses.find((s) => s.context === context); if (!cs) { return null; } // no status check exists const status = helper.giteaToRenovateStatusMapping[cs.status]; if (status) { return status; } logger_1.logger.warn({ check: cs }, 'Could not map Gitea status value to Renovate status'); return 'yellow'; }, getPrList() { return pr_cache_1.GiteaPrCache.getPrs(gitea_helper_1.giteaHttp, config.repository, config.ignorePrAuthor, botUserName); }, async getPr(number) { // Search for pull request in cached list or attempt to query directly const prList = await platform.getPrList(); let pr = prList.find((p) => p.number === number) ?? null; if (pr) { logger_1.logger.debug('Returning from cached PRs'); } else { logger_1.logger.debug('PR not found in cached PRs - trying to fetch directly'); const gpr = await helper.getPR(config.repository, number); pr = (0, utils_1.toRenovatePR)(gpr, botUserName); // Add pull request to cache for further lookups / queries if (pr) { await pr_cache_1.GiteaPrCache.setPr(gitea_helper_1.giteaHttp, config.repository, config.ignorePrAuthor, botUserName, pr); } } // Abort and return null if no match was found if (!pr) { return null; } return pr; }, async findPr({ branchName, prTitle: title, state = 'all', includeOtherAuthors, targetBranch, }) { logger_1.logger.debug(`findPr(${branchName}, ${title}, ${state})`); if (includeOtherAuthors && is_1.default.string(targetBranch)) { // do not use pr cache as it only fetches prs created by the bot account const pr = await helper.getPRByBranch(config.repository, targetBranch, branchName); if (!pr) { return null; } return (0, utils_1.toRenovatePR)(pr, null); } const prList = await platform.getPrList(); const pr = prList.find((p) => p.sourceRepo === config.repository && p.sourceBranch === branchName && matchesState(p.state, state) && (!title || p.title === title)); if (pr) { logger_1.logger.debug(`Found PR #${pr.number}`); } return pr ?? null; }, async createPr({ sourceBranch, targetBranch, prTitle, prBody: rawBody, labels: labelNames, platformPrOptions, draftPR, }) { let title = prTitle; const base = targetBranch; const head = sourceBranch; const body = (0, sanitize_1.sanitize)(rawBody); if (draftPR) { title = utils_1.DRAFT_PREFIX + title; } logger_1.logger.debug(`Creating pull request: ${title} (${head} => ${base})`); try { const labels = Array.isArray(labelNames) ? await (0, promises_1.map)(labelNames, lookupLabelByName) : []; const gpr = await helper.createPR(config.repository, { base, head, title, body, labels: labels.filter(is_1.default.number), }); if (platformPrOptions?.usePlatformAutomerge) { // Only Gitea v1.24.0+ and Forgejo v10.0.0+ support delete_branch_after_merge. // This is required to not have undesired behavior when renovate finds existing branches on next run. if (semver_1.default.gte(defaults.version, defaults.isForgejo ? '10.0.0' : '1.24.0')) { try { await helper.mergePR(config.repository, gpr.number, { Do: (0, utils_1.getMergeMethod)(platformPrOptions?.automergeStrategy) ?? config.mergeMethod, merge_when_checks_succeed: true, delete_branch_after_merge: true, }); logger_1.logger.debug({ prNumber: gpr.number }, 'Gitea-native automerge: success'); } catch (err) { logger_1.logger.warn({ err, prNumber: gpr.number }, 'Gitea-native automerge: fail'); } } else { logger_1.logger.debug({ prNumber: gpr.number }, `Gitea-native automerge: not supported on this version of ${defaults.isForgejo ? 'Forgejo' : 'Gitea'}. Use ${defaults.isForgejo ? '10.0.0' : '1.24.0'} or newer.`); } } const pr = (0, utils_1.toRenovatePR)(gpr, botUserName); if (!pr) { throw new Error('Can not parse newly created Pull Request'); } await pr_cache_1.GiteaPrCache.setPr(gitea_helper_1.giteaHttp, config.repository, config.ignorePrAuthor, botUserName, pr); return pr; } catch (err) { // When the user manually deletes a branch from Renovate, the PR remains but is no longer linked to any branch. In // the most recent versions of Gitea, the PR gets automatically closed when that happens, but older versions do // not handle this properly and keep the PR open. As pushing a branch with the same name resurrects the PR, this // would cause a HTTP 409 conflict error, which we hereby gracefully handle. if (err.statusCode === 409) { logger_1.logger.warn({ prTitle: title, sourceBranch }, 'Attempting to gracefully recover from 409 Conflict response in createPr()'); // Refresh cached PR list and search for pull request with matching information pr_cache_1.GiteaPrCache.forceSync(); const pr = await platform.findPr({ branchName: sourceBranch, state: 'open', }); // If a valid PR was found, return and gracefully recover from the error. Otherwise, abort and throw error. if (pr?.bodyStruct) { if (pr.title !== title || pr.bodyStruct.hash !== (0, pr_body_1.hashBody)(body)) { logger_1.logger.debug(`Recovered from 409 Conflict, but PR for ${sourceBranch} is outdated. Updating...`); await platform.updatePr({ number: pr.number, prTitle: title, prBody: body, }); pr.title = title; pr.bodyStruct = (0, pr_body_1.getPrBodyStruct)(body); } else { logger_1.logger.debug(`Recovered from 409 Conflict and PR for ${sourceBranch} is up-to-date`); } return pr; } } throw err; } }, async updatePr({ number, prTitle, prBody: body, labels, state, targetBranch, }) { let title = prTitle; if ((await (0, exports.getPrList)()).find((pr) => pr.number === number)?.isDraft) { title = utils_1.DRAFT_PREFIX + title; } const prUpdateParams = { title, ...(body && { body }), ...(state && { state }), }; if (targetBranch) { prUpdateParams.base = targetBranch; } /** * Update PR labels. * In the Gitea API, labels are replaced on each update if the field is present. * If the field is not present (i.e., undefined), labels aren't updated. * However, the labels array must contain label IDs instead of names, * so a lookup is performed to fetch the details (including the ID) of each label. */ if (Array.isArray(labels)) { prUpdateParams.labels = (await (0, promises_1.map)(labels, lookupLabelByName)).filter(is_1.default.number); if (labels.length !== prUpdateParams.labels.length) { logger_1.logger.warn('Some labels could not be looked up. Renovate may halt label updates assuming changes by others.'); } } const gpr = await helper.updatePR(config.repository, number, prUpdateParams); const pr = (0, utils_1.toRenovatePR)(gpr, botUserName); if (pr) { await pr_cache_1.GiteaPrCache.setPr(gitea_helper_1.giteaHttp, config.repository, config.ignorePrAuthor, botUserName, pr); } }, async mergePr({ id, strategy }) { try { await helper.mergePR(config.repository, id, { Do: (0, utils_1.getMergeMethod)(strategy) ?? config.mergeMethod, }); return true; } catch (err) { logger_1.logger.warn({ err, id }, 'Merging of PR failed'); return false; } }, getIssueList() { if (config.hasIssuesEnabled === false) { return Promise.resolve([]); } config.issueList ??= helper .searchIssues(config.repository, { state: 'all' }, { memCache: false }) .then((issues) => { const issueList = issues.map(toRenovateIssue); logger_1.logger.debug(`Retrieved ${issueList.length} Issues`); return issueList; }); return config.issueList; }, async getIssue(number, memCache = true) { if (config.hasIssuesEnabled === false) { return null; } try { const body = (await helper.getIssue(config.repository, number, { memCache })).body; return { number, body, }; } catch (err) /* v8 ignore start */ { logger_1.logger.debug({ err, number }, 'Error getting issue'); return null; } /* v8 ignore stop */ }, async findIssue(title) { const issueList = await platform.getIssueList(); const issue = issueList.find((i) => i.state === 'open' && i.title === title); if (!issue) { return null; } // TODO: types (#22198) logger_1.logger.debug(`Found Issue #${issue.number}`); // TODO #22198 return exports.getIssue(issue.number); }, async ensureIssue({ title, reuseTitle, body: content, labels: labelNames, shouldReOpen, once, }) { logger_1.logger.debug(`ensureIssue(${title})`); if (config.hasIssuesEnabled === false) { logger_1.logger.info('Cannot ensure issue because issues are disabled in this repository'); return null; } try { const body = (0, utils_1.smartLinks)(content); const issueList = await platform.getIssueList(); let issues = issueList.filter((i) => i.title === title); if (!issues.length) { issues = issueList.filter((i) => i.title === reuseTitle); } const labels = Array.isArray(labelNames) ? (await Promise.all(labelNames.map(lookupLabelByName))).filter(is_1.default.number) : undefined; // Update any matching issues which currently exist if (issues.length) { let activeIssue = issues.find((i) => i.state === 'open'); // If no active issue was found, decide if it shall be skipped, re-opened or updated without state change if (!activeIssue) { if (once) { logger_1.logger.debug('Issue already closed - skipping update'); return null; } if (shouldReOpen) { logger_1.logger.debug('Reopening previously closed Issue'); } // Pick the last issue in the list as the active one activeIssue = issues[issues.length - 1]; } // Close any duplicate issues for (const issue of issues) { if (issue.state === 'open' && issue.number !== activeIssue.number) { // TODO: types (#22198) logger_1.logger.warn({ issueNo: issue.number }, 'Closing duplicate issue'); // TODO #22198 await helper.closeIssue(config.repository, issue.number); } } // Check if issue has already correct state if (activeIssue.title === title && activeIssue.body === body && activeIssue.state === 'open') { logger_1.logger.debug( // TODO: types (#22198) `Issue #${activeIssue.number} is open and up to date - nothing to do`); return null; } // Update issue body and re-open if enabled // TODO: types (#22198) logger_1.logger.debug(`Updating Issue #${activeIssue.number}`); const existingIssue = await helper.updateIssue(config.repository, // TODO #22198 activeIssue.number, { body, title, state: shouldReOpen ? 'open' : activeIssue.state, }); // Test whether the issues need to be updated const existingLabelIds = (existingIssue.labels ?? []).map((label) => label.id); if (labels && (labels.length !== existingLabelIds.length || labels.filter((labelId) => !existingLabelIds.includes(labelId)) .length !== 0)) { await helper.updateIssueLabels(config.repository, // TODO #22198 activeIssue.number, { labels, }); } return 'updated'; } // Create new issue and reset cache const issue = await helper.createIssue(config.repository, { body, title, labels, }); logger_1.logger.debug(`Created new Issue #${issue.number}`); config.issueList = null; return 'created'; } catch (err) { logger_1.logger.warn({ err }, 'Could not ensure issue'); } return null; }, async ensureIssueClosing(title) { logger_1.logger.debug(`ensureIssueClosing(${title})`); if (config.hasIssuesEnabled === false) { return; } const issueList = await platform.getIssueList(); for (const issue of issueList) { if (issue.state === 'open' && issue.title === title) { logger_1.logger.debug(`Closing issue...issueNo: ${issue.number}`); // TODO #22198 await helper.closeIssue(config.repository, issue.number); } } }, async deleteLabel(issue, labelName) { logger_1.logger.debug(`Deleting label ${labelName} from Issue #${issue}`); const label = await lookupLabelByName(labelName); if (label) { await helper.unassignLabel(config.repository, issue, label); } else { logger_1.logger.warn({ issue, labelName }, 'Failed to lookup label for deletion'); } }, async ensureComment({ number: issue, topic, content, }) { try { let body = (0, sanitize_1.sanitize)(content); const commentList = await helper.getComments(config.repository, issue); // Search comment by either topic or exact body let comment = null; if (topic) { comment = findCommentByTopic(commentList, topic); body = `### ${topic}\n\n${body}`; } else { comment = findCommentByContent(commentList, body); } // Create a new comment if no match has been found, otherwise update if necessary if (!comment) { comment = await helper.createComment(config.repository, issue, body); logger_1.logger.info({ repository: config.repository, issue, comment: comment.id }, 'Comment added'); } else if (comment.body === body) { logger_1.logger.debug(`Comment #${comment.id} is already up-to-date`); } else { await helper.updateComment(config.repository, comment.id, body); logger_1.logger.debug({ repository: config.repository, issue, comment: comment.id }, 'Comment updated'); } return true; } catch (err) { logger_1.logger.warn({ err, issue, subject: topic }, 'Error ensuring comment'); return false; } }, async ensureCommentRemoval(deleteConfig) { const { number: issue } = deleteConfig; const key = deleteConfig.type === 'by-topic' ? deleteConfig.topic : deleteConfig.content; logger_1.logger.debug(`Ensuring comment "${key}" in #${issue} is removed`); const commentList = await helper.getComments(config.repository, issue); let comment = null; if (deleteConfig.type === 'by-topic') { comment = findCommentByTopic(commentList, deleteConfig.topic); } else if (deleteConfig.type === 'by-content') { const body = (0, sanitize_1.sanitize)(deleteConfig.content); comment = findCommentByContent(commentList, body); } // Abort and do nothing if no matching comment was found if (!comment) { return; } // Try to delete comment try { await helper.deleteComment(config.repository, comment.id); } catch (err) { logger_1.logger.warn({ err, issue, config: deleteConfig }, 'Error deleting comment'); } }, async getBranchPr(branchName) { logger_1.logger.debug(`getBranchPr(${branchName})`); const pr = await platform.findPr({ branchName, state: 'open' }); return pr ? platform.getPr(pr.number) : null; }, async addAssignees(number, assignees) { logger_1.logger.debug(`Updating assignees '${assignees?.join(', ')}' on Issue #${number}`); await helper.updateIssue(config.repository, number, { assignees, }); }, async addReviewers(number, reviewers) { logger_1.logger.debug(`Adding reviewers '${reviewers?.join(', ')}' to #${number}`); if (semver_1.default.lt(defaults.version, '1.14.0')) { logger_1.logger.debug({ version: defaults.version }, 'Adding reviewer not yet supported.'); return; } try { await helper.requestPrReviewers(config.repository, number, { reviewers }); } catch (err) { logger_1.logger.warn({ err, number, reviewers }, 'Failed to assign reviewer'); } }, massageMarkdown(prBody) { return (0, pr_body_2.smartTruncate)((0, utils_1.smartLinks)(prBody), maxBodyLength()); }, maxBodyLength, }; function maxBodyLength() { return 1000000; } /* eslint-disable @typescript-eslint/unbound-method */ exports.addAssignees = platform.addAssignees, exports.addReviewers = platform.addReviewers, exports.createPr = platform.createPr, exports.deleteLabel = platform.deleteLabel, exports.ensureComment = platform.ensureComment, exports.ensureCommentRemoval = platform.ensureCommentRemoval, exports.ensureIssue = platform.ensureIssue, exports.ensureIssueClosing = platform.ensureIssueClosing, exports.findIssue = platform.findIssue, exports.findPr = platform.findPr, exports.getBranchPr = platform.getBranchPr, exports.getBranchStatus = platform.getBranchStatus, exports.getBranchStatusCheck = platform.getBranchStatusCheck, exports.getIssue = platform.getIssue, exports.getRawFile = platform.getRawFile, exports.getJsonFile = platform.getJsonFile, exports.getIssueList = platform.getIssueList, exports.getPr = platform.getPr, exports.massageMarkdown = platform.massageMarkdown, exports.getPrList = platform.getPrList, exports.getRepos = platform.getRepos, exports.initPlatform = platform.initPlatform, exports.initRepo = platform.initRepo, exports.mergePr = platform.mergePr, exports.setBranchStatus = platform.setBranchStatus, exports.updatePr = platform.updatePr; //# sourceMappingURL=index.js.map