| |
| |
| |
| |
| |
| |
| |
|
|
| import { spawn } from 'child_process'; |
| import { execEnv } from '../lib/exec-utils.js'; |
|
|
| |
| const GITHUB_API_TIMEOUT_MS = 30000; |
|
|
| interface GraphQLMutationResponse { |
| data?: { |
| resolveReviewThread?: { |
| thread?: { isResolved: boolean; id: string } | null; |
| } | null; |
| unresolveReviewThread?: { |
| thread?: { isResolved: boolean; id: string } | null; |
| } | null; |
| }; |
| errors?: Array<{ message: string }>; |
| } |
|
|
| |
| |
| |
| export async function executeReviewThreadMutation( |
| projectPath: string, |
| threadId: string, |
| resolve: boolean |
| ): Promise<{ isResolved: boolean }> { |
| const mutationName = resolve ? 'resolveReviewThread' : 'unresolveReviewThread'; |
|
|
| const mutation = ` |
| mutation ${resolve ? 'ResolveThread' : 'UnresolveThread'}($threadId: ID!) { |
| ${mutationName}(input: { threadId: $threadId }) { |
| thread { |
| id |
| isResolved |
| } |
| } |
| }`; |
|
|
| const variables = { threadId }; |
| const requestBody = JSON.stringify({ query: mutation, variables }); |
|
|
| |
| let timeoutId: NodeJS.Timeout | undefined; |
|
|
| const response = await new Promise<GraphQLMutationResponse>((res, rej) => { |
| const gh = spawn('gh', ['api', 'graphql', '--input', '-'], { |
| cwd: projectPath, |
| env: execEnv, |
| }); |
|
|
| gh.on('error', (err) => { |
| clearTimeout(timeoutId); |
| rej(err); |
| }); |
|
|
| timeoutId = setTimeout(() => { |
| gh.kill(); |
| rej(new Error('GitHub GraphQL API request timed out')); |
| }, GITHUB_API_TIMEOUT_MS); |
|
|
| let stdout = ''; |
| let stderr = ''; |
| gh.stdout.on('data', (data: Buffer) => (stdout += data.toString())); |
| gh.stderr.on('data', (data: Buffer) => (stderr += data.toString())); |
|
|
| gh.on('close', (code) => { |
| clearTimeout(timeoutId); |
| if (code !== 0) { |
| return rej(new Error(`gh process exited with code ${code}: ${stderr}`)); |
| } |
| try { |
| res(JSON.parse(stdout)); |
| } catch (e) { |
| rej(e); |
| } |
| }); |
|
|
| gh.stdin.write(requestBody); |
| gh.stdin.end(); |
| }); |
|
|
| if (response.errors && response.errors.length > 0) { |
| throw new Error(response.errors[0].message); |
| } |
|
|
| const threadData = resolve |
| ? response.data?.resolveReviewThread?.thread |
| : response.data?.unresolveReviewThread?.thread; |
|
|
| if (!threadData) { |
| throw new Error('No thread data returned from GitHub API'); |
| } |
|
|
| return { isResolved: threadData.isResolved }; |
| } |
|
|