Skip to content

Commit c74020c

Browse files
committed
simplify pr
1 parent 89ef419 commit c74020c

File tree

6 files changed

+26
-487
lines changed

6 files changed

+26
-487
lines changed

src/platform/github/common/githubAPI.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import { ILogService } from '../../log/common/logService';
77
import { IFetcherService } from '../../networking/common/fetcherService';
88
import { ITelemetryService } from '../../telemetry/common/telemetry';
9-
import { vClosePullRequestResponse } from './githubAPIValidators';
109

1110
export interface PullRequestSearchItem {
1211
id: string;
@@ -359,17 +358,12 @@ export async function closePullRequest(
359358
return false;
360359
}
361360

362-
const validation = vClosePullRequestResponse().validate(result);
363-
if (validation.error) {
364-
logService.error(`[GitHubAPI] Failed to validate close pull request response: ${validation.error.message}`);
365-
return false;
366-
}
367-
368-
const success = validation.content.state === 'closed';
361+
const response = result as { state: string };
362+
const success = response.state === 'closed';
369363
if (success) {
370364
logService.debug(`[GitHubAPI] Successfully closed pull request ${owner}/${repo}#${pullNumber}`);
371365
} else {
372-
logService.error(`[GitHubAPI] Failed to close pull request ${owner}/${repo}#${pullNumber}. Its state is ${validation.content.state}`);
366+
logService.error(`[GitHubAPI] Failed to close pull request ${owner}/${repo}#${pullNumber}. Its state is ${response.state}`);
373367
}
374368
return success;
375369
}

src/platform/github/common/githubAPIValidators.ts

Lines changed: 3 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,10 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { IValidator, vArray, vEnum, vNull, vNumber, vObj, vRequired, vString, vUnion } from '../../configuration/common/validator';
7-
import { CustomAgentListItem, JobInfo, PullRequestFile } from './githubService';
8-
import { SessionInfo } from './githubAPI';
6+
import { IValidator, vArray, vNumber, vObj, vRequired, vString } from '../../configuration/common/validator';
7+
import { CustomAgentListItem, JobInfo } from './githubService';
98

10-
// Validator for IOctoKitUser
11-
export interface IOctoKitUser {
12-
login: string;
13-
name: string | null;
14-
avatar_url: string;
15-
}
16-
17-
export const vOctoKitUser = (): IValidator<IOctoKitUser> => vObj({
18-
login: vRequired(vString()),
19-
name: vRequired(vUnion(vString(), vNull())), // Allow string or null
20-
avatar_url: vRequired(vString()),
21-
});
22-
23-
// Validator for Actor (used in JobInfo and RemoteAgentJobResponse)
9+
// Validator for Actor (used in JobInfo)
2410
const vActor = () => vObj({
2511
id: vRequired(vNumber()),
2612
login: vRequired(vString()),
@@ -52,35 +38,6 @@ export const vJobInfo = (): IValidator<JobInfo> => vObj({
5238
event_identifiers: vArray(vString()),
5339
});
5440

55-
// Validator for RemoteAgentJobResponse
56-
export interface RemoteAgentJobResponse {
57-
job_id: string;
58-
session_id: string;
59-
actor: {
60-
id: number;
61-
login: string;
62-
};
63-
created_at: string;
64-
updated_at: string;
65-
}
66-
67-
export const vRemoteAgentJobResponse = (): IValidator<RemoteAgentJobResponse> => vObj({
68-
job_id: vRequired(vString()),
69-
session_id: vRequired(vString()),
70-
actor: vRequired(vActor()),
71-
created_at: vRequired(vString()),
72-
updated_at: vRequired(vString()),
73-
});
74-
75-
// Validator for ErrorResponseWithStatusCode
76-
export interface ErrorResponseWithStatusCode {
77-
status: number;
78-
}
79-
80-
export const vErrorResponseWithStatusCode = (): IValidator<ErrorResponseWithStatusCode> => vObj({
81-
status: vRequired(vNumber()),
82-
});
83-
8441
// Validator for CustomAgentListItem
8542
export const vCustomAgentListItem = (): IValidator<CustomAgentListItem> => vObj({
8643
name: vRequired(vString()),
@@ -102,90 +59,3 @@ export interface GetCustomAgentsResponse {
10259
export const vGetCustomAgentsResponse = (): IValidator<GetCustomAgentsResponse> => vObj({
10360
agents: vRequired(vArray(vCustomAgentListItem())),
10461
});
105-
106-
// Validator for PullRequestFile
107-
export const vPullRequestFile = (): IValidator<PullRequestFile> => vObj({
108-
filename: vRequired(vString()),
109-
status: vRequired(vEnum('added', 'removed', 'modified', 'renamed', 'copied', 'changed', 'unchanged')),
110-
additions: vRequired(vNumber()),
111-
deletions: vRequired(vNumber()),
112-
changes: vRequired(vNumber()),
113-
patch: vString(),
114-
previous_filename: vString(),
115-
});
116-
117-
// Validator for SessionInfo
118-
export const vSessionInfo = (): IValidator<SessionInfo> => vObj({
119-
id: vRequired(vString()),
120-
name: vRequired(vString()),
121-
user_id: vRequired(vNumber()),
122-
agent_id: vRequired(vNumber()),
123-
logs: vRequired(vString()),
124-
logs_blob_id: vRequired(vString()),
125-
state: vRequired(vEnum('completed', 'in_progress', 'failed', 'queued')),
126-
owner_id: vRequired(vNumber()),
127-
repo_id: vRequired(vNumber()),
128-
resource_type: vRequired(vString()),
129-
resource_id: vRequired(vNumber()),
130-
last_updated_at: vRequired(vString()),
131-
created_at: vRequired(vString()),
132-
completed_at: vRequired(vString()),
133-
event_type: vRequired(vString()),
134-
workflow_run_id: vRequired(vNumber()),
135-
premium_requests: vRequired(vNumber()),
136-
error: vRequired(vUnion(vString(), vNull())), // Allow string or null
137-
resource_global_id: vRequired(vString()),
138-
});
139-
140-
// Validator for sessions response wrapper
141-
export interface SessionsResponse {
142-
sessions: SessionInfo[];
143-
}
144-
145-
export const vSessionsResponse = (): IValidator<SessionsResponse> => vObj({
146-
sessions: vRequired(vArray(vSessionInfo())),
147-
});
148-
149-
// Validator for file content response from GitHub API
150-
export interface FileContentResponse {
151-
content: string;
152-
encoding: string;
153-
}
154-
155-
export const vFileContentResponse = (): IValidator<FileContentResponse> => vObj({
156-
content: vRequired(vString()),
157-
encoding: vRequired(vString()),
158-
});
159-
160-
// Validator for close pull request response
161-
export interface ClosePullRequestResponse {
162-
state: string;
163-
}
164-
165-
export const vClosePullRequestResponse = (): IValidator<ClosePullRequestResponse> => vObj({
166-
state: vRequired(vString()),
167-
});
168-
169-
// Validator for repository item
170-
export interface RepositoryItem {
171-
name: string;
172-
path: string;
173-
type: 'file' | 'dir';
174-
html_url: string;
175-
}
176-
177-
export const vRepositoryItem = (): IValidator<RepositoryItem> => vObj({
178-
name: vRequired(vString()),
179-
path: vRequired(vString()),
180-
type: vRequired(vEnum('file', 'dir')),
181-
html_url: vRequired(vString()),
182-
});
183-
184-
// Validator for repository content response (file)
185-
export interface RepositoryContentItem {
186-
content: string;
187-
}
188-
189-
export const vRepositoryContentItem = (): IValidator<RepositoryContentItem> => vObj({
190-
content: vRequired(vString()),
191-
});

src/platform/github/common/githubService.ts

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import { ILogService } from '../../log/common/logService';
1111
import { IFetcherService } from '../../networking/common/fetcherService';
1212
import { ITelemetryService } from '../../telemetry/common/telemetry';
1313
import { addPullRequestCommentGraphQLRequest, closePullRequest, getPullRequestFromGlobalId, makeGitHubAPIRequest, makeGitHubAPIRequestWithPagination, makeSearchGraphQLRequest, PullRequestComment, PullRequestSearchItem, SessionInfo } from './githubAPI';
14-
import { vArray } from '../../configuration/common/validator';
15-
import { vFileContentResponse, vGetCustomAgentsResponse, vJobInfo, vOctoKitUser, vPullRequestFile } from './githubAPIValidators';
14+
import { vGetCustomAgentsResponse, vJobInfo } from './githubAPIValidators';
1615

1716
export type IGetRepositoryInfoResponseData = Endpoints["GET /repos/{owner}/{repo}"]["response"]["data"];
1817

@@ -283,12 +282,7 @@ export class BaseOctoKitService {
283282
if (!response) {
284283
return undefined;
285284
}
286-
const validation = vOctoKitUser().validate(response);
287-
if (validation.error) {
288-
this._logService.error(`[GitHubService] Failed to validate user response: ${validation.error.message}`);
289-
return undefined;
290-
}
291-
return validation.content;
285+
return response as IOctoKitUser;
292286
}
293287

294288
async getTeamMembershipWithToken(teamId: number, token: string, username: string): Promise<any | undefined> {
@@ -377,12 +371,7 @@ export class BaseOctoKitService {
377371
if (!result) {
378372
return [];
379373
}
380-
const validation = vArray(vPullRequestFile()).validate(result);
381-
if (validation.error) {
382-
this._logService.error(`[GitHubService] Failed to validate pull request files response: ${validation.error.message}`);
383-
return [];
384-
}
385-
return validation.content;
374+
return result as PullRequestFile[];
386375
}
387376

388377
protected async closePullRequestWithToken(owner: string, repo: string, pullNumber: number, token: string): Promise<boolean> {
@@ -396,14 +385,9 @@ export class BaseOctoKitService {
396385
return '';
397386
}
398387

399-
const validation = vFileContentResponse().validate(response);
400-
if (validation.error) {
401-
this._logService.error(`[GitHubService] Failed to validate file content response: ${validation.error.message}`);
402-
return '';
403-
}
404-
405-
if (validation.content.encoding === 'base64') {
406-
return decodeBase64(validation.content.content.replace(/\n/g, '')).toString();
388+
const fileContent = response as { content: string; encoding: string };
389+
if (fileContent.encoding === 'base64') {
390+
return decodeBase64(fileContent.content.replace(/\n/g, '')).toString();
407391
} else {
408392
return '';
409393
}

src/platform/github/common/octoKitServiceImpl.ts

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import { IFetcherService } from '../../networking/common/fetcherService';
99
import { ITelemetryService } from '../../telemetry/common/telemetry';
1010
import { PullRequestComment, PullRequestSearchItem, SessionInfo } from './githubAPI';
1111
import { BaseOctoKitService, CustomAgentListItem, ErrorResponseWithStatusCode, IOctoKitService, IOctoKitUser, JobInfo, PullRequestFile, RemoteAgentJobPayload, RemoteAgentJobResponse } from './githubService';
12-
import { vErrorResponseWithStatusCode, vRemoteAgentJobResponse, vSessionInfo, vSessionsResponse } from './githubAPIValidators';
13-
import { vString } from '../../configuration/common/validator';
1412

1513
export class OctoKitService extends BaseOctoKitService implements IOctoKitService {
1614
declare readonly _serviceBrand: undefined;
@@ -59,12 +57,8 @@ export class OctoKitService extends BaseOctoKitService implements IOctoKitServic
5957
if (!response) {
6058
return [];
6159
}
62-
const validation = vSessionsResponse().validate(response);
63-
if (validation.error) {
64-
this._logService.error(`[OctoKitService] Failed to validate sessions response: ${validation.error.message}`);
65-
return [];
66-
}
67-
return validation.content.sessions;
60+
const sessionsResponse = response as { sessions: SessionInfo[] };
61+
return sessionsResponse.sessions;
6862
}
6963

7064
async getSessionLogs(sessionId: string): Promise<string> {
@@ -79,12 +73,7 @@ export class OctoKitService extends BaseOctoKitService implements IOctoKitServic
7973
if (!response) {
8074
return '';
8175
}
82-
const validation = vString().validate(response);
83-
if (validation.error) {
84-
this._logService.error(`[OctoKitService] Failed to validate session logs response: ${validation.error.message}`);
85-
return '';
86-
}
87-
return validation.content;
76+
return response as string;
8877
}
8978

9079
async getSessionInfo(sessionId: string): Promise<SessionInfo> {
@@ -101,21 +90,16 @@ export class OctoKitService extends BaseOctoKitService implements IOctoKitServic
10190
}
10291

10392
// The response might be a string (JSON) or already parsed
104-
let parsedResponse: unknown = response;
93+
let parsedResponse: SessionInfo = response as SessionInfo;
10594
if (typeof response === 'string') {
10695
try {
107-
parsedResponse = JSON.parse(response);
96+
parsedResponse = JSON.parse(response) as SessionInfo;
10897
} catch (e) {
10998
throw new Error('Failed to parse session info response');
11099
}
111100
}
112101

113-
const validation = vSessionInfo().validate(parsedResponse);
114-
if (validation.error) {
115-
this._logService.error(`[OctoKitService] Failed to validate session info response: ${validation.error.message}`);
116-
throw new Error(`Invalid session info response: ${validation.error.message}`);
117-
}
118-
return validation.content;
102+
return parsedResponse;
119103
}
120104

121105
async postCopilotAgentJob(owner: string, name: string, apiVersion: string, payload: RemoteAgentJobPayload): Promise<RemoteAgentJobResponse | ErrorResponseWithStatusCode> {
@@ -128,19 +112,7 @@ export class OctoKitService extends BaseOctoKitService implements IOctoKitServic
128112
throw new Error('No response received from post copilot agent job');
129113
}
130114

131-
// Try to validate as RemoteAgentJobResponse first, then as ErrorResponseWithStatusCode
132-
const jobResponseValidation = vRemoteAgentJobResponse().validate(response);
133-
if (!jobResponseValidation.error) {
134-
return jobResponseValidation.content;
135-
}
136-
137-
const errorResponseValidation = vErrorResponseWithStatusCode().validate(response);
138-
if (!errorResponseValidation.error) {
139-
return errorResponseValidation.content;
140-
}
141-
142-
this._logService.error(`[OctoKitService] Failed to validate post copilot agent job response: ${jobResponseValidation.error.message}`);
143-
throw new Error(`Invalid post copilot agent job response: ${jobResponseValidation.error.message}`);
115+
return response as RemoteAgentJobResponse | ErrorResponseWithStatusCode;
144116
}
145117

146118
async getJobByJobId(owner: string, repo: string, jobId: string, userAgent: string): Promise<JobInfo> {

src/platform/github/node/githubRepositoryService.ts

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import { IFetcherService } from '../../networking/common/fetcherService';
88
import { ITelemetryService } from '../../telemetry/common/telemetry';
99
import { makeGitHubAPIRequest } from '../common/githubAPI';
1010
import { GithubRepositoryItem, IGetRepositoryInfoResponseData, IGithubRepositoryService } from '../common/githubService';
11-
import { vRepositoryContentItem, vRepositoryItem } from '../common/githubAPIValidators';
12-
import { vArray, vUnchecked } from '../../configuration/common/validator';
1311

1412
export class GithubRepositoryService implements IGithubRepositoryService {
1513

@@ -33,14 +31,8 @@ export class GithubRepositoryService implements IGithubRepositoryService {
3331
return undefined;
3432
}
3533

36-
// IGetRepositoryInfoResponseData is from @octokit/types which is a complex external type
37-
// We use vUnchecked here since it's a well-defined external API contract
38-
const validation = vUnchecked<IGetRepositoryInfoResponseData>().validate(response);
39-
if (validation.error) {
40-
this._logService.error(`[GithubRepositoryService] Failed to validate repository info response: ${validation.error.message}`);
41-
return undefined;
42-
}
43-
return validation.content;
34+
// IGetRepositoryInfoResponseData is from @octokit/types which is a well-defined external API contract
35+
return response as IGetRepositoryInfoResponseData;
4436
}
4537

4638
async getRepositoryInfo(owner: string, repo: string) {
@@ -79,13 +71,9 @@ export class GithubRepositoryService implements IGithubRepositoryService {
7971
}
8072

8173
// Response should be an array of repository items
82-
const validation = vArray(vRepositoryItem()).validate(response);
83-
if (validation.error) {
84-
this._logService.error(`[GithubRepositoryService] Failed to validate repository items response: ${validation.error.message}`);
85-
return [];
86-
}
74+
const items = response as Array<{ name: string; path: string; type: 'file' | 'dir'; html_url: string }>;
8775

88-
for (const child of validation.content) {
76+
for (const child of items) {
8977
paths.push({ name: child.name, path: child.path, type: child.type, html_url: child.html_url });
9078
if (child.type === 'dir') {
9179
paths.push(...await this.getRepositoryItems(org, repo, child.path));
@@ -109,13 +97,8 @@ export class GithubRepositoryService implements IGithubRepositoryService {
10997
return undefined;
11098
}
11199

112-
const validation = vRepositoryContentItem().validate(response);
113-
if (validation.error) {
114-
this._logService.error(`[GithubRepositoryService] Failed to validate repository content response: ${validation.error.message}`);
115-
return undefined;
116-
}
117-
118-
const content = Buffer.from(validation.content.content, 'base64');
100+
const fileContent = response as { content: string };
101+
const content = Buffer.from(fileContent.content, 'base64');
119102
return new Uint8Array(content);
120103
} catch (e) {
121104
this._logService.error(`Failed to fetch contents from ${org}:${repo}:${path}: ${e}`);

0 commit comments

Comments
 (0)