diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts index 3542e822e1..9661368b5e 100644 --- a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts +++ b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts @@ -95,6 +95,10 @@ describe('BitbucketUrlReader', () => { res( ctx.status(200), ctx.set('Content-Type', 'application/zip'), + ctx.set( + 'content-disposition', + 'attachment; filename=backstage-mock-12ab34cd56ef.zip', + ), ctx.body(repoBuffer), ), ), @@ -114,6 +118,10 @@ describe('BitbucketUrlReader', () => { res( ctx.status(200), ctx.set('Content-Type', 'application/zip'), + ctx.set( + 'content-disposition', + 'attachment; filename=backstage-mock.zip', + ), ctx.body(privateBitbucketRepoBuffer), ), ), diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.ts b/packages/backend-common/src/reading/BitbucketUrlReader.ts index 869870f248..5b9dc7f333 100644 --- a/packages/backend-common/src/reading/BitbucketUrlReader.ts +++ b/packages/backend-common/src/reading/BitbucketUrlReader.ts @@ -125,14 +125,31 @@ export class BitbucketUrlReader implements UrlReader { throw new Error(message); } - let folderPath = `${project}-${repoName}`; - if (isHosted) { - folderPath = `${project}-${repoName}-${lastCommitShortHash}`; + // Get the filename of archive from the header of the response + const contentDispositionHeader = archiveBitbucketResponse.headers.get( + 'content-disposition', + ) as string; + if (!contentDispositionHeader) { + throw new Error( + `Failed to read tree from ${url}. ` + + 'Bitbucket API response for downloading archive does not contain content-disposition header ', + ); + } + const fileNameRegEx = new RegExp( + /^attachment; filename=(?.*).zip$/, + ); + const archiveFileName = contentDispositionHeader.match(fileNameRegEx) + ?.groups?.fileName; + if (!archiveFileName) { + throw new Error( + `Failed to read tree from ${url}. Bitbucket API response for downloading archive has an unexpected ` + + `format of content-disposition header ${contentDispositionHeader} `, + ); } return await this.treeResponseFactory.fromZipArchive({ stream: (archiveBitbucketResponse.body as unknown) as Readable, - path: `${folderPath}/${filepath}`, + path: `${archiveFileName}/${filepath}`, etag: lastCommitShortHash, filter: options?.filter, });