In order to bypass codeowner requirements when you have merge queue enabled, you need to jump through a few hoops. This is especially useful when you're in a repo with thousands of files, and 20+ teams, each with codeownership. I'm an admin, so I don't want to get approval just because I enabled a new eslint rule, and autofixed tons of files. However, if I simply admin merge, I don't get the benefit of having merge queue to catch race conditions... the PR goes directly into the target branch.
The following is the next best workaround. It's not the most ideal thing in the world, but what do you want from me?
- Create an app/bot with elevated permissions. Mine has god-ish permissions, so I'm not sure which exactly are required for this tbh.
- Create 2 rulesets. One with the majority of requirements (status checks, merge queue, etc.). The other exclusively for codeowner enablement.
- Make the app/bot your bypass actor for the codeowner ruleset, and set to "Exempt".
- Create a dispatchable workflow with a PR number input.
- Acquire a server-to-server token for the app to make some API calls
- First call is just a preliminary check to verify the "actor" permissions of the dispatch user are "admin":
const { data: permission } =
await octokit.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username,
});
return permission.permission === 'admin';- Lastly, use this API/graphql to enqueue your PR to merge queue on behalf of the app/bot.
const pr = await octokit.rest.pulls.get({
owner,
repo,
pull_number: prNumber,
});
if (pr.data.state !== 'open') {
throw new Error(`PR #${prNumber} is not open (state: ${pr.data.state})`);
}
// Use GraphQL to add PR to merge queue
const query = `
mutation EnqueuePullRequest($pullRequestId: ID!) {
enqueuePullRequest(input: {
pullRequestId: $pullRequestId,
expectedHeadOid: "${pr.data.head.sha}"
}) {
mergeQueueEntry {
id
position
state
}
}
}
`;
await octokit
.graphql(query, {
pullRequestId: pr.data.node_id,
})
.catch((error) => {
throw new Error(
`Failed to send PR #${prNumber} to merge queue: ${error.message}`,
);
});To be honest, this seems like something that should come out of the box with Github. They introduced all these great new features, but they simply don't work well together. With any luck, this gist will be obsolete in another 5 years.