feat(dev-infra): prevent attempting to merge draft, closed or merged pull requests (#41604)

During pull request validation, assert that the pull request is not in
draft mode, already merged or already closed.

PR Close #41604
This commit is contained in:
Joey Perrott 2021-04-13 14:12:32 -07:00 committed by Zach Arend
parent 1043aa42ad
commit a63cf7221b
3 changed files with 56 additions and 1 deletions

View File

@ -3379,6 +3379,15 @@ var PullRequestFailure = /** @class */ (function () {
PullRequestFailure.notMergeReady = function () { PullRequestFailure.notMergeReady = function () {
return new this("Not marked as merge ready."); return new this("Not marked as merge ready.");
}; };
PullRequestFailure.isDraft = function () {
return new this('Pull request is still in draft.');
};
PullRequestFailure.isClosed = function () {
return new this('Pull request is already closed.');
};
PullRequestFailure.isMerged = function () {
return new this('Pull request is already merged.');
};
PullRequestFailure.mismatchingTargetBranch = function (allowedBranches) { PullRequestFailure.mismatchingTargetBranch = function (allowedBranches) {
return new this("Pull request is set to wrong base branch. Please update the PR in the Github UI " + return new this("Pull request is set to wrong base branch. Please update the PR in the Github UI " +
("to one of the following branches: " + allowedBranches.join(', ') + ".")); ("to one of the following branches: " + allowedBranches.join(', ') + "."));
@ -3490,6 +3499,7 @@ function loadAndValidatePullRequest(_a, prNumber, ignoreNonFatalFailures) {
} }
commitsInPr = prData.commits.nodes.map(function (n) { return parseCommitMessage(n.commit.message); }); commitsInPr = prData.commits.nodes.map(function (n) { return parseCommitMessage(n.commit.message); });
try { try {
assertPendingState(prData);
assertChangesAllowForTargetLabel(commitsInPr, targetLabel, config); assertChangesAllowForTargetLabel(commitsInPr, targetLabel, config);
assertCorrectBreakingChangeLabeling(commitsInPr, labels, config); assertCorrectBreakingChangeLabeling(commitsInPr, labels, config);
} }
@ -3541,6 +3551,8 @@ function loadAndValidatePullRequest(_a, prNumber, ignoreNonFatalFailures) {
/* Graphql schema for the response body the requested pull request. */ /* Graphql schema for the response body the requested pull request. */
var PR_SCHEMA$2 = { var PR_SCHEMA$2 = {
url: typedGraphqlify.types.string, url: typedGraphqlify.types.string,
isDraft: typedGraphqlify.types.boolean,
state: typedGraphqlify.types.oneOf(['OPEN', 'MERGED', 'CLOSED']),
number: typedGraphqlify.types.number, number: typedGraphqlify.types.number,
// Only the last 100 commits from a pull request are obtained as we likely will never see a pull // Only the last 100 commits from a pull request are obtained as we likely will never see a pull
// requests with more than 100 commits. // requests with more than 100 commits.
@ -3646,6 +3658,18 @@ function assertCorrectBreakingChangeLabeling(commits, labels, config) {
throw PullRequestFailure.missingBreakingChangeCommit(); throw PullRequestFailure.missingBreakingChangeCommit();
} }
} }
/** Assert the pull request is pending, not closed, merged or in draft. */
function assertPendingState(pr) {
if (pr.isDraft) {
throw PullRequestFailure.isDraft();
}
switch (pr.state) {
case 'CLOSED':
throw PullRequestFailure.isClosed();
case 'MERGED':
throw PullRequestFailure.isMerged();
}
}
/** /**
* @license * @license

View File

@ -36,6 +36,18 @@ export class PullRequestFailure {
return new this(`Not marked as merge ready.`); return new this(`Not marked as merge ready.`);
} }
static isDraft() {
return new this('Pull request is still in draft.');
}
static isClosed() {
return new this('Pull request is already closed.');
}
static isMerged() {
return new this('Pull request is already merged.');
}
static mismatchingTargetBranch(allowedBranches: string[]) { static mismatchingTargetBranch(allowedBranches: string[]) {
return new this( return new this(
`Pull request is set to wrong base branch. Please update the PR in the Github UI ` + `Pull request is set to wrong base branch. Please update the PR in the Github UI ` +

View File

@ -82,6 +82,7 @@ export async function loadAndValidatePullRequest(
const commitsInPr = prData.commits.nodes.map(n => parseCommitMessage(n.commit.message)); const commitsInPr = prData.commits.nodes.map(n => parseCommitMessage(n.commit.message));
try { try {
assertPendingState(prData);
assertChangesAllowForTargetLabel(commitsInPr, targetLabel, config); assertChangesAllowForTargetLabel(commitsInPr, targetLabel, config);
assertCorrectBreakingChangeLabeling(commitsInPr, labels, config); assertCorrectBreakingChangeLabeling(commitsInPr, labels, config);
} catch (error) { } catch (error) {
@ -136,6 +137,8 @@ export async function loadAndValidatePullRequest(
/* Graphql schema for the response body the requested pull request. */ /* Graphql schema for the response body the requested pull request. */
const PR_SCHEMA = { const PR_SCHEMA = {
url: graphqlTypes.string, url: graphqlTypes.string,
isDraft: graphqlTypes.boolean,
state: graphqlTypes.oneOf(['OPEN', 'MERGED', 'CLOSED'] as const),
number: graphqlTypes.number, number: graphqlTypes.number,
// Only the last 100 commits from a pull request are obtained as we likely will never see a pull // Only the last 100 commits from a pull request are obtained as we likely will never see a pull
// requests with more than 100 commits. // requests with more than 100 commits.
@ -159,11 +162,13 @@ const PR_SCHEMA = {
}), }),
}; };
/** A pull request retrieved from github via the graphql API. */
type RawPullRequest = typeof PR_SCHEMA;
/** Fetches a pull request from Github. Returns null if an error occurred. */ /** Fetches a pull request from Github. Returns null if an error occurred. */
async function fetchPullRequestFromGithub( async function fetchPullRequestFromGithub(
git: GitClient<true>, prNumber: number): Promise<typeof PR_SCHEMA|null> { git: GitClient<true>, prNumber: number): Promise<RawPullRequest|null> {
try { try {
const x = await getPr(PR_SCHEMA, prNumber, git); const x = await getPr(PR_SCHEMA, prNumber, git);
return x; return x;
@ -241,3 +246,17 @@ function assertCorrectBreakingChangeLabeling(
throw PullRequestFailure.missingBreakingChangeCommit(); throw PullRequestFailure.missingBreakingChangeCommit();
} }
} }
/** Assert the pull request is pending, not closed, merged or in draft. */
function assertPendingState(pr: RawPullRequest) {
if (pr.isDraft) {
throw PullRequestFailure.isDraft();
}
switch (pr.state) {
case 'CLOSED':
throw PullRequestFailure.isClosed();
case 'MERGED':
throw PullRequestFailure.isMerged();
}
}