Skip to content

Commit c00857c

Browse files
Merge branch 'main' into cross-platform-licences
2 parents 9ddb049 + 07f6d11 commit c00857c

File tree

6 files changed

+243
-51
lines changed

6 files changed

+243
-51
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,6 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
284284
- `description`: Repository description (string, optional)
285285
- `private`: Whether the repository is private (boolean, optional)
286286
- `auto_init`: Auto-initialize with README (boolean, optional)
287-
- `gitignore_template`: Gitignore template name (string, optional)
288287

289288
- **get_file_contents** - Get contents of a file or directory
290289

pkg/github/issues.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ func createIssue(client *github.Client, t translations.TranslationHelperFunc) (t
261261
},
262262
),
263263
),
264+
mcp.WithNumber("milestone",
265+
mcp.Description("Milestone number"),
266+
),
264267
),
265268
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
266269
owner, err := requiredParam[string](request, "owner")
@@ -294,12 +297,24 @@ func createIssue(client *github.Client, t translations.TranslationHelperFunc) (t
294297
return mcp.NewToolResultError(err.Error()), nil
295298
}
296299

300+
// Get optional milestone
301+
milestone, err := optionalIntParam(request, "milestone")
302+
if err != nil {
303+
return mcp.NewToolResultError(err.Error()), nil
304+
}
305+
306+
var milestoneNum *int
307+
if milestone != 0 {
308+
milestoneNum = &milestone
309+
}
310+
297311
// Create the issue request
298312
issueRequest := &github.IssueRequest{
299313
Title: github.Ptr(title),
300314
Body: github.Ptr(body),
301315
Assignees: &assignees,
302316
Labels: &labels,
317+
Milestone: milestoneNum,
303318
}
304319

305320
issue, resp, err := client.Issues.Create(ctx, owner, repo, issueRequest)

pkg/github/issues_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ func Test_CreateIssue(t *testing.T) {
392392
assert.Contains(t, tool.InputSchema.Properties, "body")
393393
assert.Contains(t, tool.InputSchema.Properties, "assignees")
394394
assert.Contains(t, tool.InputSchema.Properties, "labels")
395+
assert.Contains(t, tool.InputSchema.Properties, "milestone")
395396
assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "title"})
396397

397398
// Setup mock issue for success case
@@ -403,6 +404,7 @@ func Test_CreateIssue(t *testing.T) {
403404
HTMLURL: github.Ptr("https://github.com/owner/repo/issues/123"),
404405
Assignees: []*github.User{{Login: github.Ptr("user1")}, {Login: github.Ptr("user2")}},
405406
Labels: []*github.Label{{Name: github.Ptr("bug")}, {Name: github.Ptr("help wanted")}},
407+
Milestone: &github.Milestone{Number: github.Ptr(5)},
406408
}
407409

408410
tests := []struct {
@@ -423,6 +425,7 @@ func Test_CreateIssue(t *testing.T) {
423425
"body": "This is a test issue",
424426
"labels": []any{"bug", "help wanted"},
425427
"assignees": []any{"user1", "user2"},
428+
"milestone": float64(5),
426429
}).andThen(
427430
mockResponse(t, http.StatusCreated, mockIssue),
428431
),
@@ -435,6 +438,7 @@ func Test_CreateIssue(t *testing.T) {
435438
"body": "This is a test issue",
436439
"assignees": []string{"user1", "user2"},
437440
"labels": []string{"bug", "help wanted"},
441+
"milestone": float64(5),
438442
},
439443
expectError: false,
440444
expectedIssue: mockIssue,

pkg/github/pullrequests_test.go

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,17 @@ func Test_ListPullRequests(t *testing.T) {
171171
{
172172
name: "successful PRs listing",
173173
mockedClient: mock.NewMockedHTTPClient(
174-
mock.WithRequestMatch(
174+
mock.WithRequestMatchHandler(
175175
mock.GetReposPullsByOwnerByRepo,
176-
mockPRs,
176+
expectQueryParams(t, map[string]string{
177+
"state": "all",
178+
"sort": "created",
179+
"direction": "desc",
180+
"per_page": "30",
181+
"page": "1",
182+
}).andThen(
183+
mockResponse(t, http.StatusOK, mockPRs),
184+
),
177185
),
178186
),
179187
requestArgs: map[string]interface{}{
@@ -281,9 +289,15 @@ func Test_MergePullRequest(t *testing.T) {
281289
{
282290
name: "successful merge",
283291
mockedClient: mock.NewMockedHTTPClient(
284-
mock.WithRequestMatch(
292+
mock.WithRequestMatchHandler(
285293
mock.PutReposPullsMergeByOwnerByRepoByPullNumber,
286-
mockMergeResult,
294+
expectRequestBody(t, map[string]interface{}{
295+
"commit_title": "Merge PR #42",
296+
"commit_message": "Merging awesome feature",
297+
"merge_method": "squash",
298+
}).andThen(
299+
mockResponse(t, http.StatusOK, mockMergeResult),
300+
),
287301
),
288302
),
289303
requestArgs: map[string]interface{}{
@@ -662,7 +676,11 @@ func Test_UpdatePullRequestBranch(t *testing.T) {
662676
mockedClient: mock.NewMockedHTTPClient(
663677
mock.WithRequestMatchHandler(
664678
mock.PutReposPullsUpdateBranchByOwnerByRepoByPullNumber,
665-
mockResponse(t, http.StatusAccepted, mockUpdateResult),
679+
expectRequestBody(t, map[string]interface{}{
680+
"expected_head_sha": "abcd1234",
681+
}).andThen(
682+
mockResponse(t, http.StatusAccepted, mockUpdateResult),
683+
),
666684
),
667685
),
668686
requestArgs: map[string]interface{}{
@@ -679,7 +697,9 @@ func Test_UpdatePullRequestBranch(t *testing.T) {
679697
mockedClient: mock.NewMockedHTTPClient(
680698
mock.WithRequestMatchHandler(
681699
mock.PutReposPullsUpdateBranchByOwnerByRepoByPullNumber,
682-
mockResponse(t, http.StatusAccepted, mockUpdateResult),
700+
expectRequestBody(t, map[string]interface{}{}).andThen(
701+
mockResponse(t, http.StatusAccepted, mockUpdateResult),
702+
),
683703
),
684704
),
685705
requestArgs: map[string]interface{}{
@@ -1030,9 +1050,14 @@ func Test_CreatePullRequestReview(t *testing.T) {
10301050
{
10311051
name: "successful review creation with body only",
10321052
mockedClient: mock.NewMockedHTTPClient(
1033-
mock.WithRequestMatch(
1053+
mock.WithRequestMatchHandler(
10341054
mock.PostReposPullsReviewsByOwnerByRepoByPullNumber,
1035-
mockReview,
1055+
expectRequestBody(t, map[string]interface{}{
1056+
"body": "Looks good!",
1057+
"event": "APPROVE",
1058+
}).andThen(
1059+
mockResponse(t, http.StatusOK, mockReview),
1060+
),
10361061
),
10371062
),
10381063
requestArgs: map[string]interface{}{
@@ -1048,9 +1073,15 @@ func Test_CreatePullRequestReview(t *testing.T) {
10481073
{
10491074
name: "successful review creation with commit_id",
10501075
mockedClient: mock.NewMockedHTTPClient(
1051-
mock.WithRequestMatch(
1076+
mock.WithRequestMatchHandler(
10521077
mock.PostReposPullsReviewsByOwnerByRepoByPullNumber,
1053-
mockReview,
1078+
expectRequestBody(t, map[string]interface{}{
1079+
"body": "Looks good!",
1080+
"event": "APPROVE",
1081+
"commit_id": "abcdef123456",
1082+
}).andThen(
1083+
mockResponse(t, http.StatusOK, mockReview),
1084+
),
10541085
),
10551086
),
10561087
requestArgs: map[string]interface{}{
@@ -1067,9 +1098,26 @@ func Test_CreatePullRequestReview(t *testing.T) {
10671098
{
10681099
name: "successful review creation with comments",
10691100
mockedClient: mock.NewMockedHTTPClient(
1070-
mock.WithRequestMatch(
1101+
mock.WithRequestMatchHandler(
10711102
mock.PostReposPullsReviewsByOwnerByRepoByPullNumber,
1072-
mockReview,
1103+
expectRequestBody(t, map[string]interface{}{
1104+
"body": "Some issues to fix",
1105+
"event": "REQUEST_CHANGES",
1106+
"comments": []interface{}{
1107+
map[string]interface{}{
1108+
"path": "file1.go",
1109+
"position": float64(10),
1110+
"body": "This needs to be fixed",
1111+
},
1112+
map[string]interface{}{
1113+
"path": "file2.go",
1114+
"position": float64(20),
1115+
"body": "Consider a different approach here",
1116+
},
1117+
},
1118+
}).andThen(
1119+
mockResponse(t, http.StatusOK, mockReview),
1120+
),
10731121
),
10741122
),
10751123
requestArgs: map[string]interface{}{
@@ -1240,10 +1288,18 @@ func Test_CreatePullRequest(t *testing.T) {
12401288
mockedClient: mock.NewMockedHTTPClient(
12411289
mock.WithRequestMatchHandler(
12421290
mock.PostReposPullsByOwnerByRepo,
1243-
mockResponse(t, http.StatusCreated, mockPR),
1291+
expectRequestBody(t, map[string]interface{}{
1292+
"title": "Test PR",
1293+
"body": "This is a test PR",
1294+
"head": "feature-branch",
1295+
"base": "main",
1296+
"draft": false,
1297+
"maintainer_can_modify": true,
1298+
}).andThen(
1299+
mockResponse(t, http.StatusCreated, mockPR),
1300+
),
12441301
),
12451302
),
1246-
12471303
requestArgs: map[string]interface{}{
12481304
"owner": "owner",
12491305
"repo": "repo",

0 commit comments

Comments
 (0)