Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: add reviewers parameter to UpdatePullRequest#285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
mattdholloway merged 32 commits intogithub:mainfromMayorFaj:feat/259/assign-reviewers
Jul 31, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
32 commits
Select commitHold shift + click to select a range
3234755
feat: add reviewers parameter to UpdatePullRequest and update tests
MayorFajApr 15, 2025
9db748b
Merge branch 'main' into feat/259/assign-reviewers
MayorFajApr 17, 2025
a84ede9
Merge branch 'main' into feat/259/assign-reviewers
MayorFajApr 17, 2025
276ac8d
Merge branch 'main' into feat/259/assign-reviewers
MayorFajApr 18, 2025
53d0833
Merge branch 'main' into feat/259/assign-reviewers
MayorFajApr 22, 2025
c4de80b
Merge branch 'main' into feat/259/assign-reviewers
MayorFajApr 22, 2025
0e51a09
Merge branch 'main' into feat/259/assign-reviewers
MayorFajApr 23, 2025
b9d2e28
Merge branch 'main' into feat/259/assign-reviewers
MayorFajApr 30, 2025
9ac7250
Merge branch 'main' into feat/259/assign-reviewers
MayorFajMay 5, 2025
71dcedf
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJun 25, 2025
5c85a09
Update pullrequests.go
MayorFajJun 25, 2025
b09f589
feat: enhance update pull request functionality with reviewers support
MayorFajJun 25, 2025
53e2708
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJun 26, 2025
7676eae
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJun 28, 2025
9209f5c
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJun 30, 2025
6f21c3f
update README to clarify optional reviewers parameter in API document…
MayorFajJun 30, 2025
8a6cabf
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJul 1, 2025
4e28ee7
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJul 2, 2025
432907e
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJul 3, 2025
0474365
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJul 9, 2025
20bfead
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJul 16, 2025
5650e1d
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJul 19, 2025
0674183
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJul 25, 2025
046f994
feat: enhance UpdatePullRequest to return early if no updates or revi…
MayorFajJul 25, 2025
90eb11a
Add updating draft state to `update_pull_request` tool (#774)
mattdhollowayJul 29, 2025
033f613
Add support for org-level discussions in list_discussions tool (#775)
tommaso-moroJul 29, 2025
94cef70
refactor: streamline UpdatePullRequest logic and enhance test cases f…
MayorFajJul 29, 2025
d89e522
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJul 29, 2025
5ea322b
refactor: remove redundant draft update tests and streamline UpdatePu…
MayorFajJul 29, 2025
be359ea
test: add unit tests for updating pull request draft state
MayorFajJul 29, 2025
1934e2a
Merge branch 'main' into feat/259/assign-reviewers
MayorFajJul 30, 2025
c1b9a46
refactor: simplify UpdatePullRequest tests by removing unused mock data
MayorFajJul 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletionsREADME.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -766,6 +766,7 @@ The following sets of tools are available (all are on by default):
- `owner`: Repository owner (string, required)
- `pullNumber`: Pull request number to update (number, required)
- `repo`: Repository name (string, required)
- `reviewers`: GitHub usernames to request reviews from (string[], optional)
- `state`: New state (string, optional)
- `title`: New title (string, optional)

Expand Down
7 changes: 7 additions & 0 deletionspkg/github/__toolsnaps__/update_pull_request.snap
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,6 +34,13 @@
"description": "Repository name",
"type": "string"
},
"reviewers": {
"description": "GitHub usernames to request reviews from",
"items": {
"type": "string"
},
"type": "array"
},
"state": {
"description": "New state",
"enum": [
Expand Down
3 changes: 1 addition & 2 deletionspkg/github/discussions_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -87,7 +87,6 @@ var (
"url": "https://github.com/owner/.github/discussions/4",
"category": map[string]any{"name": "General"},
},

}

// Ordered mock responses
Expand DownExpand Up@@ -190,7 +189,7 @@ var (
"startCursor": "",
"endCursor": "",
},
"totalCount": 4,
"totalCount": 4,
},
},
})
Expand Down
56 changes: 54 additions & 2 deletionspkg/github/pullrequests.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -241,6 +241,12 @@ func UpdatePullRequest(getClient GetClientFn, getGQLClient GetGQLClientFn, t tra
mcp.WithBoolean("maintainer_can_modify",
mcp.Description("Allow maintainer edits"),
),
mcp.WithArray("reviewers",
mcp.Description("GitHub usernames to request reviews from"),
mcp.Items(map[string]interface{}{
"type": "string",
}),
),
),
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
owner, err := RequiredParam[string](request, "owner")
Expand All@@ -256,15 +262,17 @@ func UpdatePullRequest(getClient GetClientFn, getGQLClient GetGQLClientFn, t tra
return mcp.NewToolResultError(err.Error()), nil
}

// Check if draft parameter is provided
draftProvided := request.GetArguments()["draft"] != nil
var draftValue bool
if draftProvided {
draftValue, err = OptionalParam[bool](request, "draft")
if err != nil {
returnnil, err
returnmcp.NewToolResultError(err.Error()), nil
}
}

// Build the update struct only with provided fields
update := &github.PullRequest{}
restUpdateNeeded := false

Expand DownExpand Up@@ -303,10 +311,18 @@ func UpdatePullRequest(getClient GetClientFn, getGQLClient GetGQLClientFn, t tra
restUpdateNeeded = true
}

if !restUpdateNeeded && !draftProvided {
// Handle reviewers separately
reviewers, err := OptionalStringArrayParam(request, "reviewers")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}

// If no updates, no draft change, and no reviewers, return error early
if !restUpdateNeeded && !draftProvided && len(reviewers) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

We could simplify it to
!(restUpdateNeeded || draftProvided || len(reviewers) != 0)

return mcp.NewToolResultError("No update parameters provided."), nil
}

// Handle REST API updates (title, body, state, base, maintainer_can_modify)
if restUpdateNeeded {
client, err := getClient(ctx)
if err != nil {
Expand All@@ -332,6 +348,7 @@ func UpdatePullRequest(getClient GetClientFn, getGQLClient GetGQLClientFn, t tra
}
}

// Handle draft status changes using GraphQL
if draftProvided {
gqlClient, err := getGQLClient(ctx)
if err != nil {
Expand DownExpand Up@@ -397,6 +414,41 @@ func UpdatePullRequest(getClient GetClientFn, getGQLClient GetGQLClientFn, t tra
}
}

// Handle reviewer requests
if len(reviewers) > 0 {
client, err := getClient(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
}

reviewersRequest := github.ReviewersRequest{
Reviewers: reviewers,
}

_, resp, err := client.PullRequests.RequestReviewers(ctx, owner, repo, pullNumber, reviewersRequest)
if err != nil {
return ghErrors.NewGitHubAPIErrorResponse(ctx,
"failed to request reviewers",
resp,
err,
), nil
}
defer func() {
if resp != nil && resp.Body != nil {
_ = resp.Body.Close()
}
}()

if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
return mcp.NewToolResultError(fmt.Sprintf("failed to request reviewers: %s", string(body))), nil
}
}

// Get the final state of the PR to return
client, err := getClient(ctx)
if err != nil {
return nil, err
Expand Down
78 changes: 75 additions & 3 deletionspkg/github/pullrequests_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -151,6 +151,7 @@ func Test_UpdatePullRequest(t *testing.T) {
assert.Contains(t, tool.InputSchema.Properties, "state")
assert.Contains(t, tool.InputSchema.Properties, "base")
assert.Contains(t, tool.InputSchema.Properties, "maintainer_can_modify")
assert.Contains(t, tool.InputSchema.Properties, "reviewers")
assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pullNumber"})

// Setup mock PR for success case
Expand All@@ -173,6 +174,17 @@ func Test_UpdatePullRequest(t *testing.T) {
State: github.Ptr("closed"), // State updated
}

// Mock PR for when there are no updates but we still need a response
mockPRWithReviewers := &github.PullRequest{
Number: github.Ptr(42),
Title: github.Ptr("Test PR"),
State: github.Ptr("open"),
RequestedReviewers: []*github.User{
{Login: github.Ptr("reviewer1")},
{Login: github.Ptr("reviewer2")},
},
}

tests := []struct {
name string
mockedClient *http.Client
Expand DownExpand Up@@ -238,6 +250,28 @@ func Test_UpdatePullRequest(t *testing.T) {
expectError: false,
expectedPR: mockClosedPR,
},
{
name: "successful PR update with reviewers",
mockedClient: mock.NewMockedHTTPClient(
// Mock for RequestReviewers call, returning the PR with reviewers
mock.WithRequestMatch(
mock.PostReposPullsRequestedReviewersByOwnerByRepoByPullNumber,
mockPRWithReviewers,
),
mock.WithRequestMatch(
mock.GetReposPullsByOwnerByRepoByPullNumber,
mockPRWithReviewers,
),
),
requestArgs: map[string]interface{}{
"owner": "owner",
"repo": "repo",
"pullNumber": float64(42),
"reviewers": []interface{}{"reviewer1", "reviewer2"},
},
expectError: false,
expectedPR: mockPRWithReviewers,
},
{
name: "successful PR update (title only)",
mockedClient: mock.NewMockedHTTPClient(
Expand DownExpand Up@@ -295,6 +329,27 @@ func Test_UpdatePullRequest(t *testing.T) {
expectError: true,
expectedErrMsg: "failed to update pull request",
},
{
name: "request reviewers fails",
mockedClient: mock.NewMockedHTTPClient(
// Then reviewer request fails
mock.WithRequestMatchHandler(
mock.PostReposPullsRequestedReviewersByOwnerByRepoByPullNumber,
http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusUnprocessableEntity)
_, _ = w.Write([]byte(`{"message": "Invalid reviewers"}`))
}),
),
),
requestArgs: map[string]interface{}{
"owner": "owner",
"repo": "repo",
"pullNumber": float64(42),
"reviewers": []interface{}{"invalid-user"},
},
expectError: true,
expectedErrMsg: "failed to request reviewers",
},
}

for _, tc := range tests {
Expand DownExpand Up@@ -347,6 +402,26 @@ func Test_UpdatePullRequest(t *testing.T) {
if tc.expectedPR.MaintainerCanModify != nil {
assert.Equal(t, *tc.expectedPR.MaintainerCanModify, *returnedPR.MaintainerCanModify)
}

// Check reviewers if they exist in the expected PR
if len(tc.expectedPR.RequestedReviewers) > 0 {
assert.NotNil(t, returnedPR.RequestedReviewers)
assert.Equal(t, len(tc.expectedPR.RequestedReviewers), len(returnedPR.RequestedReviewers))

// Create maps of reviewer logins for easy comparison
expectedReviewers := make(map[string]bool)
for _, reviewer := range tc.expectedPR.RequestedReviewers {
expectedReviewers[*reviewer.Login] = true
}

actualReviewers := make(map[string]bool)
for _, reviewer := range returnedPR.RequestedReviewers {
actualReviewers[*reviewer.Login] = true
}

// Compare the maps
assert.Equal(t, expectedReviewers, actualReviewers)
}
})
}
}
Expand DownExpand Up@@ -529,9 +604,6 @@ func Test_UpdatePullRequest_Draft(t *testing.T) {
err = json.Unmarshal([]byte(textContent.Text), &returnedPR)
require.NoError(t, err)
assert.Equal(t, *tc.expectedPR.Number, *returnedPR.Number)
if tc.expectedPR.Draft != nil {
assert.Equal(t, *tc.expectedPR.Draft, *returnedPR.Draft)
}
})
}
}
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp