Skip to content

Commit c4c2b33

Browse files
committed
Adds support for fetching user issues from Linear
(#4543, #4579)
1 parent 4609219 commit c4c2b33

File tree

3 files changed

+66
-4
lines changed

3 files changed

+66
-4
lines changed

src/plus/integrations/providers/linear.ts

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { Account } from '../../../git/models/author';
44
import type { Issue, IssueShape } from '../../../git/models/issue';
55
import type { IssueOrPullRequest, IssueOrPullRequestType } from '../../../git/models/issueOrPullRequest';
66
import type { IssueResourceDescriptor, ResourceDescriptor } from '../../../git/models/resourceDescriptor';
7+
import { Logger } from '../../../system/logger';
78
import type { IntegrationAuthenticationProviderDescriptor } from '../authentication/integrationAuthenticationProvider';
89
import type { ProviderAuthenticationSession } from '../authentication/models';
910
import { IssuesIntegration } from '../models/issuesIntegration';
@@ -62,11 +63,44 @@ export class LinearIntegration extends IssuesIntegration<IssuesCloudHostIntegrat
6263
return metadata.domain;
6364
}
6465
protected override async searchProviderMyIssues(
65-
_session: ProviderAuthenticationSession,
66-
_resources?: ResourceDescriptor[],
67-
_cancellation?: CancellationToken,
66+
session: ProviderAuthenticationSession,
67+
resources?: ResourceDescriptor[],
68+
cancellation?: CancellationToken,
6869
): Promise<IssueShape[] | undefined> {
69-
return Promise.resolve(undefined);
70+
if (resources != null) {
71+
return undefined;
72+
}
73+
const api = await this.getProvidersApi();
74+
let cursor = undefined;
75+
let hasMore = false;
76+
let requestCount = 0;
77+
const issues = [];
78+
try {
79+
do {
80+
if (cancellation?.isCancellationRequested) {
81+
break;
82+
}
83+
const result = await api.getIssuesForCurrentUser(this.id, {
84+
accessToken: session.accessToken,
85+
cursor: cursor,
86+
});
87+
requestCount += 1;
88+
hasMore = result.paging?.more ?? false;
89+
cursor = result.paging?.cursor;
90+
const formattedIssues = result.values
91+
.map(issue => toIssueShape(issue, this))
92+
.filter((result): result is IssueShape => result != null);
93+
if (formattedIssues.length > 0) {
94+
issues.push(...formattedIssues);
95+
}
96+
} while (requestCount < maxPagesPerRequest && hasMore);
97+
} catch (ex) {
98+
if (issues.length === 0) {
99+
throw ex;
100+
}
101+
Logger.error(ex, 'searchProviderMyIssues');
102+
}
103+
return issues;
70104
}
71105
protected override getProviderIssueOrPullRequest(
72106
_session: ProviderAuthenticationSession,

src/plus/integrations/providers/models.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,11 @@ export type GetIssuesForReposFn = (
281281
options?: EnterpriseOptions,
282282
) => Promise<{ data: ProviderIssue[]; pageInfo?: PageInfo }>;
283283

284+
export type GetIssuesForCurrentUserFn = (
285+
input: PagingInput,
286+
options?: EnterpriseOptions,
287+
) => Promise<{ data: ProviderIssue[]; pageInfo?: PageInfo }>;
288+
284289
export type GetIssuesForRepoFn = (
285290
input: GetIssuesForRepoInput & PagingInput,
286291
options?: EnterpriseOptions,
@@ -365,6 +370,7 @@ export interface ProviderInfo extends ProviderMetadata {
365370
getPullRequestsForAzureProjectsFn?: GetPullRequestsForAzureProjectsFn;
366371
getIssueFn?: GetIssueFn;
367372
getIssuesForReposFn?: GetIssuesForReposFn;
373+
getIssuesForCurrentUserFn?: GetIssuesForCurrentUserFn;
368374
getIssuesForRepoFn?: GetIssuesForRepoFn;
369375
getIssuesForAzureProjectFn?: GetIssuesForAzureProjectFn;
370376
getCurrentUserFn?: GetCurrentUserFn;

src/plus/integrations/providers/providersApi.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import type {
4444
IssueFilter,
4545
MergePullRequestFn,
4646
PageInfo,
47+
PagingInput,
4748
PagingMode,
4849
ProviderAccount,
4950
ProviderAzureProject,
@@ -325,6 +326,7 @@ export class ProvidersApi {
325326
[IssuesCloudHostIntegrationId.Linear]: {
326327
...providersMetadata[IssuesCloudHostIntegrationId.Linear],
327328
provider: providerApis.linear,
329+
getIssuesForCurrentUserFn: providerApis.linear.getIssuesForCurrentUser.bind(providerApis.linear),
328330
},
329331
[IssuesCloudHostIntegrationId.Trello]: {
330332
...providersMetadata[IssuesCloudHostIntegrationId.Trello],
@@ -1035,6 +1037,26 @@ export class ProvidersApi {
10351037
);
10361038
}
10371039

1040+
async getIssuesForCurrentUser(
1041+
providerId: IntegrationIds,
1042+
options?: PagingInput & { accessToken?: string; isPAT?: boolean; baseUrl?: string },
1043+
): Promise<PagedResult<ProviderIssue>> {
1044+
const { provider, token } = await this.ensureProviderTokenAndFunction(
1045+
providerId,
1046+
'getIssuesForCurrentUserFn',
1047+
options?.accessToken,
1048+
);
1049+
return this.getPagedResult<ProviderIssue>(
1050+
provider,
1051+
options,
1052+
provider.getIssuesForCurrentUserFn,
1053+
token,
1054+
options?.cursor ?? undefined,
1055+
options?.isPAT,
1056+
options?.baseUrl,
1057+
);
1058+
}
1059+
10381060
async getIssuesForAzureProject(
10391061
providerId: GitCloudHostIntegrationId.AzureDevOps | GitSelfManagedHostIntegrationId.AzureDevOpsServer,
10401062
namespace: string,

0 commit comments

Comments
 (0)