UNPKG

github-pr-automation

Version:

MCP server and CLI for automated GitHub PR management, review resolution, and workflow optimization

86 lines 3.41 kB
import { ResolveReviewThreadInputSchema, } from "./schema.js"; import { parsePRIdentifier } from "../../utils/parser.js"; /** * Resolve a GitHub review thread * @param client - GitHub client instance * @param input - Input containing PR identifier and thread/comment ID * @returns Promise resolving to resolution status */ export async function handleResolveReviewThread(client, input) { const parsed = ResolveReviewThreadInputSchema.parse(input); // Parse PR (needed for REST API calls to convert numeric comment IDs) const pr = parsePRIdentifier(parsed.pr); const octokit = client.getOctokit(); // Resolve thread id from comment if needed let threadId = parsed.thread_id; if (!threadId && parsed.comment_id) { // Support both GraphQL node IDs and numeric REST IDs for comment_id let commentNodeId = parsed.comment_id; if (/^\d+$/.test(parsed.comment_id)) { // Numeric ID - convert via REST API to get GraphQL node_id const { data } = await octokit.rest.pulls.getReviewComment({ owner: pr.owner, repo: pr.repo, comment_id: Number(parsed.comment_id), }); // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access commentNodeId = data.node_id; if (!commentNodeId) { throw new Error("Unable to get GraphQL node_id from REST comment"); } } const threadQuery = ` query($commentId: ID!) { node(id: $commentId) { ... on PullRequestReviewComment { pullRequestReviewThread { id, isResolved } } } } `; const resp = await octokit.graphql(threadQuery, { commentId: commentNodeId, }); threadId = resp ?.node?.pullRequestReviewThread?.id; if (!threadId) { throw new Error("Unable to resolve thread_id from comment_id"); } } // Check current resolution status by fetching the specific thread const statusQuery = ` query($threadId: ID!) { node(id: $threadId) { ... on PullRequestReviewThread { id isResolved } } } `; // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment const statusResp = (await octokit.graphql(statusQuery, { threadId })); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access const threadNode = statusResp?.node; if (threadNode && threadNode.isResolved) { return { ok: true, thread_id: threadId, alreadyResolved: true, message: "Thread already resolved", }; } const mutation = ` mutation($threadId: ID!) { resolveReviewThread(input: { threadId: $threadId }) { thread { id isResolved } } } `; // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment const mutResp = (await octokit.graphql(mutation, { threadId })); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access const isResolved = Boolean(mutResp?.resolveReviewThread?.thread?.isResolved); return { ok: isResolved, thread_id: threadId, alreadyResolved: false }; } //# sourceMappingURL=handler.js.map