backport
Version:
A CLI tool that automates the process of backporting commits
372 lines • 16.8 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const strip_ansi_1 = __importDefault(require("strip-ansi"));
const git = __importStar(require("../git"));
const fetchCommitsByAuthorModule = __importStar(require("../github/v4/fetchCommits/fetchCommitsByAuthor"));
const getCommitsWithoutBackports_1 = require("./getCommitsWithoutBackports");
describe('getCommitsWithoutBackports', () => {
afterEach(() => {
jest.restoreAllMocks();
});
describe('targetPullRequestStates', () => {
function setupExpectedPullRequests({ targetPullRequestStates, }) {
// simulate 1 unbackported commit
jest
.spyOn(fetchCommitsByAuthorModule, 'fetchCommitsByAuthor')
.mockResolvedValueOnce([
{
author: {
email: 'soren.louv@elastic.co',
name: 'Søren Louv-Jansen',
},
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: '10',
message: 'First commit (#1)',
sha: 'xyz',
},
sourcePullRequest: {
labels: [],
url: 'https://www.github.com/foo/bar/pull/123',
number: 123,
title: 'First commit',
mergeCommit: {
message: 'First commit (#1)',
sha: 'xyz',
},
},
targetPullRequestStates: targetPullRequestStates,
sourceBranch: 'main',
},
]);
// simulate commit is definitely not backported
jest.spyOn(git, 'getIsCommitInBranch').mockResolvedValueOnce(false);
return (0, getCommitsWithoutBackports_1.getCommitsWithoutBackports)({
options: {},
commit: {
author: { email: 'soren.louv@elastic.co', name: 'Søren Louv-Jansen' },
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: '100',
message: 'Second commit (#2)',
sha: 'abc',
},
targetPullRequestStates: [],
sourceBranch: 'main',
},
targetBranch: '7.x',
conflictingFiles: ['/foo/bar/baz.ts'],
});
}
it('should not unbackported commits if no backports were expected', async () => {
const commitsWithoutBackports = await setupExpectedPullRequests({
targetPullRequestStates: [],
});
expect(commitsWithoutBackports.length).toEqual(0);
});
it('should display as missing if a backport is CLOSED', async () => {
const commitsWithoutBackports = await setupExpectedPullRequests({
targetPullRequestStates: [
{
state: 'CLOSED',
branch: '7.x',
number: 456,
url: 'https://www.github.com/foo/bar/pull/456',
},
],
});
expect((0, strip_ansi_1.default)(commitsWithoutBackports[0].formatted)).toEqual(' - First commit (#1) (backport missing)\n https://www.github.com/foo/bar/pull/123');
});
it('should display as missing if a backport is NOT_CREATED', async () => {
const commitsWithoutBackports = await setupExpectedPullRequests({
targetPullRequestStates: [
{
branchLabelMappingKey: 'foo tbd',
state: 'NOT_CREATED',
branch: '7.x',
label: 'v7.0.0',
isSourceBranch: false,
},
],
});
expect((0, strip_ansi_1.default)(commitsWithoutBackports[0].formatted)).toEqual(' - First commit (#1) (backport missing)\n https://www.github.com/foo/bar/pull/123');
});
it('should display as pending if a backport is OPEN', async () => {
const commitsWithoutBackports = await setupExpectedPullRequests({
targetPullRequestStates: [
{
state: 'OPEN',
branch: '7.x',
url: 'https://www.github.com/foo/bar/pull/456',
number: 456,
},
],
});
expect((0, strip_ansi_1.default)(commitsWithoutBackports[0].formatted)).toEqual(' - First commit (#1) (backport pending)\n https://www.github.com/foo/bar/pull/456');
});
it('should not display commit as unbackported if a backport was MERGED', async () => {
const commitsWithoutBackports = await setupExpectedPullRequests({
targetPullRequestStates: [
{
state: 'MERGED',
branch: '7.x',
number: 456,
url: 'https://www.github.com/foo/bar/pull/456',
},
],
});
expect(commitsWithoutBackports).toEqual([]);
});
});
describe('commitDate', () => {
function setupCommitDateDiff({ offendingCommitDate, currentCommitDate, }) {
// simulate 1 commit with a pending backport
jest
.spyOn(fetchCommitsByAuthorModule, 'fetchCommitsByAuthor')
.mockResolvedValueOnce([
{
author: {
email: 'soren.louv@elastic.co',
name: 'Søren Louv-Jansen',
},
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: offendingCommitDate,
message: 'First commit (#1)',
sha: 'xyz',
},
sourcePullRequest: {
labels: [],
number: 123,
title: 'First commit',
url: 'https://www.github.com/foo/bar/pull/123',
mergeCommit: {
message: 'First commit (#1)',
sha: 'xyz',
},
},
sourceBranch: 'main',
targetPullRequestStates: [
{
state: 'OPEN',
branch: '7.x',
number: 456,
url: 'https://www.github.com/foo/bar/pull/456',
},
],
},
]);
// simulate commit is definitely not backported
jest.spyOn(git, 'getIsCommitInBranch').mockResolvedValueOnce(false);
return (0, getCommitsWithoutBackports_1.getCommitsWithoutBackports)({
options: {},
commit: {
author: { email: 'soren.louv@elastic.co', name: 'Søren Louv-Jansen' },
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: currentCommitDate,
message: 'Second commit (#2)',
sha: 'abc',
},
sourcePullRequest: {
labels: [],
number: 123,
title: 'Second commit',
url: 'https://www.github.com/foo/bar/pull/123',
mergeCommit: {
message: 'Second commit (#2)',
sha: 'abc',
},
},
sourceBranch: 'main',
targetPullRequestStates: [],
},
targetBranch: '7.x',
conflictingFiles: ['/foo/bar/baz.ts'],
});
}
it('should not display commit as unbackport if is newer than the commit currently being backported', async () => {
const commitsWithoutBackports = await setupCommitDateDiff({
offendingCommitDate: '100',
currentCommitDate: '10',
});
expect(commitsWithoutBackports).toEqual([]);
});
it('should display commit as unbackport if is older than the commit currently being backported', async () => {
const commitsWithoutBackports = await setupCommitDateDiff({
offendingCommitDate: '10',
currentCommitDate: '100',
});
expect((0, strip_ansi_1.default)(commitsWithoutBackports[0].formatted)).toEqual(' - First commit (#1) (backport pending)\n https://www.github.com/foo/bar/pull/456');
});
});
describe('targetBranch', () => {
function setupTargetBranchDiff({ offendingCommitTargetBranch, currentCommitTargetBranch, }) {
// return mock commits that also touched the conflicting files
jest
.spyOn(fetchCommitsByAuthorModule, 'fetchCommitsByAuthor')
.mockResolvedValueOnce([
{
author: {
email: 'soren.louv@elastic.co',
name: 'Søren Louv-Jansen',
},
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: '10',
message: 'First commit (#1)',
sha: 'xyz',
},
sourcePullRequest: {
labels: [],
number: 123,
title: 'First commit',
url: 'https://www.github.com/foo/bar/pull/123',
mergeCommit: {
message: 'First commit (#1)',
sha: 'xyz',
},
},
sourceBranch: 'main',
targetPullRequestStates: [
{
branch: offendingCommitTargetBranch,
state: 'OPEN',
url: 'https://www.github.com/foo/bar/pull/456',
number: 456,
},
],
},
]);
// simulate commit is definitely not backported
jest.spyOn(git, 'getIsCommitInBranch').mockResolvedValueOnce(false);
return (0, getCommitsWithoutBackports_1.getCommitsWithoutBackports)({
options: {},
// commit that is being backported
commit: {
author: { email: 'soren.louv@elastic.co', name: 'Søren Louv-Jansen' },
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: '100',
message: 'Second commit (#2)',
sha: 'abc',
},
sourcePullRequest: {
labels: [],
url: 'https://www.github.com/foo/bar/pull/123',
number: 123,
title: 'Second commit',
mergeCommit: {
message: 'Second commit (#2)',
sha: 'abc',
},
},
targetPullRequestStates: [],
sourceBranch: 'main',
},
targetBranch: currentCommitTargetBranch,
conflictingFiles: ['/foo/bar/baz.ts'],
});
}
it('should display backport as pending if target branches match', async () => {
const commitsWithoutBackports = await setupTargetBranchDiff({
offendingCommitTargetBranch: '7.x',
currentCommitTargetBranch: '7.x',
});
expect((0, strip_ansi_1.default)(commitsWithoutBackports[0].formatted)).toEqual(' - First commit (#1) (backport pending)\n https://www.github.com/foo/bar/pull/456');
});
it("should not display commit if target branches don't match", async () => {
const commitsWithoutBackports = await setupTargetBranchDiff({
offendingCommitTargetBranch: '7.x',
currentCommitTargetBranch: '8.x',
});
expect(commitsWithoutBackports.length).toBe(0);
});
});
describe("when conflicting commit doesn't have an associated pull request", () => {
it('should be ignored', async () => {
jest
.spyOn(fetchCommitsByAuthorModule, 'fetchCommitsByAuthor')
.mockResolvedValueOnce([
{
author: {
email: 'soren.louv@elastic.co',
name: 'Søren Louv-Jansen',
},
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: '10',
sha: 'xyz',
message: 'First commit (#1)',
},
targetPullRequestStates: [],
sourceBranch: 'main',
},
]);
// simulate commit is definitely not backported
jest.spyOn(git, 'getIsCommitInBranch').mockResolvedValueOnce(false);
const commitsWithoutBackports = await (0, getCommitsWithoutBackports_1.getCommitsWithoutBackports)({
options: {},
commit: {
author: { email: 'soren.louv@elastic.co', name: 'Søren Louv-Jansen' },
suggestedTargetBranches: [],
sourceCommit: {
branchLabelMapping: {},
committedDate: '100',
message: 'Second commit (#2)',
sha: 'abc',
},
sourcePullRequest: {
labels: [],
url: 'https://www.github.com/foo/bar/pull/123',
number: 123,
title: 'Second commit',
mergeCommit: {
message: 'Second commit (#2)',
sha: 'abc',
},
},
targetPullRequestStates: [],
sourceBranch: 'main',
},
targetBranch: '7.x',
conflictingFiles: ['/foo/bar/baz.ts'],
});
expect(commitsWithoutBackports.length).toEqual(0);
});
});
});
//# sourceMappingURL=getCommitsWithoutBackports.test.js.map