Skip to content

Commit 062e12c

Browse files
committed
fix(ng-dev): allow for a retry during the validation that the commit sha being released is the expected commit
1 parent 8d30db5 commit 062e12c

File tree

1 file changed

+45
-43
lines changed

1 file changed

+45
-43
lines changed

ng-dev/release/publish/actions.ts

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)