fix: [#13560] Pull commit hash for branch names by branch query

Using the commits API was unstable and broke for branches with a '/'.
Using the branches API works for any branch and is documented in the
Atlassian API docs:
https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp209

Signed-off-by: David Zemon <david@zemon.name>
This commit is contained in:
David Zemon
2022-10-04 11:14:04 -05:00
parent 037b4393c4
commit c44cf412de
3 changed files with 65 additions and 28 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
Fix BitBucket server integration
@@ -83,11 +83,23 @@ describe('BitbucketServerUrlReader', () => {
),
),
rest.get(
'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits/*',
'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/branches',
(_, res, ctx) =>
res(
ctx.status(200),
ctx.json({ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }),
ctx.json({
size: 2,
values: [
{
displayId: 'some-branch-that-should-be-ignored',
latestCommit: 'bogus hash',
},
{
displayId: 'some-branch',
latestCommit: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st',
},
],
}),
),
),
);
@@ -130,12 +142,22 @@ describe('BitbucketServerUrlReader', () => {
),
),
rest.get(
'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits/*',
'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/branches',
(_, res, ctx) =>
res(
ctx.status(200),
ctx.json({
values: [{ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }],
size: 2,
values: [
{
displayId: 'some-branch-that-should-be-ignored',
latestCommit: 'bogus hash',
},
{
displayId: 'some-branch',
latestCommit: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st',
},
],
}),
),
),
@@ -179,11 +201,23 @@ describe('BitbucketServerUrlReader', () => {
),
),
rest.get(
'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/commits/*',
'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/branches',
(_, res, ctx) =>
res(
ctx.status(200),
ctx.json({ id: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st' }),
ctx.json({
size: 2,
values: [
{
displayId: 'master-of-none',
latestCommit: 'bogus hash',
},
{
displayId: 'master',
latestCommit: '12ab34cd56ef78gh90ij12kl34mn56op78qr90st',
},
],
}),
),
),
);
@@ -188,38 +188,36 @@ export class BitbucketServerUrlReader implements UrlReader {
private async getLastCommitShortHash(url: string): Promise<string> {
const { name: repoName, owner: project, ref: branch } = parseGitUrl(url);
// Bitbucket Server https://docs.atlassian.com/bitbucket-server/rest/7.9.0/bitbucket-rest.html#idp224
const commitApiUrl = `${this.integration.config.apiBaseUrl}/projects/${project}/repos/${repoName}/commits/${branch}`;
const branchListUrl = `${
this.integration.config.apiBaseUrl
}/projects/${project}/repos/${repoName}/branches?filterText=${encodeURIComponent(
branch,
)}`;
const commitResponse = await fetch(
commitApiUrl,
const branchListResponse = await fetch(
branchListUrl,
getBitbucketServerRequestOptions(this.integration.config),
);
if (!commitResponse.ok) {
const message = `Failed to retrieve commits from ${commitApiUrl}, ${commitResponse.status} ${commitResponse.statusText}`;
if (commitResponse.status === 404) {
if (!branchListResponse.ok) {
const message = `Failed to retrieve branch list from ${branchListUrl}, ${branchListResponse.status} ${branchListResponse.statusText}`;
if (branchListResponse.status === 404) {
throw new NotFoundError(message);
}
throw new Error(message);
}
const commits = await commitResponse.json();
const branchMatches = await branchListResponse.json();
// Handles case when a branch is provided in the URL
if (commits && commits.id) {
return commits.id.substring(0, 12);
if (branchMatches && branchMatches.size > 0) {
const exactBranchMatch = branchMatches.values.filter(
(branchDetails: { displayId: string }) =>
branchDetails.displayId === branch,
)[0];
return exactBranchMatch.latestCommit.substring(0, 12);
}
// Handles case when no branch is provided in the URL
if (
commits &&
commits.values &&
commits.values.length > 0 &&
commits.values[0].id
) {
return commits.values[0].id.substring(0, 12);
}
throw new Error(`Failed to read response from ${commitApiUrl}`);
throw new Error(
`Failed to find branch "${branch}" in property "displayId" of response to ${branchListUrl}`,
);
}
}