@@ -158,23 +158,6 @@ export abstract class ReleaseAction {
158158 return commit ;
159159 }
160160
161- /** Checks whether the given revision is ahead to the base by the specified amount. */
162- private async _isRevisionAheadOfBase (
163- baseRevision : string ,
164- targetRevision : string ,
165- expectedAheadCount : number ,
166- ) {
167- const {
168- data : { ahead_by, status} ,
169- } = await this . git . github . repos . compareCommits ( {
170- ...this . git . remoteParams ,
171- base : baseRevision ,
172- head : targetRevision ,
173- } ) ;
174-
175- return status === 'ahead' && ahead_by === expectedAheadCount ;
176- }
177-
178161 /**
179162 * Verifies that the given commit has passing all statuses.
180163 *
@@ -704,24 +687,11 @@ export abstract class ReleaseAction {
704687 npmDistTag : NpmDistTag ,
705688 additionalOptions : { showAsLatestOnGitHub : boolean } ,
706689 ) {
707- const { sha : versionBumpCommitSha } = await this . getLatestCommitOfBranch ( publishBranch ) ;
708-
709- // Ensure the latest commit in the publish branch is the bump commit.
710- if ( ! ( await this . _isCommitForVersionStaging ( releaseNotes . version , versionBumpCommitSha ) ) ) {
711- Log . error ( ` ✘ Latest commit in "${ publishBranch } " branch is not a staging commit.` ) ;
712- Log . error ( ' Please make sure the staging pull request has been merged.' ) ;
713- throw new FatalReleaseActionError ( ) ;
714- }
715-
716- // Ensure no commits have landed since we started the staging process. This would signify
717- // that the locally-built release packages are not matching with the release commit on GitHub.
718- // Note: We expect the version bump commit to be ahead by **one** commit. This means it's
719- // the direct parent of the commit that was latest when we started the staging.
720- if ( ! ( await this . _isRevisionAheadOfBase ( beforeStagingSha , versionBumpCommitSha , 1 ) ) ) {
721- Log . error ( ` ✘ Unexpected additional commits have landed while staging the release.` ) ;
722- Log . error ( ' Please revert the bump commit and retry, or cut a new version on top.' ) ;
723- throw new FatalReleaseActionError ( ) ;
724- }
690+ const releaseSha = await this . _getAndValidateLatestCommitForPublishing (
691+ publishBranch ,
692+ releaseNotes . version ,
693+ beforeStagingSha ,
694+ ) ;
725695
726696 // Before publishing, we want to ensure that the locally-built packages we
727697 // built in the staging phase have not been modified accidentally.
@@ -730,7 +700,7 @@ export abstract class ReleaseAction {
730700 // Create a Github release for the new version.
731701 await this . _createGithubReleaseForVersion (
732702 releaseNotes ,
733- versionBumpCommitSha ,
703+ releaseSha ,
734704 npmDistTag === 'next' ,
735705 additionalOptions . showAsLatestOnGitHub ,
736706 ) ;
@@ -760,13 +730,45 @@ export abstract class ReleaseAction {
760730 }
761731 }
762732
763- /** Checks whether the given commit represents a staging commit for the specified version. */
764- private async _isCommitForVersionStaging ( version : semver . SemVer , commitSha : string ) {
765- const { data} = await this . git . github . repos . getCommit ( {
766- ...this . git . remoteParams ,
767- ref : commitSha ,
768- } ) ;
769- return data . commit . message . startsWith ( getCommitMessageForRelease ( version ) ) ;
733+ /**
734+ * Retreive the latest commit from the provided branch, and verify that it is the expected
735+ * release commit and is the direct child of the previous sha provided.
736+ *
737+ * The method will make one recursive attempt to check again before throwing an error if
738+ * any error occurs during this validation.
739+ */
740+ private async _getAndValidateLatestCommitForPublishing (
741+ branch : string ,
742+ version : semver . SemVer ,
743+ previousSha : string ,
744+ isRetry = false ,
745+ ) : Promise < string > {
746+ try {
747+ const commit = await this . getLatestCommitOfBranch ( branch ) ;
748+ // Ensure the latest commit in the publish branch is the bump commit.
749+ if ( ! commit . commit . message . startsWith ( getCommitMessageForRelease ( version ) ) ) {
750+ /** The shortened sha of the commit for usage in the error message. */
751+ const sha = commit . sha . slice ( 0 , 8 ) ;
752+ Log . error ( ` ✘ Latest commit (${ sha } ) in "${ branch } " branch is not a staging commit.` ) ;
753+ Log . error ( ' Please make sure the staging pull request has been merged.' ) ;
754+ throw new FatalReleaseActionError ( ) ;
755+ }
756+
757+ // We only inspect the first parent as we enforce that no merge commits are used in our
758+ // repos, so all commits have exactly one parent.
759+ if ( commit . parents [ 0 ] . sha !== previousSha ) {
760+ Log . error ( ` ✘ Unexpected additional commits have landed while staging the release.` ) ;
761+ Log . error ( ' Please revert the bump commit and retry, or cut a new version on top.' ) ;
762+ throw new FatalReleaseActionError ( ) ;
763+ }
764+
765+ return commit . sha ;
766+ } catch ( e : unknown ) {
767+ if ( isRetry ) {
768+ throw e ;
769+ }
770+ return this . _getAndValidateLatestCommitForPublishing ( branch , version , previousSha , true ) ;
771+ }
770772 }
771773
772774 // TODO: Remove this check and run it as part of common release validation.
0 commit comments