backport
Version:
A CLI tool that automates the process of backporting commits
247 lines • 10.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = __importDefault(require("crypto"));
const rest_1 = require("@octokit/rest");
const getDevAccessToken_1 = require("../../../test/private/getDevAccessToken");
const createPullRequest_1 = require("../v3/getPullRequest/createPullRequest");
const disablePullRequestAutoMerge_1 = require("./disablePullRequestAutoMerge");
const enablePullRequestAutoMerge_1 = require("./enablePullRequestAutoMerge");
const fetchPullRequestAutoMergeMethod_1 = require("./fetchPullRequestAutoMergeMethod");
// The test repo requires auto-merge being enabled in options, as well as all merge types enabled (merge, squash, rebase)
// The test pull requests should be open, and not currently able to be merged (e.g. because it requires an approval),
// otherwise it will be merged when auto-merge is turned on
const TEST_REPO_OWNER = 'backport-org';
const TEST_REPO_NAME = 'repo-with-auto-merge-enabled';
const INITIAL_SHA = '70aa879411e95b6662f8ddcb80a944fc4444579f';
const accessToken = (0, getDevAccessToken_1.getDevAccessToken)();
jest.setTimeout(20000);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function resetReference(octokit) {
return octokit.rest.git.updateRef({
owner: TEST_REPO_OWNER,
repo: TEST_REPO_NAME,
ref: 'heads/main',
sha: INITIAL_SHA,
force: true,
});
}
async function closePr({ octokit, pullNumber, }) {
await octokit.pulls.update({
owner: TEST_REPO_OWNER,
repo: TEST_REPO_NAME,
pull_number: pullNumber,
state: 'closed',
});
}
async function createPr({ options, headBranch, baseBranch, }) {
const prPayload = {
base: baseBranch,
head: headBranch,
body: 'testing...',
owner: TEST_REPO_OWNER,
repo: TEST_REPO_NAME,
title: 'my pr title',
draft: false,
};
const { number } = await (0, createPullRequest_1.createPullRequest)({ options, prPayload });
return number;
}
async function deleteBranch({ octokit, branchName, }) {
await octokit.git.deleteRef({
owner: TEST_REPO_OWNER,
repo: TEST_REPO_NAME,
ref: `heads/${branchName}`,
});
}
async function createBranch({ octokit, branchName, sha, }) {
await octokit.git.createRef({
owner: TEST_REPO_OWNER,
repo: TEST_REPO_NAME,
ref: `refs/heads/${branchName}`,
sha,
});
}
async function addCommit(octokit) {
const randomString = Math.random().toString(36).slice(2);
const res = await octokit.rest.repos.createOrUpdateFileContents({
owner: TEST_REPO_OWNER,
repo: TEST_REPO_NAME,
path: `file-to-change-${randomString}`,
message: 'Automatically changed',
content: Buffer.from(`My new hash ${randomString}`).toString('base64'),
branch: 'main',
});
const sha = res.data.commit.sha;
if (!sha) {
throw new Error('Missing sha');
}
return sha;
}
describe('enablePullRequestAutoMerge', () => {
describe('create a PR and enable auto-merge against "approvals-required-branch"', () => {
let pullNumber;
let branchName;
let octokit;
let options;
beforeAll(async () => {
const randomString = crypto_1.default.randomBytes(4).toString('hex');
branchName = `test-${randomString}`;
options = {
accessToken,
repoOwner: TEST_REPO_OWNER,
repoName: TEST_REPO_NAME,
};
octokit = new rest_1.Octokit({ auth: accessToken });
await resetReference(octokit);
const sha = await addCommit(octokit);
await createBranch({ octokit, branchName, sha });
pullNumber = await createPr({
options,
headBranch: branchName,
baseBranch: 'approvals-required-branch',
});
});
// cleanup
afterAll(async () => {
await closePr({ octokit, pullNumber });
await deleteBranch({ octokit, branchName });
await resetReference(octokit);
});
// reset auto-merge state between runs
afterEach(async () => {
await (0, disablePullRequestAutoMerge_1.disablePullRequestAutoMerge)(options, pullNumber);
});
it('should initially have auto-merge disabled', async () => {
const autoMergeMethod = await (0, fetchPullRequestAutoMergeMethod_1.fetchPullRequestAutoMergeMethod)(options, pullNumber);
expect(autoMergeMethod).toBe(undefined);
});
it('should enable auto-merge via merge', async () => {
await (0, enablePullRequestAutoMerge_1.enablePullRequestAutoMerge)({ ...options, autoMergeMethod: 'merge' }, pullNumber);
// ensure Github API reflects the change before querying
await sleep(100);
const autoMergeMethod = await (0, fetchPullRequestAutoMergeMethod_1.fetchPullRequestAutoMergeMethod)(options, pullNumber);
expect(autoMergeMethod).toBe('MERGE');
});
it('should fail when enabling auto-merge via rebase because it is disallowed', async () => {
let errorMessage;
let isMissingStatusChecks;
try {
await (0, enablePullRequestAutoMerge_1.enablePullRequestAutoMerge)({ ...options, autoMergeMethod: 'rebase' }, pullNumber);
}
catch (e) {
const err = e;
isMissingStatusChecks = (0, enablePullRequestAutoMerge_1.isMissingStatusChecksError)(err);
errorMessage = err.message;
}
expect(isMissingStatusChecks).toBe(false);
expect(errorMessage).toMatchInlineSnapshot(`"[GraphQL] Merge method rebase merging is not allowed on this repository (Github API v4)"`);
// ensure Github API reflects the change before querying
await sleep(100);
const autoMergeMethod = await (0, fetchPullRequestAutoMergeMethod_1.fetchPullRequestAutoMergeMethod)(options, pullNumber);
expect(autoMergeMethod).toBe(undefined);
});
it('should enable auto-merge via squash', async () => {
await (0, enablePullRequestAutoMerge_1.enablePullRequestAutoMerge)({ ...options, autoMergeMethod: 'squash' }, pullNumber);
// ensure Github API reflects the change before querying
await sleep(100);
const autoMergeMethod = await (0, fetchPullRequestAutoMergeMethod_1.fetchPullRequestAutoMergeMethod)(options, pullNumber);
expect(autoMergeMethod).toBe('SQUASH');
});
});
describe('when creating a PR against "no-checks-required-branch"', () => {
let pullNumber;
let branchName;
let octokit;
let options;
beforeAll(async () => {
const randomString = crypto_1.default.randomBytes(4).toString('hex');
branchName = `test-${randomString}`;
options = {
accessToken,
repoOwner: TEST_REPO_OWNER,
repoName: TEST_REPO_NAME,
};
octokit = new rest_1.Octokit({ auth: accessToken });
await resetReference(octokit);
const sha = await addCommit(octokit);
await createBranch({ octokit, branchName, sha });
pullNumber = await createPr({
options,
headBranch: branchName,
baseBranch: 'no-checks-required-branch',
});
});
// cleanup
afterAll(async () => {
await closePr({ octokit, pullNumber });
await deleteBranch({ octokit, branchName });
await resetReference(octokit);
});
// eslint-disable-next-line jest/no-disabled-tests
it.skip('should not be possible to enable auto-merge', async () => {
let isMissingStatusChecks;
let errorMessage;
try {
await (0, enablePullRequestAutoMerge_1.enablePullRequestAutoMerge)({ ...options, autoMergeMethod: 'merge' }, pullNumber);
}
catch (e) {
const err = e;
isMissingStatusChecks = (0, enablePullRequestAutoMerge_1.isMissingStatusChecksError)(err);
errorMessage = err.message;
}
expect(errorMessage).toMatchInlineSnapshot(`"Pull request Pull request is in clean status (Github API v4)"`);
expect(isMissingStatusChecks).toBe(true);
});
});
describe('when createing a PR against "status-checks-required-branch"', () => {
let pullNumber;
let branchName;
let octokit;
let options;
beforeAll(async () => {
const randomString = crypto_1.default.randomBytes(4).toString('hex');
branchName = `test-${randomString}`;
options = {
accessToken,
repoOwner: TEST_REPO_OWNER,
repoName: TEST_REPO_NAME,
};
octokit = new rest_1.Octokit({ auth: accessToken });
await resetReference(octokit);
const sha = await addCommit(octokit);
await createBranch({ octokit, branchName, sha });
pullNumber = await createPr({
options,
headBranch: branchName,
baseBranch: 'status-checks-required-branch',
});
});
// cleanup
afterAll(async () => {
await closePr({ octokit, pullNumber });
await deleteBranch({ octokit, branchName });
await resetReference(octokit);
});
// eslint-disable-next-line jest/no-disabled-tests
it.skip('should not be possible to enable auto-merge', async () => {
let isMissingStatusChecks;
let errorMessage;
try {
await (0, enablePullRequestAutoMerge_1.enablePullRequestAutoMerge)({ ...options, autoMergeMethod: 'merge' }, pullNumber);
}
catch (e) {
const err = e;
isMissingStatusChecks = (0, enablePullRequestAutoMerge_1.isMissingStatusChecksError)(err);
errorMessage = err.message;
}
const autoMergeMethod = await (0, fetchPullRequestAutoMergeMethod_1.fetchPullRequestAutoMergeMethod)(options, pullNumber);
expect(autoMergeMethod).toBe(undefined);
expect(errorMessage).toMatchInlineSnapshot(`"Pull request Pull request is in clean status (Github API v4)"`);
expect(isMissingStatusChecks).toBe(true);
});
});
});
//# sourceMappingURL=enablePullRequestAutoMerge.mutation.test.js.map