diff --git a/dev-infra/ng-dev.js b/dev-infra/ng-dev.js index 39e9f71014..04d29d9501 100755 --- a/dev-infra/ng-dev.js +++ b/dev-infra/ng-dev.js @@ -3900,35 +3900,52 @@ var AutosquashMergeStrategy = /** @class */ (function (_super) { */ AutosquashMergeStrategy.prototype.merge = function (pullRequest) { return tslib.__awaiter(this, void 0, void 0, function () { - var prNumber, targetBranches, requiredBaseSha, needsCommitMessageFixup, baseSha, revisionRange, branchOrRevisionBeforeRebase, rebaseEnv, failedBranches; + var prNumber, targetBranches, requiredBaseSha, needsCommitMessageFixup, githubTargetBranch, baseSha, revisionRange, branchOrRevisionBeforeRebase, rebaseEnv, failedBranches, localBranch, sha; return tslib.__generator(this, function (_a) { - prNumber = pullRequest.prNumber, targetBranches = pullRequest.targetBranches, requiredBaseSha = pullRequest.requiredBaseSha, needsCommitMessageFixup = pullRequest.needsCommitMessageFixup; - // In case a required base is specified for this pull request, check if the pull - // request contains the given commit. If not, return a pull request failure. This - // check is useful for enforcing that PRs are rebased on top of a given commit. e.g. - // a commit that changes the codeowner ship validation. PRs which are not rebased - // could bypass new codeowner ship rules. - if (requiredBaseSha && !this.git.hasCommit(TEMP_PR_HEAD_BRANCH, requiredBaseSha)) { - return [2 /*return*/, PullRequestFailure.unsatisfiedBaseSha()]; + switch (_a.label) { + case 0: + prNumber = pullRequest.prNumber, targetBranches = pullRequest.targetBranches, requiredBaseSha = pullRequest.requiredBaseSha, needsCommitMessageFixup = pullRequest.needsCommitMessageFixup, githubTargetBranch = pullRequest.githubTargetBranch; + // In case a required base is specified for this pull request, check if the pull + // request contains the given commit. If not, return a pull request failure. This + // check is useful for enforcing that PRs are rebased on top of a given commit. e.g. + // a commit that changes the codeowner ship validation. PRs which are not rebased + // could bypass new codeowner ship rules. + if (requiredBaseSha && !this.git.hasCommit(TEMP_PR_HEAD_BRANCH, requiredBaseSha)) { + return [2 /*return*/, PullRequestFailure.unsatisfiedBaseSha()]; + } + baseSha = this.git.run(['rev-parse', this.getPullRequestBaseRevision(pullRequest)]).stdout.trim(); + revisionRange = baseSha + ".." + TEMP_PR_HEAD_BRANCH; + branchOrRevisionBeforeRebase = this.git.getCurrentBranchOrRevision(); + rebaseEnv = needsCommitMessageFixup ? undefined : tslib.__assign(tslib.__assign({}, process.env), { GIT_SEQUENCE_EDITOR: 'true' }); + this.git.run(['rebase', '--interactive', '--autosquash', baseSha, TEMP_PR_HEAD_BRANCH], { stdio: 'inherit', env: rebaseEnv }); + // Update pull requests commits to reference the pull request. This matches what + // Github does when pull requests are merged through the Web UI. The motivation is + // that it should be easy to determine which pull request contained a given commit. + // Note: The filter-branch command relies on the working tree, so we want to make sure + // that we are on the initial branch or revision where the merge script has been invoked. + this.git.run(['checkout', '-f', branchOrRevisionBeforeRebase]); + this.git.run(['filter-branch', '-f', '--msg-filter', MSG_FILTER_SCRIPT + " " + prNumber, revisionRange]); + failedBranches = this.cherryPickIntoTargetBranches(revisionRange, targetBranches); + if (failedBranches.length) { + return [2 /*return*/, PullRequestFailure.mergeConflicts(failedBranches)]; + } + this.pushTargetBranchesUpstream(targetBranches); + if (!(githubTargetBranch !== 'master')) return [3 /*break*/, 3]; + localBranch = this.getLocalTargetBranchName(githubTargetBranch); + sha = this.git.run(['rev-parse', localBranch]).stdout.trim(); + // Create a comment saying the PR was closed by the SHA. + return [4 /*yield*/, this.git.github.issues.createComment(tslib.__assign(tslib.__assign({}, this.git.remoteParams), { issue_number: pullRequest.prNumber, body: "Closed by commit " + sha }))]; + case 1: + // Create a comment saying the PR was closed by the SHA. + _a.sent(); + // Actually close the PR. + return [4 /*yield*/, this.git.github.pulls.update(tslib.__assign(tslib.__assign({}, this.git.remoteParams), { pull_number: pullRequest.prNumber, state: 'closed' }))]; + case 2: + // Actually close the PR. + _a.sent(); + _a.label = 3; + case 3: return [2 /*return*/, null]; } - baseSha = this.git.run(['rev-parse', this.getPullRequestBaseRevision(pullRequest)]).stdout.trim(); - revisionRange = baseSha + ".." + TEMP_PR_HEAD_BRANCH; - branchOrRevisionBeforeRebase = this.git.getCurrentBranchOrRevision(); - rebaseEnv = needsCommitMessageFixup ? undefined : tslib.__assign(tslib.__assign({}, process.env), { GIT_SEQUENCE_EDITOR: 'true' }); - this.git.run(['rebase', '--interactive', '--autosquash', baseSha, TEMP_PR_HEAD_BRANCH], { stdio: 'inherit', env: rebaseEnv }); - // Update pull requests commits to reference the pull request. This matches what - // Github does when pull requests are merged through the Web UI. The motivation is - // that it should be easy to determine which pull request contained a given commit. - // Note: The filter-branch command relies on the working tree, so we want to make sure - // that we are on the initial branch or revision where the merge script has been invoked. - this.git.run(['checkout', '-f', branchOrRevisionBeforeRebase]); - this.git.run(['filter-branch', '-f', '--msg-filter', MSG_FILTER_SCRIPT + " " + prNumber, revisionRange]); - failedBranches = this.cherryPickIntoTargetBranches(revisionRange, targetBranches); - if (failedBranches.length) { - return [2 /*return*/, PullRequestFailure.mergeConflicts(failedBranches)]; - } - this.pushTargetBranchesUpstream(targetBranches); - return [2 /*return*/, null]; }); }); }; diff --git a/dev-infra/pr/merge/strategies/autosquash-merge.ts b/dev-infra/pr/merge/strategies/autosquash-merge.ts index e304ed98bd..f4d72c4680 100644 --- a/dev-infra/pr/merge/strategies/autosquash-merge.ts +++ b/dev-infra/pr/merge/strategies/autosquash-merge.ts @@ -32,7 +32,8 @@ export class AutosquashMergeStrategy extends MergeStrategy { * @returns A pull request failure or null in case of success. */ async merge(pullRequest: PullRequest): Promise { - const {prNumber, targetBranches, requiredBaseSha, needsCommitMessageFixup} = pullRequest; + const {prNumber, targetBranches, requiredBaseSha, needsCommitMessageFixup, githubTargetBranch} = + pullRequest; // In case a required base is specified for this pull request, check if the pull // request contains the given commit. If not, return a pull request failure. This // check is useful for enforcing that PRs are rebased on top of a given commit. e.g. @@ -83,6 +84,30 @@ export class AutosquashMergeStrategy extends MergeStrategy { } this.pushTargetBranchesUpstream(targetBranches); + + // For PRs which do not target the `master` branch on Github, Github does not automatically + // close the PR when its commit is pushed into the repository. To ensure these PRs are + // correctly marked as closed, we must detect this situation and close the PR via the API after + // the upstream pushes are completed. + if (githubTargetBranch !== 'master') { + /** The local branch name of the github targeted branch. */ + const localBranch = this.getLocalTargetBranchName(githubTargetBranch); + /** The SHA of the commit pushed to github which represents closing the PR. */ + const sha = this.git.run(['rev-parse', localBranch]).stdout.trim(); + // Create a comment saying the PR was closed by the SHA. + await this.git.github.issues.createComment({ + ...this.git.remoteParams, + issue_number: pullRequest.prNumber, + body: `Closed by commit ${sha}` + }); + // Actually close the PR. + await this.git.github.pulls.update({ + ...this.git.remoteParams, + pull_number: pullRequest.prNumber, + state: 'closed', + }); + } + return null; } }