UNPKG

backport

Version:

A CLI tool that automates the process of backporting commits

158 lines 7.92 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getCommentBody = exports.createStatusComment = void 0; const rest_1 = require("@octokit/rest"); const elastic_apm_node_1 = __importDefault(require("elastic-apm-node")); const packageVersion_1 = require("../../../utils/packageVersion"); const BackportError_1 = require("../../BackportError"); const logger_1 = require("../../logger"); const commitFormatters_1 = require("../commitFormatters"); async function createStatusComment({ options, backportResponse, }) { const { githubApiBaseUrlV3, repoName, repoOwner, accessToken } = options; const span = elastic_apm_node_1.default.startSpan('REST: Create status comment'); span?.setType('external', 'http'); try { const octokit = new rest_1.Octokit({ auth: accessToken, baseUrl: githubApiBaseUrlV3, log: logger_1.logger, }); await Promise.all(backportResponse.commits.map((commit) => { if (!commit.sourcePullRequest) { return; } const body = getCommentBody({ options, pullNumber: commit.sourcePullRequest.number, backportResponse, }); // only post comment if there is a body if (!body) { return; } return octokit.issues.createComment({ baseUrl: githubApiBaseUrlV3, owner: repoOwner, repo: repoName, issue_number: commit.sourcePullRequest.number, body: (0, logger_1.redactAccessToken)(body), }); })); } catch (e) { logger_1.logger.error(`Could not create status comment `, e); } finally { span?.end(); } } exports.createStatusComment = createStatusComment; function getCommentBody({ options, pullNumber, backportResponse, }) { const { repoName, repoOwner, autoMerge, isRepoPrivate, noUnmergedBackportsHelp, publishStatusCommentOnAbort, publishStatusCommentOnFailure, publishStatusCommentOnSuccess, } = options; // eg. in addition to `--noStatusComment` add `--noFailureStatusComment` and `--noSuccessStatusComment` where the former will overwrite the two latter const didAllBackportsSucceed = backportResponse.status === 'success' && backportResponse.results.every((r) => r.status === 'success'); const didAllBackportsFail = backportResponse.status === 'failure' || (backportResponse.status === 'success' && backportResponse.results.every((r) => r.status !== 'success')); if ( // don't publish on dry-run options.dryRun || // // don't publish comment under any circumstances (!publishStatusCommentOnFailure && !publishStatusCommentOnSuccess && !publishStatusCommentOnAbort) || // // dont publish comment if all backports suceeded (didAllBackportsSucceed && !publishStatusCommentOnSuccess) || // // dont publish comment if operation failed or all backports failed (didAllBackportsFail && !publishStatusCommentOnFailure) || // // dont publish comment if backport was aborted (backportResponse.status === 'aborted' && !publishStatusCommentOnAbort)) { return; } const packageVersionSection = `\n<!--- Backport version: ${(0, packageVersion_1.getPackageVersion)()} -->`; const manualBackportCommand = `\n### Manual backport\nTo create the backport manually run:\n\`\`\`\n${options.backportBinary} --pr ${pullNumber}\n\`\`\`\n`; const linkToGithubActionLogs = options.githubActionRunId ? ` and see the [Github Action logs](https://github.com/${repoOwner}/${repoName}/actions/runs/${options.githubActionRunId}) for details` : ''; const questionsAndLinkToBackport = `\n### Questions ?\nPlease refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)${linkToGithubActionLogs}\n`; if (backportResponse.status === 'aborted' && backportResponse.error.errorContext.code === 'no-branches-exception') { return `## ⚪ Backport skipped The pull request was not backported as there were no branches to backport to. If this is a mistake, please apply the desired version labels or run the backport tool manually. ${manualBackportCommand}${questionsAndLinkToBackport}${packageVersionSection}`; } if (backportResponse.status !== 'success') { return `## 💔 Backport failed The pull request could not be backported due to the following error: \`${backportResponse.error.message}\` ${manualBackportCommand}${questionsAndLinkToBackport}${packageVersionSection}`; } const tableBody = backportResponse.results .map((result) => { if (result.status === 'success') { const prShield = `[<img src="https://img.shields.io/github/pulls/detail/state/${repoOwner}/${repoName}/${result.pullRequestNumber}">](${result.pullRequestUrl})`; return [ '✅', result.targetBranch, isRepoPrivate ? result.pullRequestUrl : prShield, ]; } if (result.error instanceof BackportError_1.BackportError && result.error.errorContext.code === 'merge-conflict-exception') { const unmergedBackports = result.error.errorContext.commitsWithoutBackports.map((c) => { const msg = (0, commitFormatters_1.getFirstLine)(c.commit.sourceCommit.message); // make sure to escape the pipe character to ensure the markdown table is correct const msgEscaped = msg.replace(/\|/g, '\\|'); return ` - [${msgEscaped}](${c.commit.sourcePullRequest?.url})`; }); const unmergedBackportsSection = unmergedBackports.length > 0 ? `<br><br>You might need to backport the following PRs to ${result.targetBranch}:<br>${unmergedBackports.join('<br>')}` : undefined; const backportFailedLabel = 'Backport failed because of merge conflicts'; return [ '❌', result.targetBranch, unmergedBackportsSection && !noUnmergedBackportsHelp ? `**${backportFailedLabel}**${unmergedBackportsSection}` : backportFailedLabel, ]; } const message = result.status === 'handled-error' ? result.error.message : 'An unhandled error occurred. Please see the logs for details'; return ['❌', result.targetBranch, message]; }) .map((line) => line.join('|')) .join('|\n|'); const table = backportResponse.results.length ? `\n\n| Status | Branch | Result |\n|:------:|:------:|:------|\n|${tableBody}|\n` : ''; const didAnyBackportsSucceed = backportResponse.results.some((r) => r.status === 'success'); let header = ''; if (didAllBackportsSucceed) { header = '## 💚 All backports created successfully'; } else if (didAnyBackportsSucceed) { header = '## 💔 Some backports could not be created'; } else { header = '## 💔 All backports failed'; } const autoMergeMessage = autoMerge && didAnyBackportsSucceed ? '\nNote: Successful backport PRs will be merged automatically after passing CI.\n' : ''; const backportPRCommandMessage = !didAllBackportsSucceed ? `${manualBackportCommand}` : ''; return `${header}${table}${autoMergeMessage}${backportPRCommandMessage}${questionsAndLinkToBackport}${packageVersionSection}`; } exports.getCommentBody = getCommentBody; //# sourceMappingURL=createStatusComment.js.map