From 7299a216e090c6204ff878797580102092dd6bb7 Mon Sep 17 00:00:00 2001 From: bcoe Date: Tue, 29 Dec 2020 13:46:57 -0800 Subject: [PATCH 1/2] feat: support @ and / when falling back to tags --- src/github.ts | 34 +++++++---- src/releasers/go-yoshi.ts | 5 +- src/releasers/ruby.ts | 5 +- test/github.ts | 116 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 18 deletions(-) diff --git a/src/github.ts b/src/github.ts index f684570d9..d128dd77a 100644 --- a/src/github.ts +++ b/src/github.ts @@ -456,17 +456,8 @@ export class GitHub { async latestTag( prefix?: string, preRelease = false, - // Allow a branch prefix to differ from a tag prefix. This was required - // for google-cloud-go, which uses the tag prefix library/vx.y.z. - // this is a requirement in the go community. - branchPrefix?: string ): Promise { - const pull = await this.findMergedReleasePR( - [], - 100, - branchPrefix ?? prefix, - preRelease - ); + const pull = await this.findMergedReleasePR([], 100, prefix, preRelease); if (!pull) return await this.latestTagFallback(prefix, preRelease); const tag = { name: `v${pull.version}`, @@ -514,6 +505,16 @@ export class GitHub { private async allTags( prefix?: string ): Promise<{[version: string]: GitHubTag}> { + // If we've fallen back to using allTags, support "-", "@", and "/" as a + // suffix separating the library name from the version #. This allows + // a repository to be seamlessly be migrated from a tool like lerna: + const prefixes: string[] = []; + if (prefix) { + prefix = prefix.substring(0, prefix.length - 1) + for (const suffix of ['-', '@', '/']) { + prefixes.push(`${prefix}${suffix}`); + } + } const tags: {[version: string]: GitHubTag} = {}; for await (const response of this.octokit.paginate.iterator( this.decoratePaginateOpts({ @@ -526,8 +527,17 @@ export class GitHub { response.data.forEach((data: ReposListTagsResponseItems) => { // For monorepos, a prefix can be provided, indicating that only tags // matching the prefix should be returned: - if (prefix && !data.name.startsWith(prefix)) return; - let version = data.name.replace(prefix, ''); + let version = data.name + if (prefix) { + let match = false; + for (prefix of prefixes) { + if (data.name.startsWith(prefix)) { + version = data.name.replace(prefix, ''); + match = true; + } + } + if (!match) return; + } if ((version = semver.valid(version))) { tags[version] = {sha: data.commit.sha, name: data.name, version}; } diff --git a/src/releasers/go-yoshi.ts b/src/releasers/go-yoshi.ts index 95ecfaf22..19eb24911 100644 --- a/src/releasers/go-yoshi.ts +++ b/src/releasers/go-yoshi.ts @@ -54,9 +54,8 @@ export class GoYoshi extends ReleasePR { static releaserName = 'go-yoshi'; protected async _run(): Promise { const latestTag = await this.gh.latestTag( - this.monorepoTags ? `${this.packageName}/` : undefined, - false, - this.monorepoTags ? `${this.packageName}` : undefined + this.monorepoTags ? `${this.packageName}-` : undefined, + false ); // eslint-disable-next-line @typescript-eslint/no-unused-vars const [_owner, repo] = parseGithubRepoUrl(this.repoUrl); diff --git a/src/releasers/ruby.ts b/src/releasers/ruby.ts index 44886d0d4..8e81cd6bb 100644 --- a/src/releasers/ruby.ts +++ b/src/releasers/ruby.ts @@ -41,9 +41,8 @@ export class Ruby extends ReleasePR { } protected async _run(): Promise { const latestTag: GitHubTag | undefined = await this.gh.latestTag( - this.monorepoTags ? `${this.packageName}/` : undefined, - false, - this.monorepoTags ? `${this.packageName}-` : undefined + this.monorepoTags ? `${this.packageName}-` : undefined, + false ); const commits: Commit[] = await this.commits({ sha: latestTag ? latestTag.sha : undefined, diff --git a/test/github.ts b/test/github.ts index e407bae6b..104fed669 100644 --- a/test/github.ts +++ b/test/github.ts @@ -332,6 +332,122 @@ describe('GitHub', () => { expect(latestTag!.version).to.equal('3.0.0-rc1'); req.done(); }); + it('falls back to using tags, for simple case', async () => { + req + .get( + '/repos/fake/fake/pulls?state=closed&per_page=100&sort=merged_at&direction=desc' + ) + .reply(200, []) + .get('/repos/fake/fake/tags?per_page=100') + .reply(200, [ + { + name: 'v1.0.0', + commit: {sha: 'abc123'}, + }, + { + name: 'v1.1.0', + commit: {sha: 'deadbeef'}, + }, + ]); + const latestTag = await github.latestTag(); + expect(latestTag!.version).to.equal('1.1.0'); + req.done(); + }); + it('falls back to using tags, when prefix is provided', async () => { + req + .get( + '/repos/fake/fake/pulls?state=closed&per_page=100&sort=merged_at&direction=desc' + ) + .reply(200, []) + .get('/repos/fake/fake/tags?per_page=100') + .reply(200, [ + { + name: 'v1.0.0', + commit: {sha: 'abc123'}, + }, + { + name: 'v1.1.0', + commit: {sha: 'deadbeef'}, + }, + { + name: 'foo-v1.9.0', + commit: {sha: 'deadbeef'}, + }, + { + name: 'v1.2.0', + commit: {sha: 'deadbeef'}, + }, + ]); + const latestTag = await github.latestTag('foo-'); + expect(latestTag!.version).to.equal('1.9.0'); + req.done(); + }); + it('allows for "@" rather than "-" when fallback used', async () => { + req + .get( + '/repos/fake/fake/pulls?state=closed&per_page=100&sort=merged_at&direction=desc' + ) + .reply(200, []) + .get('/repos/fake/fake/tags?per_page=100') + .reply(200, [ + { + name: 'v1.0.0', + commit: {sha: 'abc123'}, + }, + { + name: 'v1.1.0', + commit: {sha: 'deadbeef'}, + }, + { + name: 'foo@v1.9.0', + commit: {sha: 'dead'}, + }, + { + name: 'v1.2.0', + commit: {sha: 'beef'}, + }, + { + name: 'foo@v2.1.0', + commit: {sha: '123abc'}, + }, + ]); + const latestTag = await github.latestTag('foo-'); + expect(latestTag!.version).to.equal('2.1.0'); + req.done(); + }); + it('allows for "/" rather than "-" when fallback used', async () => { + req + .get( + '/repos/fake/fake/pulls?state=closed&per_page=100&sort=merged_at&direction=desc' + ) + .reply(200, []) + .get('/repos/fake/fake/tags?per_page=100') + .reply(200, [ + { + name: 'v1.0.0', + commit: {sha: 'abc123'}, + }, + { + name: 'v1.1.0', + commit: {sha: 'deadbeef'}, + }, + { + name: 'foo/v2.3.0', + commit: {sha: 'dead'}, + }, + { + name: 'v1.2.0', + commit: {sha: 'beef'}, + }, + { + name: 'foo/v2.1.0', + commit: {sha: '123abc'}, + }, + ]); + const latestTag = await github.latestTag('foo-'); + expect(latestTag!.version).to.equal('2.3.0'); + req.done(); + }); }); describe('getFileContents', () => { From c3e7ca7db8c2ce690bf26d1527d57402b1078733 Mon Sep 17 00:00:00 2001 From: bcoe Date: Tue, 29 Dec 2020 14:45:47 -0800 Subject: [PATCH 2/2] lint: ran linter --- src/github.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/github.ts b/src/github.ts index d128dd77a..c1817de2a 100644 --- a/src/github.ts +++ b/src/github.ts @@ -455,7 +455,7 @@ export class GitHub { // the branch we're configured for. async latestTag( prefix?: string, - preRelease = false, + preRelease = false ): Promise { const pull = await this.findMergedReleasePR([], 100, prefix, preRelease); if (!pull) return await this.latestTagFallback(prefix, preRelease); @@ -510,7 +510,7 @@ export class GitHub { // a repository to be seamlessly be migrated from a tool like lerna: const prefixes: string[] = []; if (prefix) { - prefix = prefix.substring(0, prefix.length - 1) + prefix = prefix.substring(0, prefix.length - 1); for (const suffix of ['-', '@', '/']) { prefixes.push(`${prefix}${suffix}`); } @@ -527,7 +527,7 @@ export class GitHub { response.data.forEach((data: ReposListTagsResponseItems) => { // For monorepos, a prefix can be provided, indicating that only tags // matching the prefix should be returned: - let version = data.name + let version = data.name; if (prefix) { let match = false; for (prefix of prefixes) {