diff --git a/ng-dev/release/publish/actions.ts b/ng-dev/release/publish/actions.ts index 21f0fd692..c8c6a3d13 100644 --- a/ng-dev/release/publish/actions.ts +++ b/ng-dev/release/publish/actions.ts @@ -469,7 +469,38 @@ export abstract class ReleaseAction { pullRequest: PullRequest; builtPackagesWithInfo: BuiltPackageWithInfo[]; }> { - const releaseNotesCompareTag = getReleaseTagForVersion(compareVersionForReleaseNotes); + /** Tag name for the version being used for the base of comparison generating release notes. */ + let releaseNotesCompareTag: string; + // Determine whether the previous version used for comparison in generating release notes used a v prefix. + /** The expected comparison version prefixed with `v`. */ + const prefixedTag = getReleaseTagForVersion(compareVersionForReleaseNotes); + /** The expected comparison version. */ + const unprefixedTag = compareVersionForReleaseNotes.version; + + if ( + this.git.runGraceful([ + 'ls-remote', + '-q', + '--exit-code', + this.git.getRepoGitUrl(), + `refs/tags/${prefixedTag}`, + ]).status === 0 + ) { + releaseNotesCompareTag = prefixedTag; + } else if ( + this.git.runGraceful([ + 'ls-remote', + '-q', + '--exit-code', + this.git.getRepoGitUrl(), + `refs/tags/${unprefixedTag}`, + ]).status === 0 + ) { + releaseNotesCompareTag = unprefixedTag; + } else { + Log.error(` ✘ Unable to find previous tag (${prefixedTag}) for building release notes.`); + throw new FatalReleaseActionError(); + } // Fetch the compare tag so that commits for the release notes can be determined. // We forcibly override existing local tags that are named similar as we will fetch @@ -700,6 +731,10 @@ export abstract class ReleaseAction { // built in the staging phase have not been modified accidentally. await assertIntegrityOfBuiltPackages(builtPackagesWithInfo); + // NOTE: + // The Github Release must be created prior to publishing to npm as the version of the package + // being published is verified by wombot proxy to already match the existing Github relase. + // Create a Github release for the new version. await this._createGithubReleaseForVersion( releaseNotes, diff --git a/ng-dev/release/publish/test/common.spec.ts b/ng-dev/release/publish/test/common.spec.ts index f1517c3c1..963f7bc96 100644 --- a/ng-dev/release/publish/test/common.spec.ts +++ b/ng-dev/release/publish/test/common.spec.ts @@ -345,7 +345,7 @@ describe('common release action logic', () => { tagName, true, changelogPattern` - Release notes are too large to be captured here. [View all changes here](https://github.com/angular/dev-infra-test/blob/10.0.1/CHANGELOG.md#10.0.1). + Release notes are too large to be captured here. [View all changes here](https://github.com/angular/dev-infra-test/blob/v10.0.1/CHANGELOG.md#10.0.1). `, ); diff --git a/ng-dev/release/versioning/version-tags.ts b/ng-dev/release/versioning/version-tags.ts index bf553d2af..15e34e518 100644 --- a/ng-dev/release/versioning/version-tags.ts +++ b/ng-dev/release/versioning/version-tags.ts @@ -10,5 +10,5 @@ import semver from 'semver'; /** Gets the release tag name for the specified version. */ export function getReleaseTagForVersion(version: semver.SemVer): string { - return version.format(); + return `v${version.format()}`; } diff --git a/ng-dev/utils/testing/github-api-testing.ts b/ng-dev/utils/testing/github-api-testing.ts index 3f8f302d6..d98ba806f 100644 --- a/ng-dev/utils/testing/github-api-testing.ts +++ b/ng-dev/utils/testing/github-api-testing.ts @@ -79,7 +79,9 @@ export class GithubTestingRepo { } expectReleaseByTagRequest(tagName: string, id: number): this { - nock(this.repoApiUrl).get(`/releases/tags/${tagName}`).reply(200, {id}); + nock(this.repoApiUrl) + .get(new RegExp(`/releases/tags/v?${tagName}`)) + .reply(200, {id}); return this; } @@ -113,7 +115,11 @@ export class GithubTestingRepo { expectTagToBeCreated(tagName: string, sha: string): this { nock(this.repoApiUrl) - .post(`/git/refs`, (b) => b.ref === `refs/tags/${tagName}` && b.sha === sha) + .post( + `/git/refs`, + (b: {ref: string; sha: string}) => + new RegExp(`refs/tags/v?${tagName}`).test(b.ref) && b.sha === sha, + ) .reply(200, {}); return this; } @@ -135,7 +141,7 @@ export class GithubTestingRepo { if (bodyRegex && !bodyRegex.test(requestBody.body)) { return false; } - return requestBody['tag_name'] === tagName; + return new RegExp(`v?${tagName}`).test(requestBody['tag_name']); }) .reply(200, {}); return this; diff --git a/ng-dev/utils/testing/sandbox-git-client.ts b/ng-dev/utils/testing/sandbox-git-client.ts index 7851f97e1..08c67a1cd 100644 --- a/ng-dev/utils/testing/sandbox-git-client.ts +++ b/ng-dev/utils/testing/sandbox-git-client.ts @@ -55,6 +55,17 @@ export class SandboxGitClient extends AuthenticatedGitClient { return noopSpawnSyncReturns; } + // When ls-remote is run in our testing environment we are always + // checking for an already defined ref which "should exist upstream" + // Since no upstream exists in testing, we just check to make sure + // the ref has already been defined locally by changing the git remote + // provided to '.' which points to the local git repo. + if (command === 'ls-remote') { + const gitRemoteMatcher = + /((git|ssh|http(s)?)|(git@[\w\.]+))(:(\/\/)?)([\w\.@\:/\-~]+)(\.git)(\/)?/; + args = args.map((arg) => (gitRemoteMatcher.test(arg) ? '.' : arg)); + } + return super.runGraceful(args, options); } }