Skip to content

Commit b921168

Browse files
committed
Implements issue retrieval for Bitbucket to show on StartWork list
(#4047, #4119)
1 parent 76d8ebe commit b921168

File tree

3 files changed

+99
-4
lines changed

3 files changed

+99
-4
lines changed

src/plus/integrations/providers/bitbucket.ts

+25-3
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,32 @@ export class BitbucketIntegration extends HostingIntegration<
240240
}
241241

242242
protected override async searchProviderMyIssues(
243-
_session: AuthenticationSession,
244-
_repos?: BitbucketRepositoryDescriptor[],
243+
session: AuthenticationSession,
244+
repos?: BitbucketRepositoryDescriptor[],
245245
): Promise<IssueShape[] | undefined> {
246-
return Promise.resolve(undefined);
246+
if (repos == null || repos.length === 0) return undefined;
247+
248+
const user = await this.getProviderCurrentAccount(session);
249+
if (user?.username == null) return undefined;
250+
251+
const workspaces = await this.getProviderResourcesForUser(session);
252+
if (workspaces == null || workspaces.length === 0) return undefined;
253+
254+
const api = await this.container.bitbucket;
255+
if (!api) return undefined;
256+
const issueResult = await flatSettled(
257+
repos.map(repo => {
258+
return api.getUsersIssuesForRepo(
259+
this,
260+
session.accessToken,
261+
user.id,
262+
repo.owner,
263+
repo.name,
264+
this.apiBaseUrl,
265+
);
266+
}),
267+
);
268+
return issueResult;
247269
}
248270

249271
protected override async providerOnConnect(): Promise<void> {

src/plus/integrations/providers/bitbucket/bitbucket.ts

+69-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
RequestClientError,
1414
RequestNotFoundError,
1515
} from '../../../../errors';
16+
import type { Issue } from '../../../../git/models/issue';
1617
import type { IssueOrPullRequest, IssueOrPullRequestType } from '../../../../git/models/issueOrPullRequest';
1718
import type { PullRequest } from '../../../../git/models/pullRequest';
1819
import type { Provider } from '../../../../git/models/remoteProvider';
@@ -25,7 +26,7 @@ import type { LogScope } from '../../../../system/logger.scope';
2526
import { getLogScope } from '../../../../system/logger.scope';
2627
import { maybeStopWatch } from '../../../../system/stopwatch';
2728
import type { BitbucketIssue, BitbucketPullRequest, BitbucketRepository } from './models';
28-
import { bitbucketIssueStateToState, fromBitbucketPullRequest } from './models';
29+
import { bitbucketIssueStateToState, fromBitbucketIssue, fromBitbucketPullRequest } from './models';
2930

3031
export class BitbucketApi implements Disposable {
3132
private readonly _disposable: Disposable;
@@ -92,6 +93,73 @@ export class BitbucketApi implements Disposable {
9293
return fromBitbucketPullRequest(response.values[0], provider);
9394
}
9495

96+
@debug<BitbucketApi['getUsersIssuesForRepo']>({ args: { 0: p => p.name, 1: '<token>' } })
97+
async getUsersIssuesForRepo(
98+
provider: Provider,
99+
token: string,
100+
userUuid: string,
101+
owner: string,
102+
repo: string,
103+
baseUrl: string,
104+
): Promise<Issue[] | undefined> {
105+
const scope = getLogScope();
106+
const query = encodeURIComponent(`assignee.uuid="${userUuid}" OR reporter.uuid="${userUuid}"`);
107+
108+
const response = await this.request<{
109+
values: BitbucketIssue[];
110+
pagelen: number;
111+
size: number;
112+
page: number;
113+
}>(
114+
provider,
115+
token,
116+
baseUrl,
117+
`repositories/${owner}/${repo}/issues?q=${query}`,
118+
{
119+
method: 'GET',
120+
},
121+
scope,
122+
);
123+
124+
if (!response?.values?.length) {
125+
return undefined;
126+
}
127+
return response.values.map(issue => fromBitbucketIssue(issue, provider));
128+
}
129+
130+
@debug<BitbucketApi['getIssue']>({ args: { 0: p => p.name, 1: '<token>' } })
131+
async getIssue(
132+
provider: Provider,
133+
token: string,
134+
owner: string,
135+
repo: string,
136+
id: string,
137+
baseUrl: string,
138+
): Promise<Issue | undefined> {
139+
const scope = getLogScope();
140+
141+
try {
142+
const response = await this.request<BitbucketIssue>(
143+
provider,
144+
token,
145+
baseUrl,
146+
`repositories/${owner}/${repo}/issues/${id}`,
147+
{
148+
method: 'GET',
149+
},
150+
scope,
151+
);
152+
153+
if (response) {
154+
return fromBitbucketIssue(response, provider);
155+
}
156+
return undefined;
157+
} catch (ex) {
158+
Logger.error(ex, scope);
159+
return undefined;
160+
}
161+
}
162+
95163
@debug<BitbucketApi['getIssueOrPullRequest']>({ args: { 0: p => p.name, 1: '<token>' } })
96164
public async getIssueOrPullRequest(
97165
provider: Provider,

src/plus/startWork/startWork.ts

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
import {
2222
ConnectIntegrationButton,
2323
OpenOnAzureDevOpsQuickInputButton,
24+
OpenOnBitbucketQuickInputButton,
2425
OpenOnGitHubQuickInputButton,
2526
OpenOnGitLabQuickInputButton,
2627
OpenOnJiraQuickInputButton,
@@ -96,6 +97,7 @@ export const supportedStartWorkIntegrations = [
9697
HostingIntegrationId.GitLab,
9798
SelfHostedIntegrationId.CloudGitLabSelfHosted,
9899
HostingIntegrationId.AzureDevOps,
100+
HostingIntegrationId.Bitbucket,
99101
IssueIntegrationId.Jira,
100102
];
101103
export type SupportedStartWorkIntegrationIds = (typeof supportedStartWorkIntegrations)[number];
@@ -483,6 +485,7 @@ export abstract class StartWorkBaseCommand extends QuickCommand<State> {
483485
onDidClickItemButton: (_quickpick, button, { item }) => {
484486
switch (button) {
485487
case OpenOnAzureDevOpsQuickInputButton:
488+
case OpenOnBitbucketQuickInputButton:
486489
case OpenOnGitHubQuickInputButton:
487490
case OpenOnGitLabQuickInputButton:
488491
case OpenOnJiraQuickInputButton:
@@ -716,6 +719,8 @@ function getOpenOnWebQuickInputButton(integrationId: string): QuickInputButton |
716719
switch (integrationId) {
717720
case HostingIntegrationId.AzureDevOps:
718721
return OpenOnAzureDevOpsQuickInputButton;
722+
case HostingIntegrationId.Bitbucket:
723+
return OpenOnBitbucketQuickInputButton;
719724
case HostingIntegrationId.GitHub:
720725
case SelfHostedIntegrationId.CloudGitHubEnterprise:
721726
return OpenOnGitHubQuickInputButton;

0 commit comments

Comments
 (0)