backport
Version:
A CLI tool that automates the process of backporting commits
168 lines • 6.95 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.backportRun = void 0;
const chalk_1 = __importDefault(require("chalk"));
const elastic_apm_node_1 = __importDefault(require("elastic-apm-node"));
const BackportError_1 = require("./lib/BackportError");
const apm_1 = require("./lib/apm");
const env_1 = require("./lib/env");
const getCommits_1 = require("./lib/getCommits");
const getTargetBranches_1 = require("./lib/getTargetBranches");
const createStatusComment_1 = require("./lib/github/v3/createStatusComment");
const graphqlClient_1 = require("./lib/github/v4/client/graphqlClient");
const logger_1 = require("./lib/logger");
const ora_1 = require("./lib/ora");
const registerHandlebarsHelpers_1 = require("./lib/registerHandlebarsHelpers");
const runSequentially_1 = require("./lib/runSequentially");
const setupRepo_1 = require("./lib/setupRepo");
const cliArgs_1 = require("./options/cliArgs");
const options_1 = require("./options/options");
(0, registerHandlebarsHelpers_1.registerHandlebarsHelpers)();
let _apmTransaction;
async function backportRun({ processArgs, optionsFromModule = {}, exitCodeOnFailure, apmTransaction, }) {
_apmTransaction = apmTransaction;
const { interactive, logFilePath } = (0, cliArgs_1.getRuntimeArguments)(processArgs, optionsFromModule);
const logger = (0, logger_1.initLogger)({ interactive, logFilePath });
let optionsFromCliArgs;
try {
optionsFromCliArgs = (0, cliArgs_1.getOptionsFromCliArgs)(processArgs);
}
catch (e) {
elastic_apm_node_1.default.captureError(e);
if (e instanceof Error) {
(0, logger_1.consoleLog)(e.message);
(0, logger_1.consoleLog)(`Run "backport --help" to see all options`);
return {
status: 'failure',
error: e,
errorMessage: e.message,
commits: [],
};
}
throw e;
}
let options = null;
let commits = [];
const spinner = (0, ora_1.ora)(interactive).start('Initializing...');
try {
options = await (0, options_1.getOptions)({ optionsFromCliArgs, optionsFromModule });
if (!options.telemetry) {
(0, apm_1.disableApm)();
}
apmTransaction?.setLabel('cli_options', JSON.stringify(optionsFromCliArgs));
Object.entries(options).forEach(([key, value]) => {
apmTransaction?.setLabel(`option__${key}`, JSON.stringify(value));
});
logger.info('Backporting options', options);
spinner.stop();
(0, logger_1.consoleLog)((0, options_1.getActiveOptionsFormatted)(options));
const commitsSpan = elastic_apm_node_1.default.startSpan(`Get commits`);
commits = await (0, getCommits_1.getCommits)(options);
commitsSpan?.setLabel('commit_count', commits.length);
commitsSpan?.end();
logger.info('Commits', commits);
if (options.ls) {
return { status: 'success', commits, results: [] };
}
const targetBranchesSpan = elastic_apm_node_1.default.startSpan('Get target branches');
const targetBranches = await (0, getTargetBranches_1.getTargetBranches)(options, commits);
targetBranchesSpan?.setLabel('target-branches-count', targetBranches.length);
targetBranchesSpan?.end();
logger.info('Target branches', targetBranches);
const setupRepoSpan = elastic_apm_node_1.default.startSpan('Setup repository');
await (0, setupRepo_1.setupRepo)(options);
setupRepoSpan?.end();
const backportCommitsSpan = elastic_apm_node_1.default.startSpan('Backport commits');
const results = await (0, runSequentially_1.runSequentially)({
options,
commits,
targetBranches,
});
logger.info('Results', results);
backportCommitsSpan?.end();
const backportResponse = {
status: 'success',
commits,
results,
};
await (0, createStatusComment_1.createStatusComment)({ options, backportResponse });
return backportResponse;
}
catch (e) {
spinner.stop();
let backportResponse;
if (e instanceof BackportError_1.BackportError &&
e.errorContext.code === 'no-branches-exception') {
backportResponse = {
status: 'aborted',
commits,
error: e,
errorMessage: e.message,
};
// this will catch both BackportError and Error
}
else if (e instanceof Error) {
backportResponse = {
status: 'failure',
commits,
error: e,
errorMessage: e.message,
};
}
else {
throw e;
}
if (options) {
await (0, createStatusComment_1.createStatusComment)({ options, backportResponse });
}
outputError({ e, logFilePath });
// only change exit code for failures while in cli mode
if (exitCodeOnFailure && backportResponse.status === 'failure') {
process.exitCode = 1;
}
logger.error('Unhandled exception:', e);
return backportResponse;
}
}
exports.backportRun = backportRun;
function outputError({ e, logFilePath, }) {
if (e instanceof BackportError_1.BackportError || e instanceof graphqlClient_1.GithubV4Exception) {
(0, logger_1.consoleLog)(e.message);
return;
}
if (e instanceof Error) {
// output
(0, logger_1.consoleLog)('\n');
(0, logger_1.consoleLog)(chalk_1.default.bold('⚠️ Ouch! An unhandled error occured 😿'));
(0, logger_1.consoleLog)(e.stack ? e.stack : e.message);
(0, logger_1.consoleLog)('Please open an issue in https://github.com/sorenlouv/backport/issues or contact me directly on https://twitter.com/sorenlouv');
const infoLogPath = (0, env_1.getLogfilePath)({ logFilePath, logLevel: 'info' });
(0, logger_1.consoleLog)(chalk_1.default.italic(`For additional details see the logs: ${infoLogPath}`));
}
}
let didFlush = false;
process.on('exit', () => {
if (!didFlush) {
didFlush = true;
_apmTransaction?.end('exit');
elastic_apm_node_1.default.flush(() => process.exit());
}
});
process.on('uncaughtException', () => {
if (!didFlush) {
didFlush = true;
_apmTransaction?.end('exit');
elastic_apm_node_1.default.flush(() => process.exit());
}
});
process.on('SIGINT', () => {
if (!didFlush) {
didFlush = true;
_apmTransaction?.end('SIGINT');
elastic_apm_node_1.default.flush(() => process.exit());
}
});
//# sourceMappingURL=backportRun.js.map