diff --git a/lib/workers/repository/update/pr/changelog/github.spec.ts b/lib/workers/repository/update/pr/changelog/github.spec.ts index 7a489d028dafd9ebc4334cf7d0931c317ee4af86..77074ea4b63cfa76a2b4c7f31d45fcd64ded89e5 100644 --- a/lib/workers/repository/update/pr/changelog/github.spec.ts +++ b/lib/workers/repository/update/pr/changelog/github.spec.ts @@ -294,5 +294,61 @@ describe('workers/repository/update/pr/changelog/github', () => { ], }); }); + + it('works with same version releases but different prefix', async () => { + httpMock + .scope('https://api.github.com/') + .get('/repos/chalk/chalk/tags?per_page=100') + .reply(200, [ + { name: 'v1.0.1' }, + { name: '1.0.1' }, + { name: 'correctPrefix/target@1.0.1' }, + { name: 'wrongPrefix/target-1.0.1' }, + ]); + + const upgradeData: BranchUpgradeConfig = { + branchName: undefined, + depName: 'correctPrefix/target', + endpoint: 'https://api.github.com/', + versioning: 'npm', + currentVersion: '1.0.0', + newVersion: '1.0.1', + sourceUrl: 'https://github.com/chalk/chalk', + releases: [ + { version: '1.0.1', gitRef: '123456' }, + { version: '0.1.1', gitRef: 'npm_1.0.0' }, + ], + }; + expect( + await getChangeLogJSON({ + ...upgradeData, + }) + ).toMatchObject({ + project: { + apiBaseUrl: 'https://api.github.com/', + baseUrl: 'https://github.com/', + type: 'github', + repository: 'chalk/chalk', + sourceUrl: 'https://github.com/chalk/chalk', + sourceDirectory: undefined, + depName: 'correctPrefix/target', + }, + versions: [ + { + version: '1.0.1', + date: undefined, + changes: [], + compare: { + url: 'https://github.com/chalk/chalk/compare/npm_1.0.0...correctPrefix/target@1.0.1', + }, + releaseNotes: { + url: 'https://github.com/chalk/chalk/compare/npm_1.0.0...correctPrefix/target@1.0.1', + notesSourceUrl: '', + }, + }, + ], + hasReleaseNotes: true, + }); + }); }); }); diff --git a/lib/workers/repository/update/pr/changelog/release-notes.spec.ts b/lib/workers/repository/update/pr/changelog/release-notes.spec.ts index 032b3a18826e0c7e4e54b433c542a01c3858418b..04c99e669e325afdcbff62857b27afe43e6df12c 100644 --- a/lib/workers/repository/update/pr/changelog/release-notes.spec.ts +++ b/lib/workers/repository/update/pr/changelog/release-notes.spec.ts @@ -544,6 +544,41 @@ describe('workers/repository/update/pr/changelog/release-notes', () => { ); expect(res).toBeNull(); }); + + it('handles same version but different repo releases', async () => { + const depName = 'correctTagPrefix/exampleDep'; + httpMock + .scope('https://api.github.com/') + .get('/repos/some/other-repository/releases?per_page=100') + .reply(200, [ + { + tag_name: `${depName}@1.0.0`, + html_url: 'correct/url/tag.com', + body: 'some body', + }, + { tag_name: `someOtherRelease1/exampleDep_1.0.0` }, + { + tag_name: `someOtherRelease2/exampleDep-1.0.0`, + }, + ]); + const res = await getReleaseNotes( + { + ...githubProject, + repository: 'some/other-repository', + depName: 'exampleDep', + }, + '1.0.0' + ); + expect(res).toEqual({ + url: 'correct/url/tag.com', + notesSourceUrl: + 'https://api.github.com/repos/some/other-repository/releases', + id: undefined, + tag: 'correctTagPrefix/exampleDep@1.0.0', + name: undefined, + body: 'some body\n', + }); + }); }); describe('getReleaseNotesMd()', () => { diff --git a/lib/workers/repository/update/pr/changelog/release-notes.ts b/lib/workers/repository/update/pr/changelog/release-notes.ts index 1cfd3c3253dd2c4b3c681be2600f5dc31e93786c..1709d6cf0424c2cca67b731a9e9f648cc15c1f71 100644 --- a/lib/workers/repository/update/pr/changelog/release-notes.ts +++ b/lib/workers/repository/update/pr/changelog/release-notes.ts @@ -97,40 +97,70 @@ export async function getReleaseNotes( project: ChangeLogProject, version: string ): Promise<ChangeLogNotes | null> { - const { baseUrl, depName, repository } = project; + const { depName, repository } = project; logger.trace(`getReleaseNotes(${repository}, ${version}, ${depName})`); - const releaseList = await getCachedReleaseList(project); - logger.trace({ releaseList }, 'Release list from getReleaseList'); + const releases = await getCachedReleaseList(project); + logger.trace({ releases }, 'Release list from getReleaseList'); let releaseNotes: ChangeLogNotes | null = null; - for (const release of releaseList) { - if ( - release.tag === version || - release.tag === `v${version}` || - release.tag === `${depName}-${version}` || - release.tag === `${depName}_v${version}` || - release.tag === `${depName}@${version}` - ) { - releaseNotes = release; - releaseNotes.url = baseUrl.includes('gitlab') - ? `${baseUrl}${repository}/tags/${release.tag}` - : `${baseUrl}${repository}/releases/${release.tag}`; - releaseNotes.body = massageBody(releaseNotes.body, baseUrl); - if (releaseNotes.body.length) { - try { - if (baseUrl !== 'https://gitlab.com/') { - releaseNotes.body = await linkify(releaseNotes.body, { - repository: `${baseUrl}${repository}`, - }); - } - } catch (err) /* istanbul ignore next */ { - logger.warn({ err, baseUrl, repository }, 'Error linkifying'); - } - } else { - releaseNotes = null; + + let matchedRelease = getExactReleaseMatch(depName, version, releases); + if (is.undefined(matchedRelease)) { + // no exact match of a release then check other cases + matchedRelease = releases.find( + (r) => r.tag === version || r.tag === `v${version}` + ); + } + releaseNotes = await releaseNotesResult(matchedRelease, project); + logger.trace({ releaseNotes }); + return releaseNotes; +} + +function getExactReleaseMatch( + depName: string, + version: string, + releases: ChangeLogNotes[] +): ChangeLogNotes | undefined { + const exactReleaseReg = regEx(`${depName}[@_-]v?${version}`); + const candidateReleases = releases.filter((r) => r.tag?.endsWith(version)); + const matchedRelease = candidateReleases.find((r) => + exactReleaseReg.test(r.tag) + ); + return matchedRelease; +} + +async function releaseNotesResult( + releaseMatch: ChangeLogNotes | undefined, + project: ChangeLogProject +): Promise<ChangeLogNotes | null> { + if (!releaseMatch) { + return null; + } + const { baseUrl, repository } = project; + const releaseNotes: ChangeLogNotes = releaseMatch; + if (releaseMatch.url && !baseUrl.includes('gitlab')) { + // there is a ready link + releaseNotes.url = releaseMatch.url; + } else { + releaseNotes.url = baseUrl.includes('gitlab') + ? `${baseUrl}${repository}/tags/${releaseMatch.tag}` + : `${baseUrl}${repository}/releases/${releaseMatch.tag}`; + } + // set body for release notes + releaseNotes.body = massageBody(releaseNotes.body, baseUrl); + if (releaseNotes.body.length) { + try { + if (baseUrl !== 'https://gitlab.com/') { + releaseNotes.body = await linkify(releaseNotes.body, { + repository: `${baseUrl}${repository}`, + }); } + } catch (err) /* istanbul ignore next */ { + logger.warn({ err, baseUrl, repository }, 'Error linkifying'); } + } else { + return null; } - logger.trace({ releaseNotes }); + return releaseNotes; } diff --git a/lib/workers/repository/update/pr/changelog/source-github.ts b/lib/workers/repository/update/pr/changelog/source-github.ts index 2de019a7266fd4e9e31e802b3d80ccfa741766b9..34729fa91467faa3b2dd8d7aafeaaac6e659b1cb 100644 --- a/lib/workers/repository/update/pr/changelog/source-github.ts +++ b/lib/workers/repository/update/pr/changelog/source-github.ts @@ -105,10 +105,7 @@ export async function getChangeLogJSON({ if (!tags) { tags = await getCachedTags(apiBaseUrl, repository); } - const regex = regEx(`(?:${depName}|release)[@-]`, undefined, false); - const tagName = tags - .filter((tag) => version.isVersion(tag.replace(regex, ''))) - .find((tag) => version.equals(tag.replace(regex, ''), release.version)); + const tagName = findTagOfRelease(version, depName, release.version, tags); if (tagName) { return tagName; } @@ -179,3 +176,27 @@ export async function getChangeLogJSON({ return res; } + +function findTagOfRelease( + version: allVersioning.VersioningApi, + depName: string, + depNewVersion: string, + tags: string[] +): string | undefined { + const regex = regEx(`(?:${depName}|release)[@-]`, undefined, false); + const excactReleaseRegex = regEx(`${depName}[@-_]v?${depNewVersion}`); + const exactTagsList = tags.filter((tag) => { + return excactReleaseRegex.test(tag); + }); + let tagName: string | undefined; + if (exactTagsList.length) { + tagName = exactTagsList + .filter((tag) => version.isVersion(tag.replace(regex, ''))) + .find((tag) => version.equals(tag.replace(regex, ''), depNewVersion)); + } else { + tagName = tags + .filter((tag) => version.isVersion(tag.replace(regex, ''))) + .find((tag) => version.equals(tag.replace(regex, ''), depNewVersion)); + } + return tagName; +}