diff --git a/.changeset/chatty-vans-cross.md b/.changeset/chatty-vans-cross.md new file mode 100644 index 0000000000..fab7af5155 --- /dev/null +++ b/.changeset/chatty-vans-cross.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration': patch +--- + +Fixed an issue with resolution of SCM URLs against a base URL with a trailing slash. diff --git a/packages/integration/src/helpers.test.ts b/packages/integration/src/helpers.test.ts index 7468c83bc6..72ccd53061 100644 --- a/packages/integration/src/helpers.test.ts +++ b/packages/integration/src/helpers.test.ts @@ -116,6 +116,82 @@ describe('defaultScmResolveUrl', () => { ); }); + it('works for the root path', () => { + expect( + defaultScmResolveUrl({ + url: '/', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/', + ); + + expect( + defaultScmResolveUrl({ + url: '/', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/', + ); + + expect( + defaultScmResolveUrl({ + url: '/', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/', + ); + + expect( + defaultScmResolveUrl({ + url: '/', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/?at=master', + ); + }); + + it('works for files in the repo root', () => { + expect( + defaultScmResolveUrl({ + url: '/b.yaml', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/b.yaml', + ); + + expect( + defaultScmResolveUrl({ + url: '/b.yaml', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/b.yaml', + ); + + expect( + defaultScmResolveUrl({ + url: '/b.yaml', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/b.yaml', + ); + + expect( + defaultScmResolveUrl({ + url: '/b.yaml', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/b.yaml?at=master', + ); + }); + it('works for absolute paths and retains query params', () => { expect( defaultScmResolveUrl({ @@ -126,6 +202,24 @@ describe('defaultScmResolveUrl', () => { 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/other/b.yaml', ); + expect( + defaultScmResolveUrl({ + url: '/other/b.yaml', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/other/b.yaml', + ); + + expect( + defaultScmResolveUrl({ + url: '/other/b.yaml', + base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/', + }), + ).toBe( + 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/other/b.yaml', + ); + expect( defaultScmResolveUrl({ url: '/other/b.yaml', diff --git a/packages/integration/src/helpers.ts b/packages/integration/src/helpers.ts index 94aafaa6c3..b403155cc5 100644 --- a/packages/integration/src/helpers.ts +++ b/packages/integration/src/helpers.ts @@ -84,8 +84,10 @@ export function defaultScmResolveUrl(options: { if (url.startsWith('/')) { // If it is an absolute path, move relative to the repo root - const { filepath } = parseGitUrl(base); - updated = new URL(base); + const { href, filepath } = parseGitUrl(base); + + updated = new URL(href); + const repoRootPath = trimEnd( updated.pathname.substring(0, updated.pathname.length - filepath.length), '/',