Skip to content

Commit

Permalink
Add merge modes and refactor methods
Browse files Browse the repository at this point in the history
  • Loading branch information
0x2b3bfa0 authored Apr 4, 2022
1 parent 556138d commit be39f94
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 75 deletions.
7 changes: 4 additions & 3 deletions bin/cml/pr.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ exports.builder = (yargs) =>
description: 'Output in markdown format [](url).'
},
autoMerge: {
type: 'boolean',
description:
'Mark the PR/MR for automatic merging after tests pass (unsupported by Bitbucket).'
type: 'string',
choices: ['merge', 'rebase', 'squash'],
coerce: (val) => (val === '' ? 'merge' : val),
description: 'Mark the PR/MR for automatic merging after tests pass.'
},
remote: {
type: 'string',
Expand Down
4 changes: 2 additions & 2 deletions bin/cml/pr.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ describe('CML e2e', () => {
--log Maximum log level
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
--md Output in markdown format [](url). [boolean]
--auto-merge Mark the PR/MR for automatic merging after tests pass
(unsupported by Bitbucket). [boolean]
--auto-merge Mark the PR/MR for automatic merging after tests pass.
[string] [choices: \\"merge\\", \\"rebase\\", \\"squash\\"]
--remote Sets git remote. [string] [default: \\"origin\\"]
--user-email Sets git user email. [string] [default: \\"[email protected]\\"]
--user-name Sets git user name. [string] [default: \\"Olivaw[bot]\\"]
Expand Down
39 changes: 26 additions & 13 deletions src/drivers/bitbucket_cloud.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,32 +128,45 @@ class BitbucketCloud {
}
}
});
const endpoint = `/repositories/${projectPath}/pullrequests`;
const endpoint = `/repositories/${projectPath}/pullrequests/`;
const {
id,
links: {
html: { href }
}
} = await this.request({
method: 'POST',
endpoint: `${endpoint}/`,
endpoint,
body
});

if (autoMerge) {
winston.warn(
'Auto-merge is unsupported by Bitbucket Cloud; see https://jira.atlassian.com/browse/BCLOUD-14286. Trying to merge immediately...'
);
await this.request({
method: 'POST',
endpoint: `${endpoint}/${id}/merge`,
body
});
}

if (autoMerge)
await this.prAutoMerge({ pullRequestId: id, mergeMode: autoMerge });
return href;
}

async prAutoMerge({ pullRequestId, mergeMode, mergeMessage = undefined }) {
winston.warn(
'Auto-merge is unsupported by Bitbucket Cloud; see https://jira.atlassian.com/browse/BCLOUD-14286. Trying to merge immediately...'
);
const { projectPath } = this;
const endpoint = `/repositories/${projectPath}/pullrequests/${pullRequestId}/merge`;
const body = JSON.stringify({
merge_strategy: {
merge: 'merge_commit',
rebase: 'fast_forward',
squash: 'squash'
}[mergeMode],
close_source_branch: true,
message: mergeMessage
});
await this.request({
method: 'POST',
endpoint,
body
});
}

async prCommentCreate(opts = {}) {
const { projectPath } = this;
const { report, prNumber } = opts;
Expand Down
88 changes: 56 additions & 32 deletions src/drivers/github.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ class Github {
const { pulls } = octokit(this.token, this.repo);

const {
data: { html_url: htmlUrl, node_id: nodeId, number }
data: { html_url: htmlUrl, number }
} = await pulls.create({
owner,
repo,
Expand All @@ -363,17 +363,12 @@ class Github {
body
});

if (autoMerge) {
try {
await this.prAutoMerge({ pullRequestId: nodeId, base });
} catch ({ message }) {
winston.warn(
`Failed to enable auto-merge: ${message}. Trying to merge immediately...`
);
await pulls.merge({ owner, repo, pull_number: number });
}
}

if (autoMerge)
await this.prAutoMerge({
pullRequestId: number,
mergeMode: autoMerge,
base
});
return htmlUrl;
}

Expand Down Expand Up @@ -403,45 +398,74 @@ class Github {
* @param {{ pullRequestId: number, base: string }} param0
* @returns {Promise<void>}
*/
async prAutoMerge({ pullRequestId, base }) {
async prAutoMerge({
pullRequestId,
mergeMode,
mergeMessage = undefined,
base
}) {
const octo = octokit(this.token, this.repo);
const graphql = withCustomRequest(octo.request);

const { owner, repo } = this.ownerRepo();
const [commitHeadline, commitBody] =
mergeMessage === undefined ? [] : mergeMessage.split(/\n\n(.*)/s);
const {
data: { node_id: nodeId }
} = await octo.pulls.get({ owner, repo, pull_number: pullRequestId });
try {
await graphql(
`
mutation autoMerge($pullRequestId: ID!) {
mutation autoMerge(
$pullRequestId: ID!
$mergeMethod: PullRequestMergeMethod
$commitHeadline: String
$commitBody: String
) {
enablePullRequestAutoMerge(
input: { pullRequestId: $pullRequestId }
input: {
pullRequestId: $pullRequestId
mergeMethod: $mergeMethod
commitHeadline: $commitHeadline
commitBody: $commitBody
}
) {
clientMutationId
}
}
`,
{
pullRequestId
pullRequestId: nodeId,
mergeMethod: mergeMode.toUpperCase(),
commitHeadline,
commitBody
}
);
} catch (error) {
} catch (err) {
if (
error.message.includes("Can't enable auto-merge for this pull request")
) {
const { owner, repo } = this.ownerRepo();
const settingsUrl = `https://github.com/${owner}/${repo}/settings`;

const isProtected = await this.isProtected({ branch: base });
if (!isProtected) {
throw new Error(
`Enabling Auto-Merge failed. Please set up branch protection and add "required status checks" for branch '${base}': ${settingsUrl}/branches`
);
}
!err.message.includes("Can't enable auto-merge for this pull request")
)
throw err;

const settingsUrl = `https://github.com/${owner}/${repo}/settings`;

throw new Error(
`Enabling Auto-Merge failed. Enable the feature in your repository settings: ${settingsUrl}#merge_types_auto_merge`
if (!(await this.isProtected({ branch: base }))) {
winston.warn(
`Failed to enable auto-merge: Set up branch protection and add "required status checks" for branch '${base}': ${settingsUrl}/branches. Trying to merge immediately...`
);
} else {
winston.warn(
`Failed to enable auto-merge: Enable the feature in your repository settings: ${settingsUrl}#merge_types_auto_merge. Trying to merge immediately...`
);
}

throw error;
await octo.pulls.merge({
owner,
repo,
pull_number: pullRequestId,
merge_method: mergeMode,
commit_title: commitHeadline,
commit_message: commitBody
});
}
}

Expand Down
58 changes: 33 additions & 25 deletions src/drivers/gitlab.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,41 +272,49 @@ class Gitlab {
body
});

if (autoMerge) {
try {
await this.prAutoMerge({ mergeRequestId: iid });
} catch ({ message }) {
winston.warn(
`Failed to enable auto-merge: ${message}. Trying to merge immediately...`
);
await this.prAutoMerge({
mergeRequestId: iid,
whenPipelineSucceeds: false
});
}
}

if (autoMerge)
await this.prAutoMerge({ pullRequestId: iid, mergeMode: autoMerge });
return url;
}

/**
* @param {{ mergeRequestId: string }} param0
* @param {{ pullRequestId: string }} param0
* @returns {Promise<void>}
*/
async prAutoMerge({ mergeRequestId, whenPipelineSucceeds = true }) {
async prAutoMerge({ pullRequestId, mergeMode, mergeMessage = undefined }) {
if (mergeMode === 'rebase')
throw new Error(`Rebase auto-merge mode not implemented for GitLab`);

const projectPath = await this.projectPath();

const endpoint = `/projects/${projectPath}/merge_requests/${mergeRequestId}/merge`;
const endpoint = `/projects/${projectPath}/merge_requests/${pullRequestId}/merge`;
const body = new URLSearchParams();
body.append('merge_when_pipeline_succeeds', whenPipelineSucceeds);
body.set('merge_when_pipeline_succeeds', true);
body.set('squash', mergeMode === 'squash');
if (mergeMessage !== undefined)
body.set(`${mergeMode}_commit_message`, mergeMessage);

await backOff(() =>
this.request({
endpoint,
method: 'PUT',
body
})
);
try {
await backOff(() =>
this.request({
endpoint,
method: 'PUT',
body
})
);
} catch ({ message }) {
winston.warn(
`Failed to enable auto-merge: ${message}. Trying to merge immediately...`
);
body.set('merge_when_pipeline_succeeds', false);
await backOff(() =>
this.request({
endpoint,
method: 'PUT',
body
})
);
}
}

async prCommentCreate(opts = {}) {
Expand Down
1 change: 1 addition & 0 deletions test
Submodule test added at 7b3bea

0 comments on commit be39f94

Please sign in to comment.