backport
Version:
A CLI tool that automates the process of backporting commits
664 lines (620 loc) β’ 28.1 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const nock_1 = __importDefault(require("nock"));
const BackportError_1 = require("../../BackportError");
const logger_1 = require("../../logger");
const createStatusComment_1 = require("./createStatusComment");
jest.unmock('../../logger');
describe('createStatusComment', () => {
it('redacts accessToken if it is included in the error message', async () => {
const accessToken = 'ghp_abcdefg';
(0, logger_1.setAccessToken)(accessToken);
const scope = (0, nock_1.default)('https://api.github.com')
.post('/repos/elastic/kibana/issues/100/comments')
.reply(200, 'some response');
let postedCommentBody = '';
scope.on('request', (req, interceptor, body) => {
postedCommentBody = JSON.parse(body).body;
});
await (0, createStatusComment_1.createStatusComment)({
options: {
repoName: 'kibana',
repoOwner: 'elastic',
accessToken,
backportBinary: 'node scripts/backport',
publishStatusCommentOnSuccess: true,
publishStatusCommentOnFailure: true,
githubApiBaseUrlV3: 'https://api.github.com',
interactive: false,
},
backportResponse: {
commits: [{ sourcePullRequest: { number: 100 } }],
status: 'failure',
error: new Error(`Error message containing very secret access token: ${accessToken}.`),
},
});
expect(postedCommentBody).toContain('Error message containing very secret access token: <REDACTED>');
scope.done();
nock_1.default.cleanAll();
});
});
describe('getCommentBody', () => {
describe('when an unknown error occurs', () => {
const getParams = (opts) => ({
options: {
backportBinary: 'node scripts/backport',
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'failure',
error: new Error('A terrible error occured'),
},
});
it('posts a comment when `publishStatusCommentOnFailure = true`', () => {
const params = getParams({ publishStatusCommentOnFailure: true });
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π Backport failed
The pull request could not be backported due to the following error:
\`A terrible error occured\`
### Manual backport
To create the backport manually run:
\`\`\`
node scripts/backport --pr 55
\`\`\`
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('does not post a comment when `publishStatusCommentOnFailure = false`', () => {
const params = getParams({ publishStatusCommentOnFailure: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toBe(undefined);
});
});
describe('when all backports succeed', () => {
const getParams = (opts) => ({
options: {
repoName: 'kibana',
repoOwner: 'elastic',
autoMerge: true,
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'success',
results: [
{
status: 'success',
targetBranch: '7.x',
pullRequestNumber: 55,
pullRequestUrl: 'url-to-pr',
},
{
status: 'success',
targetBranch: '7.1',
pullRequestNumber: 66,
pullRequestUrl: 'url-to-pr',
},
],
},
});
it('posts a comment when `publishStatusCommentOnSuccess = true`', () => {
const params = getParams({ publishStatusCommentOnSuccess: true });
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π All backports created successfully
| Status | Branch | Result |
|:------:|:------:|:------|
|β
|7.x|[<img src="https://img.shields.io/github/pulls/detail/state/elastic/kibana/55">](url-to-pr)|
|β
|7.1|[<img src="https://img.shields.io/github/pulls/detail/state/elastic/kibana/66">](url-to-pr)|
Note: Successful backport PRs will be merged automatically after passing CI.
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('does not post a comment when `publishStatusCommentOnSuccess = false`', () => {
const params = getParams({ interactive: true });
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`undefined`);
});
});
describe('when all backports fail', () => {
const getParams = (opts) => ({
options: {
repoName: 'kibana',
repoOwner: 'elastic',
autoMerge: true,
backportBinary: 'node scripts/backport',
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'success',
results: [
{
status: 'unhandled-error',
targetBranch: '7.x',
error: new Error('My boom error!'),
},
{
status: 'unhandled-error',
targetBranch: '7.1',
error: new Error('My boom error!'),
},
],
},
});
it('posts a comment when `publishStatusCommentOnFailure = true`', () => {
const params = getParams({ publishStatusCommentOnFailure: true });
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π All backports failed
| Status | Branch | Result |
|:------:|:------:|:------|
|β|7.x|An unhandled error occurred. Please see the logs for details|
|β|7.1|An unhandled error occurred. Please see the logs for details|
### Manual backport
To create the backport manually run:
\`\`\`
node scripts/backport --pr 55
\`\`\`
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('does not post a comment when `publishStatusCommentOnFailure = false`', () => {
const params = getParams({ publishStatusCommentOnFailure: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toBe(undefined);
});
});
describe('when some backports fail', () => {
const getParams = (opts) => ({
options: {
repoName: 'kibana',
repoOwner: 'elastic',
autoMerge: true,
backportBinary: 'node scripts/backport',
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'success',
results: [
{
status: 'success',
targetBranch: '7.x',
pullRequestNumber: 55,
pullRequestUrl: 'url-to-pr-55',
},
{
status: 'failure',
targetBranch: '7.1',
error: new Error('My boom error!'),
},
],
},
});
it('posts a comment when `publishStatusCommentOnFailure = true`', () => {
const params = getParams({ publishStatusCommentOnFailure: true });
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π Some backports could not be created
| Status | Branch | Result |
|:------:|:------:|:------|
|β
|7.x|[<img src="https://img.shields.io/github/pulls/detail/state/elastic/kibana/55">](url-to-pr-55)|
|β|7.1|An unhandled error occurred. Please see the logs for details|
Note: Successful backport PRs will be merged automatically after passing CI.
### Manual backport
To create the backport manually run:
\`\`\`
node scripts/backport --pr 55
\`\`\`
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('does not post a comment when running `publishStatusCommentOnFailure = false`', () => {
const params = getParams({ publishStatusCommentOnFailure: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`undefined`);
});
});
describe('when some backports fail due to conflicts', () => {
const getParams = (opts) => ({
options: {
repoName: 'kibana',
repoOwner: 'elastic',
autoMerge: true,
backportBinary: 'node scripts/backport',
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'success',
results: [
{
status: 'success',
targetBranch: '7.x',
pullRequestNumber: 55,
pullRequestUrl: 'url-to-pr-55',
},
{
status: 'failure',
targetBranch: '7.1',
error: new BackportError_1.BackportError({
code: 'merge-conflict-exception',
conflictingFiles: ['readme.md'],
commitsWithoutBackports: [
{
formatted: 'some-formatted-text',
commit: {
author: {
email: 'soren.louv@elastic.co',
name: 'SΓΈren Louv-Jansen',
},
sourceBranch: 'master',
sourcePullRequest: {
labels: [],
number: 5,
url: 'url-to-pr-5',
title: 'New Zealand commit message',
mergeCommit: {
sha: '',
message: 'New Zealand commit message',
},
},
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: '',
sha: '',
message: 'New Zealand commit message',
},
targetPullRequestStates: [],
},
},
{
formatted: 'some-formatted-text',
commit: {
author: {
email: 'soren.louv@elastic.co',
name: 'SΓΈren Louv-Jansen',
},
sourceBranch: 'master',
sourcePullRequest: {
labels: [],
number: 44,
title: 'Australia commit',
url: 'url-to-pr-44',
mergeCommit: {
sha: '',
message: 'Australia commit',
},
},
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: '',
sha: '',
message: 'Australia commit',
},
targetPullRequestStates: [],
},
},
{
formatted: 'some-formatted-text',
commit: {
author: {
email: 'matthias.wilhelm@elastic.co',
name: 'Matthias Polman-Wilhelm',
},
sourceBranch: 'master',
sourcePullRequest: {
labels: [],
number: 44,
title: 'Antarctica commit | with pipeline char',
url: 'url-to-pr-45',
mergeCommit: {
sha: '',
message: 'Antarctica commit | with pipeline char',
},
},
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: '',
sha: '',
message: 'Antarctica commit | with pipeline char',
},
targetPullRequestStates: [],
},
},
],
}),
},
{
status: 'failure',
targetBranch: '7.2',
error: new BackportError_1.BackportError({
code: 'merge-conflict-exception',
conflictingFiles: ['my-file.txt'],
commitsWithoutBackports: [],
}),
},
],
},
});
it('posts a comment when `publishStatusCommentOnFailure = true`', () => {
const params = getParams({ publishStatusCommentOnFailure: true });
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π Some backports could not be created
| Status | Branch | Result |
|:------:|:------:|:------|
|β
|7.x|[<img src="https://img.shields.io/github/pulls/detail/state/elastic/kibana/55">](url-to-pr-55)|
|β|7.1|**Backport failed because of merge conflicts**<br><br>You might need to backport the following PRs to 7.1:<br> - [New Zealand commit message](url-to-pr-5)<br> - [Australia commit](url-to-pr-44)<br> - [Antarctica commit \\| with pipeline char](url-to-pr-45)|
|β|7.2|Backport failed because of merge conflicts|
Note: Successful backport PRs will be merged automatically after passing CI.
### Manual backport
To create the backport manually run:
\`\`\`
node scripts/backport --pr 55
\`\`\`
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('does not post a comment when `publishStatusCommentOnFailure = false`', () => {
const params = getParams({ publishStatusCommentOnFailure: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toBe(undefined);
});
});
describe('when backport was aborted due to missing branches', () => {
const getParams = (opts) => ({
options: {
repoName: 'kibana',
repoOwner: 'elastic',
autoMerge: true,
backportBinary: 'node scripts/backport',
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'aborted',
commits: [],
error: new BackportError_1.BackportError({ code: 'no-branches-exception' }),
errorMessage: 'my message',
},
});
it('posts a comment when `publishStatusCommentOnAbort = true`', () => {
const params = getParams({
publishStatusCommentOnAbort: true,
});
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## βͺ 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.
### Manual backport
To create the backport manually run:
\`\`\`
node scripts/backport --pr 55
\`\`\`
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('does not post a comment when `publishStatusCommentOnAbort = false`', () => {
const params = getParams({ publishStatusCommentOnAbort: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toBe(undefined);
});
});
describe('when backport was aborted during conflict resolution', () => {
const getParams = (opts) => ({
options: {
interactive: true,
repoName: 'kibana',
repoOwner: 'elastic',
autoMerge: true,
backportBinary: 'node scripts/backport',
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'success',
commits: [],
results: [
{
targetBranch: 'staging',
status: 'handled-error',
error: new BackportError_1.BackportError({
code: 'abort-conflict-resolution-exception',
}),
},
],
},
});
it('posts a comment when `publishStatusCommentOnAbort = true`', () => {
const params = getParams({
publishStatusCommentOnAbort: true,
});
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`undefined`);
});
it('does not post a comment when `publishStatusCommentOnAbort = false`', () => {
const params = getParams({ publishStatusCommentOnAbort: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toBe(undefined);
});
it('posts a comment when `publishStatusCommentOnFailure = true`', () => {
const params = getParams({
publishStatusCommentOnFailure: true,
});
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π All backports failed
| Status | Branch | Result |
|:------:|:------:|:------|
|β|staging|Conflict resolution was aborted by the user|
### Manual backport
To create the backport manually run:
\`\`\`
node scripts/backport --pr 55
\`\`\`
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('does not post a comment when `publishStatusCommentOnFailure = false`', () => {
const params = getParams({ publishStatusCommentOnFailure: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toBe(undefined);
});
});
describe("when target branch doesn't exist", () => {
const getParams = (opts) => ({
options: {
interactive: true,
repoName: 'kibana',
repoOwner: 'elastic',
autoMerge: true,
backportBinary: 'node scripts/backport',
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'success',
commits: [],
results: [
{
targetBranch: 'main',
status: 'handled-error',
error: new BackportError_1.BackportError('The branch "main" is invalid or doesn\'t exist'),
},
],
},
});
it('posts a comment when `publishStatusCommentOnFailure = true`', () => {
const params = getParams({
publishStatusCommentOnFailure: true,
});
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π All backports failed
| Status | Branch | Result |
|:------:|:------:|:------|
|β|main|The branch "main" is invalid or doesn't exist|
### Manual backport
To create the backport manually run:
\`\`\`
node scripts/backport --pr 55
\`\`\`
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('does not post a comment when `publishStatusCommentOnFailure = false`', () => {
const params = getParams({ publishStatusCommentOnFailure: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toBe(undefined);
});
});
describe('when target branch is invalid', () => {
const getParams = (opts) => ({
options: {
interactive: true,
repoName: 'kibana',
repoOwner: 'elastic',
autoMerge: true,
backportBinary: 'node scripts/backport',
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'success',
commits: [],
results: [
{
targetBranch: '--foo',
status: 'unhandled-error',
error: new BackportError_1.BackportError('The branch "--foo" does not exist'),
},
],
},
});
it('posts a comment when `publishStatusCommentOnFailure = true`', () => {
const params = getParams({
publishStatusCommentOnFailure: true,
});
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π All backports failed
| Status | Branch | Result |
|:------:|:------:|:------|
|β|--foo|An unhandled error occurred. Please see the logs for details|
### Manual backport
To create the backport manually run:
\`\`\`
node scripts/backport --pr 55
\`\`\`
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('does not post a comment when `publishStatusCommentOnFailure = false`', () => {
const params = getParams({ publishStatusCommentOnFailure: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toBe(undefined);
});
});
describe('shield.io badges', () => {
const getParams = (opts) => ({
options: {
interactive: true,
repoName: 'kibana',
repoOwner: 'elastic',
autoMerge: true,
backportBinary: 'node scripts/backport',
publishStatusCommentOnSuccess: true,
...opts,
},
pullNumber: 55,
backportResponse: {
status: 'success',
results: [
{
status: 'success',
targetBranch: '7.x',
pullRequestNumber: 55,
pullRequestUrl: 'url-to-pr',
},
],
},
});
it('posts a comment without shields.io badge when repo is private`', () => {
const params = getParams({ isRepoPrivate: true });
expect((0, createStatusComment_1.getCommentBody)(params)).not.toContain('img.shields.io');
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π All backports created successfully
| Status | Branch | Result |
|:------:|:------:|:------|
|β
|7.x|url-to-pr|
Note: Successful backport PRs will be merged automatically after passing CI.
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
it('posts a comment with shields.io badge when repo is public`', () => {
const params = getParams({ isRepoPrivate: false });
expect((0, createStatusComment_1.getCommentBody)(params)).toContain('img.shields.io');
expect((0, createStatusComment_1.getCommentBody)(params)).toMatchInlineSnapshot(`
"## π All backports created successfully
| Status | Branch | Result |
|:------:|:------:|:------|
|β
|7.x|[<img src="https://img.shields.io/github/pulls/detail/state/elastic/kibana/55">](url-to-pr)|
Note: Successful backport PRs will be merged automatically after passing CI.
### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)
<!--- Backport version: 1.2.3-mocked -->"
`);
});
});
});
//# sourceMappingURL=createStatusComment.test.js.map