Skip to content

Commit 650aac6

Browse files
committed
feat: convert mark_pr_ready_for_review to set_pr_status tool
- Replace mark_pr_ready_for_review with set_pr_status tool - Add bidirectional PR status changes (draft ↔ ready_for_review) - Use enum parameter for status: "draft", "ready_for_review" - Implement GraphQL mutations for both directions - Add comprehensive test suite with 8 test scenarios - Remove deprecated MarkPullRequestReadyForReview function Addresses user feedback to provide enum-based PR status management with support for setting PRs to both draft and ready-for-review states.
1 parent 71b0916 commit 650aac6

File tree

3 files changed

+250
-49
lines changed

3 files changed

+250
-49
lines changed

pkg/github/pullrequests.go

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,13 +1607,13 @@ func newGQLIntPtr(i *int32) *githubv4.Int {
16071607
return &gi
16081608
}
16091609

1610-
// MarkPullRequestReadyForReview creates a tool to mark a draft pull request as ready for review.
1611-
// This uses the GraphQL API because the REST API does not support changing a PR from draft to ready-for-review.
1612-
func MarkPullRequestReadyForReview(getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (mcp.Tool, server.ToolHandlerFunc) {
1613-
return mcp.NewTool("mark_pr_ready_for_review",
1614-
mcp.WithDescription(t("TOOL_MARK_PR_READY_FOR_REVIEW_DESCRIPTION", "Mark a draft pull request as ready for review. Use this to change a pull request from draft state to ready for review.")),
1610+
// SetPRStatus creates a tool to set pull request status between draft and ready-for-review states.
1611+
// This uses the GraphQL API because the REST API does not support changing PR draft status.
1612+
func SetPRStatus(getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (mcp.Tool, server.ToolHandlerFunc) {
1613+
return mcp.NewTool("set_pr_status",
1614+
mcp.WithDescription(t("TOOL_SET_PR_STATUS_DESCRIPTION", "Set pull request status between draft and ready-for-review states. Use this to change a pull request from draft to ready-for-review or vice versa.")),
16151615
mcp.WithToolAnnotation(mcp.ToolAnnotation{
1616-
Title: t("TOOL_MARK_PR_READY_FOR_REVIEW_USER_TITLE", "Mark pull request ready for review"),
1616+
Title: t("TOOL_SET_PR_STATUS_USER_TITLE", "Set pull request status"),
16171617
ReadOnlyHint: toBoolPtr(false),
16181618
}),
16191619
mcp.WithString("owner",
@@ -1628,24 +1628,35 @@ func MarkPullRequestReadyForReview(getGQLClient GetGQLClientFn, t translations.T
16281628
mcp.Required(),
16291629
mcp.Description("Pull request number"),
16301630
),
1631+
mcp.WithString("status",
1632+
mcp.Required(),
1633+
mcp.Description("Target status for the pull request"),
1634+
mcp.Enum("draft", "ready_for_review"),
1635+
),
16311636
),
16321637
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
16331638
var params struct {
16341639
Owner string
16351640
Repo string
16361641
PullNumber int32
1642+
Status string
16371643
}
16381644
if err := mapstructure.Decode(request.Params.Arguments, &params); err != nil {
16391645
return mcp.NewToolResultError(err.Error()), nil
16401646
}
16411647

1648+
// Validate status parameter
1649+
if params.Status != "draft" && params.Status != "ready_for_review" {
1650+
return mcp.NewToolResultError("status must be either 'draft' or 'ready_for_review'"), nil
1651+
}
1652+
16421653
// Get the GraphQL client
16431654
client, err := getGQLClient(ctx)
16441655
if err != nil {
16451656
return mcp.NewToolResultError(fmt.Sprintf("failed to get GitHub GraphQL client: %v", err)), nil
16461657
}
16471658

1648-
// First, we need to get the GraphQL ID of the pull request
1659+
// First, we need to get the GraphQL ID of the pull request and its current status
16491660
var getPullRequestQuery struct {
16501661
Repository struct {
16511662
PullRequest struct {
@@ -1665,28 +1676,57 @@ func MarkPullRequestReadyForReview(getGQLClient GetGQLClientFn, t translations.T
16651676
return mcp.NewToolResultError(fmt.Sprintf("failed to get pull request: %v", err)), nil
16661677
}
16671678

1668-
// Check if the PR is already in non-draft state
1669-
if !getPullRequestQuery.Repository.PullRequest.IsDraft {
1670-
return mcp.NewToolResultText("Pull request is already marked as ready for review"), nil
1671-
}
1679+
currentIsDraft := bool(getPullRequestQuery.Repository.PullRequest.IsDraft)
1680+
targetIsDraft := params.Status == "draft"
16721681

1673-
// Now we can mark the PR as ready for review using the GraphQL mutation
1674-
var markReadyForReviewMutation struct {
1675-
MarkPullRequestReadyForReview struct {
1676-
PullRequest struct {
1677-
ID githubv4.ID // Required by GraphQL schema, but not used in response
1678-
}
1679-
} `graphql:"markPullRequestReadyForReview(input: $input)"`
1682+
// Check if the PR is already in the target state
1683+
if currentIsDraft == targetIsDraft {
1684+
if targetIsDraft {
1685+
return mcp.NewToolResultText("Pull request is already in draft state"), nil
1686+
} else {
1687+
return mcp.NewToolResultText("Pull request is already marked as ready for review"), nil
1688+
}
16801689
}
16811690

1682-
input := githubv4.MarkPullRequestReadyForReviewInput{
1683-
PullRequestID: getPullRequestQuery.Repository.PullRequest.ID,
1684-
}
1691+
// Perform the appropriate mutation based on target status
1692+
if targetIsDraft {
1693+
// Convert to draft
1694+
var convertToDraftMutation struct {
1695+
ConvertPullRequestToDraft struct {
1696+
PullRequest struct {
1697+
ID githubv4.ID // Required by GraphQL schema, but not used in response
1698+
}
1699+
} `graphql:"convertPullRequestToDraft(input: $input)"`
1700+
}
16851701

1686-
if err := client.Mutate(ctx, &markReadyForReviewMutation, input, nil); err != nil {
1687-
return mcp.NewToolResultError(fmt.Sprintf("failed to mark pull request as ready for review: %v", err)), nil
1688-
}
1702+
input := githubv4.ConvertPullRequestToDraftInput{
1703+
PullRequestID: getPullRequestQuery.Repository.PullRequest.ID,
1704+
}
1705+
1706+
if err := client.Mutate(ctx, &convertToDraftMutation, input, nil); err != nil {
1707+
return mcp.NewToolResultError(fmt.Sprintf("failed to convert pull request to draft: %v", err)), nil
1708+
}
16891709

1690-
return mcp.NewToolResultText("Pull request successfully marked as ready for review"), nil
1710+
return mcp.NewToolResultText("Pull request successfully converted to draft"), nil
1711+
} else {
1712+
// Mark as ready for review
1713+
var markReadyForReviewMutation struct {
1714+
MarkPullRequestReadyForReview struct {
1715+
PullRequest struct {
1716+
ID githubv4.ID // Required by GraphQL schema, but not used in response
1717+
}
1718+
} `graphql:"markPullRequestReadyForReview(input: $input)"`
1719+
}
1720+
1721+
input := githubv4.MarkPullRequestReadyForReviewInput{
1722+
PullRequestID: getPullRequestQuery.Repository.PullRequest.ID,
1723+
}
1724+
1725+
if err := client.Mutate(ctx, &markReadyForReviewMutation, input, nil); err != nil {
1726+
return mcp.NewToolResultError(fmt.Sprintf("failed to mark pull request as ready for review: %v", err)), nil
1727+
}
1728+
1729+
return mcp.NewToolResultText("Pull request successfully marked as ready for review"), nil
1730+
}
16911731
}
16921732
}

0 commit comments

Comments
 (0)