|
7 | 7 | "encoding/base64"
|
8 | 8 | "encoding/json"
|
9 | 9 | "fmt"
|
| 10 | +"net/http" |
10 | 11 | "os"
|
11 | 12 | "os/exec"
|
12 | 13 | "slices"
|
@@ -210,7 +211,6 @@ func TestGetMe(t *testing.T) {
|
210 | 211 | t.Parallel()
|
211 | 212 |
|
212 | 213 | mcpClient:=setupMCPClient(t)
|
213 |
| - |
214 | 214 | ctx:=context.Background()
|
215 | 215 |
|
216 | 216 | // When we call the "get_me" tool
|
@@ -795,14 +795,13 @@ func TestDirectoryDeletion(t *testing.T) {
|
795 | 795 | }
|
796 | 796 |
|
797 | 797 | funcTestRequestCopilotReview(t*testing.T) {
|
| 798 | +t.Parallel() |
| 799 | + |
798 | 800 | ifgetE2EHost()!=""&&getE2EHost()!="https://github.com" {
|
799 | 801 | t.Skip("Skipping test because the host does not support copilot reviews")
|
800 | 802 | }
|
801 | 803 |
|
802 |
| -t.Parallel() |
803 |
| - |
804 | 804 | mcpClient:=setupMCPClient(t)
|
805 |
| - |
806 | 805 | ctx:=context.Background()
|
807 | 806 |
|
808 | 807 | // First, who am I
|
@@ -943,6 +942,112 @@ func TestRequestCopilotReview(t *testing.T) {
|
943 | 942 | require.Equal(t,"Bot",*reviewRequests.Users[0].Type,"expected review request to be for Bot")
|
944 | 943 | }
|
945 | 944 |
|
| 945 | +funcTestAssignCopilotToIssue(t*testing.T) { |
| 946 | +t.Parallel() |
| 947 | + |
| 948 | +ifgetE2EHost()!=""&&getE2EHost()!="https://github.com" { |
| 949 | +t.Skip("Skipping test because the host does not support copilot being assigned to issues") |
| 950 | +} |
| 951 | + |
| 952 | +mcpClient:=setupMCPClient(t) |
| 953 | +ctx:=context.Background() |
| 954 | + |
| 955 | +// First, who am I |
| 956 | +getMeRequest:= mcp.CallToolRequest{} |
| 957 | +getMeRequest.Params.Name="get_me" |
| 958 | + |
| 959 | +t.Log("Getting current user...") |
| 960 | +resp,err:=mcpClient.CallTool(ctx,getMeRequest) |
| 961 | +require.NoError(t,err,"expected to call 'get_me' tool successfully") |
| 962 | +require.False(t,resp.IsError,fmt.Sprintf("expected result not to be an error: %+v",resp)) |
| 963 | + |
| 964 | +require.False(t,resp.IsError,"expected result not to be an error") |
| 965 | +require.Len(t,resp.Content,1,"expected content to have one item") |
| 966 | + |
| 967 | +textContent,ok:=resp.Content[0].(mcp.TextContent) |
| 968 | +require.True(t,ok,"expected content to be of type TextContent") |
| 969 | + |
| 970 | +vartrimmedGetMeTextstruct { |
| 971 | +Loginstring`json:"login"` |
| 972 | +} |
| 973 | +err=json.Unmarshal([]byte(textContent.Text),&trimmedGetMeText) |
| 974 | +require.NoError(t,err,"expected to unmarshal text content successfully") |
| 975 | + |
| 976 | +currentOwner:=trimmedGetMeText.Login |
| 977 | + |
| 978 | +// Then create a repository with a README (via autoInit) |
| 979 | +repoName:=fmt.Sprintf("github-mcp-server-e2e-%s-%d",t.Name(),time.Now().UnixMilli()) |
| 980 | +createRepoRequest:= mcp.CallToolRequest{} |
| 981 | +createRepoRequest.Params.Name="create_repository" |
| 982 | +createRepoRequest.Params.Arguments=map[string]any{ |
| 983 | +"name":repoName, |
| 984 | +"private":true, |
| 985 | +"autoInit":true, |
| 986 | +} |
| 987 | + |
| 988 | +t.Logf("Creating repository %s/%s...",currentOwner,repoName) |
| 989 | +_,err=mcpClient.CallTool(ctx,createRepoRequest) |
| 990 | +require.NoError(t,err,"expected to call 'get_me' tool successfully") |
| 991 | +require.False(t,resp.IsError,fmt.Sprintf("expected result not to be an error: %+v",resp)) |
| 992 | + |
| 993 | +// Cleanup the repository after the test |
| 994 | +t.Cleanup(func() { |
| 995 | +// MCP Server doesn't support deletions, but we can use the GitHub Client |
| 996 | +ghClient:=getRESTClient(t) |
| 997 | +t.Logf("Deleting repository %s/%s...",currentOwner,repoName) |
| 998 | +_,err:=ghClient.Repositories.Delete(context.Background(),currentOwner,repoName) |
| 999 | +require.NoError(t,err,"expected to delete repository successfully") |
| 1000 | +}) |
| 1001 | + |
| 1002 | +// Create an issue |
| 1003 | +createIssueRequest:= mcp.CallToolRequest{} |
| 1004 | +createIssueRequest.Params.Name="create_issue" |
| 1005 | +createIssueRequest.Params.Arguments=map[string]any{ |
| 1006 | +"owner":currentOwner, |
| 1007 | +"repo":repoName, |
| 1008 | +"title":"Test issue to assign copilot to", |
| 1009 | +} |
| 1010 | + |
| 1011 | +t.Logf("Creating issue in %s/%s...",currentOwner,repoName) |
| 1012 | +resp,err=mcpClient.CallTool(ctx,createIssueRequest) |
| 1013 | +require.NoError(t,err,"expected to call 'create_issue' tool successfully") |
| 1014 | +require.False(t,resp.IsError,fmt.Sprintf("expected result not to be an error: %+v",resp)) |
| 1015 | + |
| 1016 | +// Assign copilot to the issue |
| 1017 | +assignCopilotRequest:= mcp.CallToolRequest{} |
| 1018 | +assignCopilotRequest.Params.Name="assign_copilot_to_issue" |
| 1019 | +assignCopilotRequest.Params.Arguments=map[string]any{ |
| 1020 | +"owner":currentOwner, |
| 1021 | +"repo":repoName, |
| 1022 | +"issueNumber":1, |
| 1023 | +} |
| 1024 | + |
| 1025 | +t.Logf("Assigning copilot to issue in %s/%s...",currentOwner,repoName) |
| 1026 | +resp,err=mcpClient.CallTool(ctx,assignCopilotRequest) |
| 1027 | +require.NoError(t,err,"expected to call 'assign_copilot_to_issue' tool successfully") |
| 1028 | + |
| 1029 | +textContent,ok=resp.Content[0].(mcp.TextContent) |
| 1030 | +require.True(t,ok,"expected content to be of type TextContent") |
| 1031 | + |
| 1032 | +possibleExpectedFailure:="copilot isn't available as an assignee for this issue, perhaps you need to enable it in your settings?" |
| 1033 | +ifresp.IsError&&textContent.Text==possibleExpectedFailure { |
| 1034 | +t.Skip("skipping because copilot wasn't available as an assignee on this issue, it's likely that the owner doesn't have copilot enabled in their settings") |
| 1035 | +} |
| 1036 | + |
| 1037 | +require.False(t,resp.IsError,fmt.Sprintf("expected result not to be an error: %+v",resp)) |
| 1038 | + |
| 1039 | +require.Equal(t,"successfully assigned copilot to issue",textContent.Text) |
| 1040 | + |
| 1041 | +// Check that copilot is assigned to the issue |
| 1042 | +// MCP Server doesn't support getting assignees yet |
| 1043 | +ghClient:=getRESTClient(t) |
| 1044 | +assignees,response,err:=ghClient.Issues.Get(context.Background(),currentOwner,repoName,1) |
| 1045 | +require.NoError(t,err,"expected to get issue successfully") |
| 1046 | +require.Equal(t,http.StatusOK,response.StatusCode,"expected to get issue successfully") |
| 1047 | +require.Len(t,assignees.Assignees,1,"expected to find one assignee") |
| 1048 | +require.Equal(t,"Copilot",*assignees.Assignees[0].Login,"expected copilot to be assigned to the issue") |
| 1049 | +} |
| 1050 | + |
946 | 1051 | funcTestPullRequestAtomicCreateAndSubmit(t*testing.T) {
|
947 | 1052 | t.Parallel()
|
948 | 1053 |
|
@@ -1145,7 +1250,7 @@ func TestPullRequestReviewCommentSubmit(t *testing.T) {
|
1145 | 1250 |
|
1146 | 1251 | t.Logf("Creating repository %s/%s...",currentOwner,repoName)
|
1147 | 1252 | _,err=mcpClient.CallTool(ctx,createRepoRequest)
|
1148 |
| -require.NoError(t,err,"expected to call 'get_me' tool successfully") |
| 1253 | +require.NoError(t,err,"expected to call 'create_repository' tool successfully") |
1149 | 1254 | require.False(t,resp.IsError,fmt.Sprintf("expected result not to be an error: %+v",resp))
|
1150 | 1255 |
|
1151 | 1256 | // Cleanup the repository after the test
|
|