mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-25 14:06:27 +00:00
Support branch automerging (#274)
Add support for automerging without PR, Closes #177 * update definitions and docs * Add mergeBranch api * support merge commit * set automergeType * Update API * Refactor merge commit * branch-push working * Refactor branch * Add back base tree * Fix failing tests * Update definitions and docs * Fix automerge logic * Test isBranchStale * start mergeBranch test * test mergeBranch branch-push throws * more tests * test unknown commit type * pr tests * Detect automerge in versions helper * update tests for new automergeEnabled flag * refactor pr logic * complete pr worker tests * branch automerge tests * Update docs * refactor branch automerge check
This commit is contained in:
parent
f3ff65e4fa
commit
112ff0b410
13 changed files with 650 additions and 114 deletions
|
@ -89,6 +89,7 @@ $ node renovate --help
|
|||
--rebase-stale-prs [boolean] Rebase stale PRs (GitHub only)
|
||||
--pr-creation <string> When to create the PR for a branch. Values: immediate, not-pending, status-success.
|
||||
--automerge <string> What types of upgrades to merge to base branch automatically. Values: none, minor or any
|
||||
--automerge-type <string> How to automerge - "branch-merge-commit", "branch-push" or "pr". Branch support is GitHub-only
|
||||
--yarn-cache-folder <string> Location of yarn cache folder to use. Set to empty string to disable
|
||||
--maintain-yarn-lock [boolean] Keep yarn.lock files updated in base branch
|
||||
--lazy-grouping [boolean] Use group names only when multiple dependencies upgraded
|
||||
|
@ -152,6 +153,7 @@ Obviously, you can't set repository or package file location with this method.
|
|||
| `rebaseStalePrs` | Rebase stale PRs (GitHub only) | boolean | `false` | `RENOVATE_REBASE_STALE_PRS` | `--rebase-stale-prs` |
|
||||
| `prCreation` | When to create the PR for a branch. Values: immediate, not-pending, status-success. | string | `"immediate"` | `RENOVATE_PR_CREATION` | `--pr-creation` |
|
||||
| `automerge` | What types of upgrades to merge to base branch automatically. Values: none, minor or any | string | `"none"` | `RENOVATE_AUTOMERGE` | `--automerge` |
|
||||
| `automergeType` | How to automerge - "branch-merge-commit", "branch-push" or "pr". Branch support is GitHub-only | string | `"pr"` | `RENOVATE_AUTOMERGE_TYPE` | `--automerge-type` |
|
||||
| `branchName` | Branch name template | string | `"renovate/{{depName}}-{{newVersionMajor}}.x"` | `RENOVATE_BRANCH_NAME` | |
|
||||
| `commitMessage` | Commit message template | string | `"Update dependency {{depName}} to version {{newVersion}}"` | `RENOVATE_COMMIT_MESSAGE` | |
|
||||
| `prTitle` | Pull Request title template | string | `"{{#if isPin}}Pin{{else}}Update{{/if}} dependency {{depName}} to version {{#if isRange}}{{newVersion}}{{else}}{{#if isMajor}}{{newVersionMajor}}.x{{else}}{{newVersion}}{{/if}}{{/if}}"` | `RENOVATE_PR_TITLE` | |
|
||||
|
|
|
@ -15,9 +15,11 @@ module.exports = {
|
|||
findFilePaths,
|
||||
// Branch
|
||||
branchExists,
|
||||
isBranchStale,
|
||||
getBranchPr,
|
||||
getBranchStatus,
|
||||
deleteBranch,
|
||||
mergeBranch,
|
||||
// issue
|
||||
addAssignees,
|
||||
addReviewers,
|
||||
|
@ -209,6 +211,19 @@ async function branchExists(branchName) {
|
|||
}
|
||||
}
|
||||
|
||||
async function isBranchStale(branchName) {
|
||||
// Check if branch's parent SHA = master SHA
|
||||
logger.debug(`isBranchStale(${branchName})`);
|
||||
const branchCommit = await getBranchCommit(branchName);
|
||||
logger.debug(`branchCommit=${branchCommit}`);
|
||||
const commitDetails = await getCommitDetails(branchCommit);
|
||||
logger.debug(`commitDetails=${JSON.stringify(commitDetails)}`);
|
||||
const parentSha = commitDetails.parents[0].sha;
|
||||
logger.debug(`parentSha=${parentSha}`);
|
||||
// Return true if the SHAs don't match
|
||||
return parentSha !== config.baseCommitSHA;
|
||||
}
|
||||
|
||||
// Returns the Pull Request for a branch. Null if not exists.
|
||||
async function getBranchPr(branchName) {
|
||||
logger.debug(`getBranchPr(${branchName})`);
|
||||
|
@ -236,6 +251,46 @@ async function deleteBranch(branchName) {
|
|||
await ghGot.delete(`repos/${config.repoName}/git/refs/heads/${branchName}`);
|
||||
}
|
||||
|
||||
async function mergeBranch(branchName, mergeType) {
|
||||
logger.debug(`mergeBranch(${branchName}, ${mergeType})`);
|
||||
if (mergeType === 'branch-push') {
|
||||
const url = `repos/${config.repoName}/git/refs/heads/${config.defaultBranch}`;
|
||||
const options = {
|
||||
body: {
|
||||
sha: await getBranchCommit(branchName),
|
||||
},
|
||||
};
|
||||
try {
|
||||
await ghGot.patch(url, options);
|
||||
} catch (err) {
|
||||
logger.error(`Error pushing branch merge for ${branchName}`);
|
||||
logger.debug(JSON.stringify(err));
|
||||
throw new Error('branch-push failed');
|
||||
}
|
||||
} else if (mergeType === 'branch-merge-commit') {
|
||||
const url = `repos/${config.repoName}/merges`;
|
||||
const options = {
|
||||
body: {
|
||||
base: config.defaultBranch,
|
||||
head: branchName,
|
||||
},
|
||||
};
|
||||
try {
|
||||
await ghGot.post(url, options);
|
||||
} catch (err) {
|
||||
logger.error(`Error pushing branch merge for ${branchName}`);
|
||||
logger.debug(JSON.stringify(err));
|
||||
throw new Error('branch-push failed');
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Unsupported branch merge type: ${mergeType}`);
|
||||
}
|
||||
// Update base commit
|
||||
config.baseCommitSHA = await getBranchCommit(config.defaultBranch);
|
||||
// Delete branch
|
||||
await deleteBranch(branchName);
|
||||
}
|
||||
|
||||
// Issue
|
||||
|
||||
async function addAssignees(issueNo, assignees) {
|
||||
|
@ -522,6 +577,12 @@ async function getBranchCommit(branchName) {
|
|||
.body.object.sha;
|
||||
}
|
||||
|
||||
async function getCommitDetails(commit) {
|
||||
logger.debug(`getCommitDetails(${commit})`);
|
||||
const results = await ghGot(`repos/${config.repoName}/git/commits/${commit}`);
|
||||
return results.body;
|
||||
}
|
||||
|
||||
// Return the tree SHA for a commit
|
||||
async function getCommitTree(commit) {
|
||||
logger.debug(`getCommitTree(${commit})`);
|
||||
|
|
|
@ -131,6 +131,13 @@ const options = [
|
|||
type: 'string',
|
||||
default: 'none',
|
||||
},
|
||||
{
|
||||
name: 'automergeType',
|
||||
description:
|
||||
'How to automerge - "branch-merge-commit", "branch-push" or "pr". Branch support is GitHub-only',
|
||||
type: 'string',
|
||||
default: 'pr',
|
||||
},
|
||||
// String templates
|
||||
{
|
||||
name: 'branchName',
|
||||
|
|
|
@ -79,12 +79,16 @@ function determineUpgrades(dep, currentVersion, config) {
|
|||
? 'major'
|
||||
: 'minor';
|
||||
const changeLogToVersion = newVersion;
|
||||
const automergeEnabled =
|
||||
config.automerge === 'any' ||
|
||||
(config.automerge === 'minor' && upgradeType === 'minor');
|
||||
allUpgrades[upgradeKey] = {
|
||||
upgradeType,
|
||||
newVersion,
|
||||
newVersionMajor,
|
||||
changeLogFromVersion,
|
||||
changeLogToVersion,
|
||||
automergeEnabled,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
|
@ -16,6 +16,18 @@ async function getParentBranch(branchName, config) {
|
|||
return undefined;
|
||||
}
|
||||
logger.debug(`${branchName} already exists`);
|
||||
// Check if needs rebasing
|
||||
if (
|
||||
(config.automergeEnabled && config.automergeType === 'branch-push') ||
|
||||
config.rebaseStalePrs
|
||||
) {
|
||||
const isBranchStale = await config.api.isBranchStale(branchName);
|
||||
if (isBranchStale) {
|
||||
logger.debug(`Branch ${branchName} is stale and needs rebasing`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for existing PR
|
||||
const pr = await config.api.getBranchPr(branchName);
|
||||
// Decide if we need to rebase
|
||||
|
@ -35,17 +47,6 @@ async function getParentBranch(branchName, config) {
|
|||
// Don't do anything different, but warn
|
||||
logger.verbose(`Cannot rebase branch ${branchName}`);
|
||||
}
|
||||
if (pr.isStale && config.rebaseStalePrs) {
|
||||
logger.verbose(`Existing PR for ${branchName} is stale`);
|
||||
if (pr.canRebase) {
|
||||
// Only supported by GitHub
|
||||
// Setting parentBranch back to undefined means that we'll use the default branch
|
||||
logger.debug(`Rebasing branch ${branchName}`);
|
||||
return undefined;
|
||||
}
|
||||
// Don't do anything different, but warn
|
||||
logger.verbose(`Cannot rebase branch ${branchName}`);
|
||||
}
|
||||
logger.debug(`Existing ${branchName} does not need rebasing`);
|
||||
return branchName;
|
||||
}
|
||||
|
@ -156,8 +157,34 @@ async function ensureBranch(upgrades) {
|
|||
commitMessage,
|
||||
parentBranch
|
||||
);
|
||||
} else {
|
||||
logger.debug(`No files to commit to branch ${branchName}`);
|
||||
}
|
||||
if (!api.branchExists(branchName)) {
|
||||
// Return now if no branch exists
|
||||
return false;
|
||||
}
|
||||
const config = upgrades[0];
|
||||
if (config.automergeEnabled === false || config.automergeType === 'pr') {
|
||||
// No branch automerge
|
||||
return true;
|
||||
}
|
||||
logger.debug(`No files to commit to branch ${branchName}`);
|
||||
return api.branchExists(branchName);
|
||||
logger.debug('Checking if we can automerge branch');
|
||||
const branchStatus = await api.getBranchStatus(branchName);
|
||||
if (branchStatus === 'success') {
|
||||
logger.info(`Automerging branch ${branchName}`);
|
||||
try {
|
||||
await api.mergeBranch(branchName, config.automergeType);
|
||||
} catch (err) {
|
||||
logger.error(`Failed to automerge branch ${branchName}`);
|
||||
logger.debug(JSON.stringify(err));
|
||||
throw err;
|
||||
}
|
||||
} else {
|
||||
logger.debug(
|
||||
`Branch status is "${branchStatus}" - skipping branch automerge`
|
||||
);
|
||||
}
|
||||
// Return true as branch exists
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -15,10 +15,19 @@ async function ensurePr(upgrades) {
|
|||
logger.debug('Ensuring PR');
|
||||
|
||||
const branchName = handlebars.compile(config.branchName)(config);
|
||||
const branchStatus = await config.api.getBranchStatus(branchName);
|
||||
|
||||
// Only create a PR if a branch automerge has failed
|
||||
if (config.automergeEnabled && config.automergeType.startsWith('branch')) {
|
||||
logger.debug(`Branch is configured for branch automerge`);
|
||||
if (branchStatus === 'failed') {
|
||||
logger.debug(`Branch tests failed, so will create PR`);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (config.prCreation === 'status-success') {
|
||||
logger.debug('Checking branch combined status');
|
||||
const branchStatus = await config.api.getBranchStatus(branchName);
|
||||
if (branchStatus !== 'success') {
|
||||
logger.debug(`Branch status is "${branchStatus}" - not creating PR`);
|
||||
return null;
|
||||
|
@ -26,7 +35,6 @@ async function ensurePr(upgrades) {
|
|||
logger.debug('Branch status success');
|
||||
} else if (config.prCreation === 'not-pending') {
|
||||
logger.debug('Checking branch combined status');
|
||||
const branchStatus = await config.api.getBranchStatus(branchName);
|
||||
if (branchStatus === 'pending' || branchStatus === 'running') {
|
||||
logger.debug(`Branch status is "${branchStatus}" - not creating PR`);
|
||||
return null;
|
||||
|
@ -74,21 +82,18 @@ async function ensurePr(upgrades) {
|
|||
if (config.labels.length > 0) {
|
||||
await config.api.addLabels(pr.number, config.labels);
|
||||
}
|
||||
// Don't assign or review if automerging
|
||||
if (
|
||||
config.automerge === 'none' ||
|
||||
(config.automerge === 'minor' && config.upgradeType !== 'minor')
|
||||
) {
|
||||
// Skip assign and review if automerging PR
|
||||
if (config.automergeEnabled && config.automergeType === 'pr') {
|
||||
logger.debug(
|
||||
`Skipping assignees and reviewers as automerge=${config.automerge}`
|
||||
);
|
||||
} else {
|
||||
if (config.assignees.length > 0) {
|
||||
await config.api.addAssignees(pr.number, config.assignees);
|
||||
}
|
||||
if (config.reviewers.length > 0) {
|
||||
await config.api.addReviewers(pr.number, config.reviewers);
|
||||
}
|
||||
} else {
|
||||
logger.debug(
|
||||
`Skipping assignees and reviewers as automerge=${config.automerge}`
|
||||
);
|
||||
}
|
||||
logger.info(`Created ${pr.displayNumber}`);
|
||||
return pr;
|
||||
|
@ -100,10 +105,7 @@ async function ensurePr(upgrades) {
|
|||
|
||||
async function checkAutoMerge(pr, config) {
|
||||
logger.debug(`Checking #${pr.number} for automerge`);
|
||||
if (
|
||||
config.automerge === 'any' ||
|
||||
(config.automerge === 'minor' && config.upgradeType === 'minor')
|
||||
) {
|
||||
if (config.automergeEnabled && config.automergeType === 'pr') {
|
||||
logger.verbose('PR is configured for automerge');
|
||||
logger.debug(JSON.stringify(pr));
|
||||
// Return if PR not ready for automerge
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"test-dirty": "git diff --exit-code",
|
||||
"test": "npm run lint && npm run jest",
|
||||
"transpile": "rimraf dist && mkdirp dist && babel lib --out-dir dist",
|
||||
"update-docs": "bash bin/update-docs.sh"
|
||||
"update-docs": "npm run transpile && bash bin/update-docs.sh"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -771,6 +771,177 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-merge-commit merge 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo",
|
||||
],
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/master",
|
||||
],
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/master",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-merge-commit merge 2`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-merge-commit merge 3`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo/merges",
|
||||
Object {
|
||||
"body": Object {
|
||||
"base": "master",
|
||||
"head": "thebranchname",
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-merge-commit merge 4`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-merge-commit merge 5`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/thebranchname",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-push merge 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo",
|
||||
],
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/master",
|
||||
],
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/thebranchname",
|
||||
],
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/master",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-push merge 2`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/master",
|
||||
Object {
|
||||
"body": Object {
|
||||
"sha": "1235",
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-push merge 3`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-push merge 4`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should perform a branch-push merge 5`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/thebranchname",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-merge-commit throws 1`] = `[Error: branch-push failed]`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-merge-commit throws 2`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo",
|
||||
],
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/master",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-merge-commit throws 3`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-merge-commit throws 4`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo/merges",
|
||||
Object {
|
||||
"body": Object {
|
||||
"base": "master",
|
||||
"head": "thebranchname",
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-merge-commit throws 5`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-merge-commit throws 6`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-push merge throws 1`] = `[Error: branch-push failed]`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-push merge throws 2`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo",
|
||||
],
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/master",
|
||||
],
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/thebranchname",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-push merge throws 3`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/master",
|
||||
Object {
|
||||
"body": Object {
|
||||
"sha": "1235",
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-push merge throws 4`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-push merge throws 5`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if branch-push merge throws 6`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if unknown merge type 1`] = `[Error: Unsupported branch merge type: wrong-merge-type]`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if unknown merge type 2`] = `
|
||||
Array [
|
||||
Array [
|
||||
"repos/some/repo",
|
||||
],
|
||||
Array [
|
||||
"repos/some/repo/git/refs/heads/master",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if unknown merge type 3`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if unknown merge type 4`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if unknown merge type 5`] = `Array []`;
|
||||
|
||||
exports[`api/github mergeBranch(branchName, mergeType) should throw if unknown merge type 6`] = `Array []`;
|
||||
|
||||
exports[`api/github updatePr(prNo, title, body) should update the PR 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
|
|
|
@ -407,6 +407,52 @@ describe('api/github', () => {
|
|||
expect(err.message).toBe('Something went wrong');
|
||||
});
|
||||
});
|
||||
describe('isBranchStale(branchName)', () => {
|
||||
it('should return false if same SHA as master', async () => {
|
||||
await initRepo('some/repo', 'token');
|
||||
// getBranchCommit
|
||||
ghGot.mockImplementationOnce(() => ({
|
||||
body: {
|
||||
object: {
|
||||
sha: '1235',
|
||||
},
|
||||
},
|
||||
}));
|
||||
// getCommitDetails - same as master
|
||||
ghGot.mockImplementationOnce(() => ({
|
||||
body: {
|
||||
parents: [
|
||||
{
|
||||
sha: '1234',
|
||||
},
|
||||
],
|
||||
},
|
||||
}));
|
||||
expect(await github.isBranchStale('thebranchname')).toBe(false);
|
||||
});
|
||||
it('should return true if SHA different from master', async () => {
|
||||
await initRepo('some/repo', 'token');
|
||||
// getBranchCommit
|
||||
ghGot.mockImplementationOnce(() => ({
|
||||
body: {
|
||||
object: {
|
||||
sha: '1235',
|
||||
},
|
||||
},
|
||||
}));
|
||||
// getCommitDetails - different
|
||||
ghGot.mockImplementationOnce(() => ({
|
||||
body: {
|
||||
parents: [
|
||||
{
|
||||
sha: '12345678',
|
||||
},
|
||||
],
|
||||
},
|
||||
}));
|
||||
expect(await github.isBranchStale('thebranchname')).toBe(true);
|
||||
});
|
||||
});
|
||||
describe('getBranchPr(branchName)', () => {
|
||||
it('should return null if no PR exists', async () => {
|
||||
await initRepo('some/repo', 'token');
|
||||
|
@ -460,6 +506,112 @@ describe('api/github', () => {
|
|||
expect(res).toEqual(false);
|
||||
});
|
||||
});
|
||||
describe('mergeBranch(branchName, mergeType)', () => {
|
||||
it('should perform a branch-push merge', async () => {
|
||||
await initRepo('some/repo', 'token');
|
||||
// getBranchCommit
|
||||
ghGot.mockImplementationOnce(() => ({
|
||||
body: {
|
||||
object: {
|
||||
sha: '1235',
|
||||
},
|
||||
},
|
||||
}));
|
||||
ghGot.patch.mockImplementationOnce();
|
||||
// getBranchCommit
|
||||
ghGot.mockImplementationOnce(() => ({
|
||||
body: {
|
||||
object: {
|
||||
sha: '1235',
|
||||
},
|
||||
},
|
||||
}));
|
||||
// deleteBranch
|
||||
ghGot.delete.mockImplementationOnce();
|
||||
await github.mergeBranch('thebranchname', 'branch-push');
|
||||
expect(ghGot.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.patch.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.post.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.put.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.delete.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
it('should throw if branch-push merge throws', async () => {
|
||||
await initRepo('some/repo', 'token');
|
||||
// getBranchCommit
|
||||
ghGot.mockImplementationOnce(() => ({
|
||||
body: {
|
||||
object: {
|
||||
sha: '1235',
|
||||
},
|
||||
},
|
||||
}));
|
||||
ghGot.patch.mockImplementationOnce(() => {
|
||||
throw new Error('branch-push failed');
|
||||
});
|
||||
let e;
|
||||
try {
|
||||
await github.mergeBranch('thebranchname', 'branch-push');
|
||||
} catch (err) {
|
||||
e = err;
|
||||
}
|
||||
expect(e).toMatchSnapshot();
|
||||
expect(ghGot.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.patch.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.post.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.put.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.delete.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
it('should perform a branch-merge-commit merge', async () => {
|
||||
await initRepo('some/repo', 'token');
|
||||
// getBranchCommit
|
||||
ghGot.mockImplementationOnce(() => ({
|
||||
body: {
|
||||
object: {
|
||||
sha: '1235',
|
||||
},
|
||||
},
|
||||
}));
|
||||
await github.mergeBranch('thebranchname', 'branch-merge-commit');
|
||||
expect(ghGot.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.patch.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.post.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.put.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.delete.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
it('should throw if branch-merge-commit throws', async () => {
|
||||
await initRepo('some/repo', 'token');
|
||||
ghGot.post.mockImplementationOnce(() => {
|
||||
throw new Error('branch-push failed');
|
||||
});
|
||||
let e;
|
||||
try {
|
||||
await github.mergeBranch('thebranchname', 'branch-merge-commit');
|
||||
} catch (err) {
|
||||
e = err;
|
||||
}
|
||||
expect(e).toMatchSnapshot();
|
||||
expect(ghGot.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.patch.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.post.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.put.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.delete.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
it('should throw if unknown merge type', async () => {
|
||||
await initRepo('some/repo', 'token');
|
||||
let e;
|
||||
try {
|
||||
await github.mergeBranch('thebranchname', 'wrong-merge-type');
|
||||
} catch (err) {
|
||||
e = err;
|
||||
}
|
||||
expect(e).toMatchSnapshot();
|
||||
expect(ghGot.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.patch.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.post.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.put.mock.calls).toMatchSnapshot();
|
||||
expect(ghGot.delete.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
describe('addAssignees(issueNo, assignees)', () => {
|
||||
it('should add the given assignees to the issue', async () => {
|
||||
await initRepo('some/repo', 'token');
|
||||
|
@ -708,6 +860,14 @@ describe('api/github', () => {
|
|||
},
|
||||
},
|
||||
}));
|
||||
// getBranchCommit
|
||||
ghGot.mockImplementationOnce(() => ({
|
||||
body: {
|
||||
object: {
|
||||
sha: '1235',
|
||||
},
|
||||
},
|
||||
}));
|
||||
return github.initRepo(...args);
|
||||
}
|
||||
await guessInitRepo('some/repo', 'token');
|
||||
|
@ -723,7 +883,6 @@ describe('api/github', () => {
|
|||
await github.mergePr(pr);
|
||||
expect(ghGot.put.mock.calls).toHaveLength(1);
|
||||
expect(ghGot.delete.mock.calls).toHaveLength(1);
|
||||
expect(ghGot.mock.calls).toHaveLength(3);
|
||||
});
|
||||
it('should try squash after rebase', async () => {
|
||||
const pr = {
|
||||
|
@ -738,7 +897,6 @@ describe('api/github', () => {
|
|||
await github.mergePr(pr);
|
||||
expect(ghGot.put.mock.calls).toHaveLength(2);
|
||||
expect(ghGot.delete.mock.calls).toHaveLength(1);
|
||||
expect(ghGot.mock.calls).toHaveLength(3);
|
||||
});
|
||||
it('should try merge after squash', async () => {
|
||||
const pr = {
|
||||
|
@ -756,7 +914,6 @@ describe('api/github', () => {
|
|||
await github.mergePr(pr);
|
||||
expect(ghGot.put.mock.calls).toHaveLength(3);
|
||||
expect(ghGot.delete.mock.calls).toHaveLength(1);
|
||||
expect(ghGot.mock.calls).toHaveLength(3);
|
||||
});
|
||||
it('should give up', async () => {
|
||||
const pr = {
|
||||
|
@ -777,7 +934,6 @@ describe('api/github', () => {
|
|||
await github.mergePr(pr);
|
||||
expect(ghGot.put.mock.calls).toHaveLength(3);
|
||||
expect(ghGot.delete.mock.calls).toHaveLength(0);
|
||||
expect(ghGot.mock.calls).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
describe('getFile(filePatch, branchName)', () => {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) disables major release separation (major) 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.4.4",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -15,6 +16,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) disables major release separation (minor) 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.0.0",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -27,6 +29,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) ignores pinning for ranges when other upgrade exists 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.9.7",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -49,6 +52,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) returns both updates if automerging minor 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": true,
|
||||
"changeLogFromVersion": "0.4.4",
|
||||
"changeLogToVersion": "0.9.7",
|
||||
"newVersion": "0.9.7",
|
||||
|
@ -56,6 +60,7 @@ Array [
|
|||
"upgradeType": "minor",
|
||||
},
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.4.4",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -68,6 +73,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) returns only one update if automerging any 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": true,
|
||||
"changeLogFromVersion": "0.4.4",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -80,6 +86,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) returns only one update if grouping 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.4.4",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -92,6 +99,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) should allow unstable versions if the current version is unstable 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.0.0-beta",
|
||||
"changeLogToVersion": "1.1.0-beta",
|
||||
"newVersion": "1.1.0-beta",
|
||||
|
@ -104,6 +112,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) should treat zero zero caret ranges as pinned 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.0.34",
|
||||
"changeLogToVersion": "0.0.35",
|
||||
"isRange": true,
|
||||
|
@ -117,6 +126,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) supports > latest versions if configured 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.4.1",
|
||||
"changeLogToVersion": "2.0.1",
|
||||
"newVersion": "2.0.1",
|
||||
|
@ -139,6 +149,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) supports future versions if configured 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.4.1",
|
||||
"changeLogToVersion": "2.0.3",
|
||||
"newVersion": "2.0.3",
|
||||
|
@ -151,6 +162,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) supports minor and major upgrades for ranged versions 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.4.4",
|
||||
"changeLogToVersion": "0.9.7",
|
||||
"newVersion": "0.9.7",
|
||||
|
@ -158,6 +170,7 @@ Array [
|
|||
"upgradeType": "minor",
|
||||
},
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.4.4",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -170,6 +183,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) supports minor and major upgrades for tilde ranges 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.4.4",
|
||||
"changeLogToVersion": "0.9.7",
|
||||
"newVersion": "0.9.7",
|
||||
|
@ -177,6 +191,7 @@ Array [
|
|||
"upgradeType": "minor",
|
||||
},
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.4.4",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -189,6 +204,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades .x major ranges without pinning 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.9.7",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"isRange": true,
|
||||
|
@ -202,6 +218,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades .x minor ranges 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.3.0",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -214,6 +231,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades .x minor ranges without pinning 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.3.0",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"isRange": true,
|
||||
|
@ -227,6 +245,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades less than equal ranges without pinning 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.7.2",
|
||||
"changeLogToVersion": "0.9.7",
|
||||
"isRange": true,
|
||||
|
@ -235,6 +254,7 @@ Array [
|
|||
"upgradeType": "minor",
|
||||
},
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.7.2",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"isRange": true,
|
||||
|
@ -248,6 +268,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades minor ranged versions 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.0.1",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -260,6 +281,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades multiple caret ranges without pinning 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.7.2",
|
||||
"changeLogToVersion": "0.9.7",
|
||||
"isRange": true,
|
||||
|
@ -268,6 +290,7 @@ Array [
|
|||
"upgradeType": "minor",
|
||||
},
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.7.2",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"isRange": true,
|
||||
|
@ -281,6 +304,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades multiple tilde ranges without pinning 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.7.2",
|
||||
"changeLogToVersion": "0.9.7",
|
||||
"isRange": true,
|
||||
|
@ -289,6 +313,7 @@ Array [
|
|||
"upgradeType": "minor",
|
||||
},
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.7.2",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"isRange": true,
|
||||
|
@ -302,6 +327,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades shorthand major ranges without pinning 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "0.9.7",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"isRange": true,
|
||||
|
@ -315,6 +341,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades shorthand minor ranges without pinning 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.3.0",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"isRange": true,
|
||||
|
@ -328,6 +355,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades tilde ranges 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.3.0",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"newVersion": "1.4.1",
|
||||
|
@ -340,6 +368,7 @@ Array [
|
|||
exports[`helpers/versions .determineUpgrades(dep, currentVersion, defaultConfig) upgrades tilde ranges without pinning 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"automergeEnabled": false,
|
||||
"changeLogFromVersion": "1.3.0",
|
||||
"changeLogToVersion": "1.4.1",
|
||||
"isRange": true,
|
||||
|
|
43
test/workers/__snapshots__/branch.spec.js.snap
Normal file
43
test/workers/__snapshots__/branch.spec.js.snap
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`workers/branch ensureBranch(config) automerges successful branches 1`] = `
|
||||
Object {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"renovate/dummy-1.x",
|
||||
"branch-push",
|
||||
],
|
||||
],
|
||||
"instances": Array [
|
||||
Object {
|
||||
"branchExists": [Function],
|
||||
"commitFilesToBranch": [Function],
|
||||
"getBranchStatus": [Function],
|
||||
"getFileContent": [Function],
|
||||
"mergeBranch": [Function],
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`workers/branch ensureBranch(config) throws if automerge throws 1`] = `[Error: automerge failed]`;
|
||||
|
||||
exports[`workers/branch ensureBranch(config) throws if automerge throws 2`] = `
|
||||
Object {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"renovate/dummy-1.x",
|
||||
"branch-push",
|
||||
],
|
||||
],
|
||||
"instances": Array [
|
||||
Object {
|
||||
"branchExists": [Function],
|
||||
"commitFilesToBranch": [Function],
|
||||
"getBranchStatus": [Function],
|
||||
"getFileContent": [Function],
|
||||
"mergeBranch": [Function],
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
|
@ -16,6 +16,8 @@ describe('workers/branch', () => {
|
|||
api: {
|
||||
branchExists: jest.fn(() => true),
|
||||
getBranchPr: jest.fn(),
|
||||
getBranchStatus: jest.fn(),
|
||||
isBranchStale: jest.fn(() => false),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -31,7 +33,7 @@ describe('workers/branch', () => {
|
|||
branchName
|
||||
);
|
||||
});
|
||||
it('returns false if does not need rebaseing', async () => {
|
||||
it('returns branchName if does not need rebaseing', async () => {
|
||||
config.api.getBranchPr.mockReturnValue({
|
||||
isUnmergeable: false,
|
||||
});
|
||||
|
@ -39,7 +41,7 @@ describe('workers/branch', () => {
|
|||
branchName
|
||||
);
|
||||
});
|
||||
it('returns false if unmergeable and cannot rebase', async () => {
|
||||
it('returns branchName if unmergeable and cannot rebase', async () => {
|
||||
config.api.getBranchPr.mockReturnValue({
|
||||
isUnmergeable: true,
|
||||
canRebase: false,
|
||||
|
@ -48,7 +50,7 @@ describe('workers/branch', () => {
|
|||
branchName
|
||||
);
|
||||
});
|
||||
it('returns true if unmergeable and can rebase', async () => {
|
||||
it('returns undefined if unmergeable and can rebase', async () => {
|
||||
config.api.getBranchPr.mockReturnValue({
|
||||
isUnmergeable: true,
|
||||
canRebase: true,
|
||||
|
@ -57,35 +59,17 @@ describe('workers/branch', () => {
|
|||
undefined
|
||||
);
|
||||
});
|
||||
it('returns false if stale but not configured to rebase', async () => {
|
||||
config.api.getBranchPr.mockReturnValue({
|
||||
isUnmergeable: false,
|
||||
isStale: true,
|
||||
canRebase: true,
|
||||
});
|
||||
config.rebaseStalePrs = false;
|
||||
it('returns branchName if automerge branch-push and not stale', async () => {
|
||||
config.automergeEnabled = true;
|
||||
config.automergeType = 'branch-push';
|
||||
expect(await branchWorker.getParentBranch(branchName, config)).toBe(
|
||||
branchName
|
||||
);
|
||||
});
|
||||
it('returns false if stale but cannot rebase', async () => {
|
||||
config.api.getBranchPr.mockReturnValueOnce({
|
||||
isUnmergeable: false,
|
||||
isStale: true,
|
||||
canRebase: false,
|
||||
});
|
||||
config.rebaseStalePrs = true;
|
||||
expect(await branchWorker.getParentBranch(branchName, config)).toBe(
|
||||
branchName
|
||||
);
|
||||
});
|
||||
it('returns true if stale and can rebase', async () => {
|
||||
config.api.getBranchPr.mockReturnValueOnce({
|
||||
isUnmergeable: false,
|
||||
isStale: true,
|
||||
canRebase: true,
|
||||
});
|
||||
config.rebaseStalePrs = true;
|
||||
it('returns undefined if automerge branch-push and stale', async () => {
|
||||
config.automergeEnabled = true;
|
||||
config.automergeType = 'branch-push';
|
||||
config.api.isBranchStale.mockReturnValueOnce(true);
|
||||
expect(await branchWorker.getParentBranch(branchName, config)).toBe(
|
||||
undefined
|
||||
);
|
||||
|
@ -105,15 +89,17 @@ describe('workers/branch', () => {
|
|||
config.api.branchExists = jest.fn();
|
||||
config.api.commitFilesToBranch = jest.fn();
|
||||
config.api.getFileContent.mockReturnValueOnce('old content');
|
||||
config.api.getBranchStatus = jest.fn();
|
||||
config.depName = 'dummy';
|
||||
config.currentVersion = '1.0.0';
|
||||
config.newVersion = '1.1.0';
|
||||
config.newVersionMajor = 1;
|
||||
});
|
||||
it('returns if new content matches old', async () => {
|
||||
branchWorker.getParentBranch.mockReturnValueOnce('dummy branch');
|
||||
packageJsonHelper.setNewValue.mockReturnValueOnce('old content');
|
||||
config.api.branchExists.mockReturnValueOnce(false);
|
||||
await branchWorker.ensureBranch([config]);
|
||||
expect(await branchWorker.ensureBranch([config])).toBe(false);
|
||||
expect(branchWorker.getParentBranch.mock.calls.length).toBe(1);
|
||||
expect(packageJsonHelper.setNewValue.mock.calls.length).toBe(1);
|
||||
expect(npmHelper.getLockFile.mock.calls.length).toBe(0);
|
||||
|
@ -122,13 +108,86 @@ describe('workers/branch', () => {
|
|||
it('commits one file if no yarn lock or package-lock.json found', async () => {
|
||||
branchWorker.getParentBranch.mockReturnValueOnce('dummy branch');
|
||||
packageJsonHelper.setNewValue.mockReturnValueOnce('new content');
|
||||
await branchWorker.ensureBranch([config]);
|
||||
config.api.branchExists.mockReturnValueOnce(true);
|
||||
expect(await branchWorker.ensureBranch([config])).toBe(true);
|
||||
expect(branchWorker.getParentBranch.mock.calls.length).toBe(1);
|
||||
expect(packageJsonHelper.setNewValue.mock.calls.length).toBe(1);
|
||||
expect(npmHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(yarnHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(config.api.commitFilesToBranch.mock.calls[0][1].length).toBe(1);
|
||||
});
|
||||
it('returns true if automerging pr', async () => {
|
||||
branchWorker.getParentBranch.mockReturnValueOnce('dummy branch');
|
||||
packageJsonHelper.setNewValue.mockReturnValueOnce('new content');
|
||||
config.api.branchExists.mockReturnValueOnce(true);
|
||||
config.automergeEnabled = true;
|
||||
config.automergeType = 'pr';
|
||||
expect(await branchWorker.ensureBranch([config])).toBe(true);
|
||||
expect(branchWorker.getParentBranch.mock.calls.length).toBe(1);
|
||||
expect(packageJsonHelper.setNewValue.mock.calls.length).toBe(1);
|
||||
expect(npmHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(yarnHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(config.api.commitFilesToBranch.mock.calls[0][1].length).toBe(1);
|
||||
});
|
||||
it('automerges successful branches', async () => {
|
||||
branchWorker.getParentBranch.mockReturnValueOnce('dummy branch');
|
||||
packageJsonHelper.setNewValue.mockReturnValueOnce('new content');
|
||||
config.api.branchExists.mockReturnValueOnce(true);
|
||||
config.api.getBranchStatus.mockReturnValueOnce('success');
|
||||
config.api.mergeBranch = jest.fn();
|
||||
config.automergeEnabled = true;
|
||||
config.automergeType = 'branch-push';
|
||||
expect(await branchWorker.ensureBranch([config])).toBe(true);
|
||||
expect(branchWorker.getParentBranch.mock.calls.length).toBe(1);
|
||||
expect(config.api.getBranchStatus.mock.calls.length).toBe(1);
|
||||
expect(config.api.mergeBranch.mock).toMatchSnapshot();
|
||||
expect(packageJsonHelper.setNewValue.mock.calls.length).toBe(1);
|
||||
expect(npmHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(yarnHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(config.api.commitFilesToBranch.mock.calls[0][1].length).toBe(1);
|
||||
});
|
||||
it('skips automerge if status not success', async () => {
|
||||
branchWorker.getParentBranch.mockReturnValueOnce('dummy branch');
|
||||
packageJsonHelper.setNewValue.mockReturnValueOnce('new content');
|
||||
config.api.branchExists.mockReturnValueOnce(true);
|
||||
config.api.getBranchStatus.mockReturnValueOnce('pending');
|
||||
config.api.mergeBranch = jest.fn();
|
||||
config.automergeEnabled = true;
|
||||
config.automergeType = 'branch-push';
|
||||
expect(await branchWorker.ensureBranch([config])).toBe(true);
|
||||
expect(branchWorker.getParentBranch.mock.calls.length).toBe(1);
|
||||
expect(config.api.getBranchStatus.mock.calls.length).toBe(1);
|
||||
expect(config.api.mergeBranch.mock.calls.length).toBe(0);
|
||||
expect(packageJsonHelper.setNewValue.mock.calls.length).toBe(1);
|
||||
expect(npmHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(yarnHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(config.api.commitFilesToBranch.mock.calls[0][1].length).toBe(1);
|
||||
});
|
||||
it('throws if automerge throws', async () => {
|
||||
branchWorker.getParentBranch.mockReturnValueOnce('dummy branch');
|
||||
packageJsonHelper.setNewValue.mockReturnValueOnce('new content');
|
||||
config.api.branchExists.mockReturnValueOnce(true);
|
||||
config.api.getBranchStatus.mockReturnValueOnce('success');
|
||||
config.automergeEnabled = true;
|
||||
config.automergeType = 'branch-push';
|
||||
config.api.mergeBranch = jest.fn(() => {
|
||||
throw new Error('automerge failed');
|
||||
});
|
||||
let e;
|
||||
try {
|
||||
await branchWorker.ensureBranch([config]);
|
||||
} catch (err) {
|
||||
e = err;
|
||||
}
|
||||
expect(e).toMatchSnapshot();
|
||||
expect(branchWorker.getParentBranch.mock.calls.length).toBe(1);
|
||||
expect(config.api.getBranchStatus.mock.calls.length).toBe(1);
|
||||
expect(config.api.mergeBranch.mock).toMatchSnapshot();
|
||||
expect(packageJsonHelper.setNewValue.mock.calls.length).toBe(1);
|
||||
expect(npmHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(yarnHelper.getLockFile.mock.calls.length).toBe(1);
|
||||
expect(config.api.commitFilesToBranch.mock.calls[0][1].length).toBe(1);
|
||||
});
|
||||
it('commits two files if yarn lock found', async () => {
|
||||
branchWorker.getParentBranch.mockReturnValueOnce('dummy branch');
|
||||
yarnHelper.getLockFile.mockReturnValueOnce('non null response');
|
||||
|
|
|
@ -27,48 +27,33 @@ describe('workers/pr', () => {
|
|||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(config.api.mergePr.mock.calls.length).toBe(0);
|
||||
});
|
||||
it('should automerge if any and pr is mergeable', async () => {
|
||||
config.automerge = 'any';
|
||||
it('should automerge if enabled and pr is mergeable', async () => {
|
||||
config.automergeEnabled = true;
|
||||
pr.mergeable = true;
|
||||
config.api.getBranchStatus.mockReturnValueOnce('success');
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(config.api.mergePr.mock.calls.length).toBe(1);
|
||||
});
|
||||
it('should not automerge if any and pr is mergeable but branch status is not success', async () => {
|
||||
config.automerge = 'any';
|
||||
it('should not automerge if enabled and pr is mergeable but branch status is not success', async () => {
|
||||
config.automergeEnabled = true;
|
||||
pr.mergeable = true;
|
||||
config.api.getBranchStatus.mockReturnValueOnce('pending');
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(config.api.mergePr.mock.calls.length).toBe(0);
|
||||
});
|
||||
it('should not automerge if any and pr is mergeable but unstable', async () => {
|
||||
config.automerge = 'any';
|
||||
it('should not automerge if enabled and pr is mergeable but unstable', async () => {
|
||||
config.automergeEnabled = true;
|
||||
pr.mergeable = true;
|
||||
pr.mergeable_state = 'unstable';
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(config.api.mergePr.mock.calls.length).toBe(0);
|
||||
});
|
||||
it('should not automerge if any and pr is unmergeable', async () => {
|
||||
config.automerge = 'any';
|
||||
it('should not automerge if enabled and pr is unmergeable', async () => {
|
||||
config.automergeEnabled = true;
|
||||
pr.mergeable = false;
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(config.api.mergePr.mock.calls.length).toBe(0);
|
||||
});
|
||||
it('should automerge if minor and upgradeType is minor', async () => {
|
||||
config.automerge = 'minor';
|
||||
config.upgradeType = 'minor';
|
||||
pr.mergeable = true;
|
||||
config.api.getBranchStatus.mockReturnValueOnce('success');
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(config.api.mergePr.mock.calls.length).toBe(1);
|
||||
});
|
||||
it('should not automerge if minor and upgradeType is major', async () => {
|
||||
config.automerge = 'minor';
|
||||
config.upgradeType = 'major';
|
||||
pr.mergeable = true;
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(config.api.mergePr.mock.calls.length).toBe(0);
|
||||
});
|
||||
});
|
||||
describe('ensurePr(upgrades)', () => {
|
||||
let config;
|
||||
|
@ -77,6 +62,7 @@ describe('workers/pr', () => {
|
|||
config = Object.assign({}, defaultConfig);
|
||||
config.api = {
|
||||
createPr: jest.fn(() => ({ displayNumber: 'New Pull Request' })),
|
||||
getBranchStatus: jest.fn(),
|
||||
};
|
||||
existingPr = {
|
||||
title: 'Update dependency dummy to version 1.1.0',
|
||||
|
@ -150,44 +136,18 @@ describe('workers/pr', () => {
|
|||
expect(config.api.addAssignees.mock.calls.length).toBe(1);
|
||||
expect(config.api.addReviewers.mock.calls.length).toBe(1);
|
||||
});
|
||||
it('should not add assignees and reviewers to new PR if automerging any', async () => {
|
||||
it('should not add assignees and reviewers to new PR if automerging enabled', async () => {
|
||||
config.api.getBranchPr = jest.fn();
|
||||
config.api.addAssignees = jest.fn();
|
||||
config.api.addReviewers = jest.fn();
|
||||
config.assignees = ['bar'];
|
||||
config.reviewers = ['baz'];
|
||||
config.automerge = 'any';
|
||||
config.automergeEnabled = true;
|
||||
const pr = await prWorker.ensurePr([config]);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(config.api.addAssignees.mock.calls.length).toBe(0);
|
||||
expect(config.api.addReviewers.mock.calls.length).toBe(0);
|
||||
});
|
||||
it('should not add assignees and reviewers to new PR if automerging minor', async () => {
|
||||
config.api.getBranchPr = jest.fn();
|
||||
config.api.addAssignees = jest.fn();
|
||||
config.api.addReviewers = jest.fn();
|
||||
config.assignees = ['bar'];
|
||||
config.reviewers = ['baz'];
|
||||
config.upgradeType = 'minor';
|
||||
config.automerge = 'minor';
|
||||
const pr = await prWorker.ensurePr([config]);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(config.api.addAssignees.mock.calls.length).toBe(0);
|
||||
expect(config.api.addReviewers.mock.calls.length).toBe(0);
|
||||
});
|
||||
it('should add assignees and reviewers to new PR if automerging minor and its major', async () => {
|
||||
config.api.getBranchPr = jest.fn();
|
||||
config.api.addAssignees = jest.fn();
|
||||
config.api.addReviewers = jest.fn();
|
||||
config.assignees = ['bar'];
|
||||
config.reviewers = ['baz'];
|
||||
config.upgradeType = 'major';
|
||||
config.automerge = 'minor';
|
||||
const pr = await prWorker.ensurePr([config]);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(config.api.addAssignees.mock.calls.length).toBe(1);
|
||||
expect(config.api.addReviewers.mock.calls.length).toBe(1);
|
||||
});
|
||||
it('should return unmodified existing PR', async () => {
|
||||
config.depName = 'dummy';
|
||||
config.currentVersion = '1.0.0';
|
||||
|
@ -210,5 +170,20 @@ describe('workers/pr', () => {
|
|||
});
|
||||
expect(pr).toMatchObject(updatedPr);
|
||||
});
|
||||
it('should create PR if branch automerging failed', async () => {
|
||||
config.automergeEnabled = true;
|
||||
config.automergeType = 'branch-push';
|
||||
config.api.getBranchStatus.mockReturnValueOnce('failed');
|
||||
config.api.getBranchPr = jest.fn();
|
||||
const pr = await prWorker.ensurePr([config]);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should return null if branch automerging not failed', async () => {
|
||||
config.automergeEnabled = true;
|
||||
config.automergeType = 'branch-push';
|
||||
config.api.getBranchStatus.mockReturnValueOnce('pending');
|
||||
const pr = await prWorker.ensurePr([config]);
|
||||
expect(pr).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue