Skip to content

Commit fcbc256

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 c9cda90 commit fcbc256

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
@@ -1608,13 +1608,13 @@ func newGQLIntPtr(i *int32) *githubv4.Int {
16081608
return &gi
16091609
}
16101610

1611-
// MarkPullRequestReadyForReview creates a tool to mark a draft pull request as ready for review.
1612-
// This uses the GraphQL API because the REST API does not support changing a PR from draft to ready-for-review.
1613-
func MarkPullRequestReadyForReview(getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (mcp.Tool, server.ToolHandlerFunc) {
1614-
return mcp.NewTool("mark_pr_ready_for_review",
1615-
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.")),
1611+
// SetPRStatus creates a tool to set pull request status between draft and ready-for-review states.
1612+
// This uses the GraphQL API because the REST API does not support changing PR draft status.
1613+
func SetPRStatus(getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (mcp.Tool, server.ToolHandlerFunc) {
1614+
return mcp.NewTool("set_pr_status",
1615+
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.")),
16161616
mcp.WithToolAnnotation(mcp.ToolAnnotation{
1617-
Title: t("TOOL_MARK_PR_READY_FOR_REVIEW_USER_TITLE", "Mark pull request ready for review"),
1617+
Title: t("TOOL_SET_PR_STATUS_USER_TITLE", "Set pull request status"),
16181618
ReadOnlyHint: toBoolPtr(false),
16191619
}),
16201620
mcp.WithString("owner",
@@ -1629,24 +1629,35 @@ func MarkPullRequestReadyForReview(getGQLClient GetGQLClientFn, t translations.T
16291629
mcp.Required(),
16301630
mcp.Description("Pull request number"),
16311631
),
1632+
mcp.WithString("status",
1633+
mcp.Required(),
1634+
mcp.Description("Target status for the pull request"),
1635+
mcp.Enum("draft", "ready_for_review"),
1636+
),
16321637
),
16331638
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
16341639
var params struct {
16351640
Owner string
16361641
Repo string
16371642
PullNumber int32
1643+
Status string
16381644
}
16391645
if err := mapstructure.Decode(request.Params.Arguments, &params); err != nil {
16401646
return mcp.NewToolResultError(err.Error()), nil
16411647
}
16421648

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

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

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

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

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

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

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

0 commit comments

Comments
 (0)