Skip to content

Commit 92d95e4

Browse files
williammartinSamMorrowDrums
authored andcommitted
Add e2e test for tags
1 parent 09e1563 commit 92d95e4

File tree

2 files changed

+139
-1
lines changed

2 files changed

+139
-1
lines changed

e2e/README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,6 @@ FAIL
8181

8282
The current test suite is intentionally very limited in scope. This is because the maintenance costs on e2e tests tend to increase significantly over time. To read about some challenges with GitHub integration tests, see [go-github integration tests README](https://github.com/google/go-github/blob/5b75aa86dba5cf4af2923afa0938774f37fa0a67/test/README.md). We will expand this suite circumspectly!
8383

84-
Currently, visibility into failures is not particularly good.
84+
The tests are quite repetitive and verbose. This is intentional as we want to see them develop more before committing to abstractions.
85+
86+
Currently, visibility into failures is not particularly good. We're hoping that we can pull apart the mcp-go client and have it hook into streams representing stdio without requiring an exec. This way we can get breakpoints in the debugger easily.

e2e/e2e_test.go

+136
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,139 @@ func TestToolsets(t *testing.T) {
206206
require.True(t, toolsContains("list_branches"), "expected to find 'list_branches' tool")
207207
require.False(t, toolsContains("get_pull_request"), "expected not to find 'get_pull_request' tool")
208208
}
209+
210+
func TestTags(t *testing.T) {
211+
mcpClient := setupMCPClient(t)
212+
213+
ctx := context.Background()
214+
215+
// First, who am I
216+
getMeRequest := mcp.CallToolRequest{}
217+
getMeRequest.Params.Name = "get_me"
218+
219+
t.Log("Getting current user...")
220+
resp, err := mcpClient.CallTool(ctx, getMeRequest)
221+
require.NoError(t, err, "expected to call 'get_me' tool successfully")
222+
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))
223+
224+
require.False(t, resp.IsError, "expected result not to be an error")
225+
require.Len(t, resp.Content, 1, "expected content to have one item")
226+
227+
textContent, ok := resp.Content[0].(mcp.TextContent)
228+
require.True(t, ok, "expected content to be of type TextContent")
229+
230+
var trimmedGetMeText struct {
231+
Login string `json:"login"`
232+
}
233+
err = json.Unmarshal([]byte(textContent.Text), &trimmedGetMeText)
234+
require.NoError(t, err, "expected to unmarshal text content successfully")
235+
236+
currentOwner := trimmedGetMeText.Login
237+
238+
// Then create a repository with a README (via autoInit)
239+
repoName := fmt.Sprintf("github-mcp-server-e2e-%s-%d", t.Name(), time.Now().UnixMilli())
240+
createRepoRequest := mcp.CallToolRequest{}
241+
createRepoRequest.Params.Name = "create_repository"
242+
createRepoRequest.Params.Arguments = map[string]any{
243+
"name": repoName,
244+
"private": true,
245+
"autoInit": true,
246+
}
247+
248+
t.Logf("Creating repository %s/%s...", currentOwner, repoName)
249+
_, err = mcpClient.CallTool(ctx, createRepoRequest)
250+
require.NoError(t, err, "expected to call 'get_me' tool successfully")
251+
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))
252+
253+
// Cleanup the repository after the test
254+
t.Cleanup(func() {
255+
// MCP Server doesn't support deletions, but we can use the GitHub Client
256+
ghClient := github.NewClient(nil).WithAuthToken(getE2EToken(t))
257+
t.Logf("Deleting repository %s/%s...", currentOwner, repoName)
258+
_, err := ghClient.Repositories.Delete(context.Background(), currentOwner, repoName)
259+
require.NoError(t, err, "expected to delete repository successfully")
260+
})
261+
262+
// Then create a tag
263+
// MCP Server doesn't support tag creation, but we can use the GitHub Client
264+
ghClient := github.NewClient(nil).WithAuthToken(getE2EToken(t))
265+
t.Logf("Creating tag %s/%s:%s...", currentOwner, repoName, "v0.0.1")
266+
ref, _, err := ghClient.Git.GetRef(context.Background(), currentOwner, repoName, "refs/heads/main")
267+
require.NoError(t, err, "expected to get ref successfully")
268+
269+
tagObj, _, err := ghClient.Git.CreateTag(context.Background(), currentOwner, repoName, &github.Tag{
270+
Tag: github.Ptr("v0.0.1"),
271+
Message: github.Ptr("v0.0.1"),
272+
Object: &github.GitObject{
273+
SHA: ref.Object.SHA,
274+
Type: github.Ptr("commit"),
275+
},
276+
})
277+
require.NoError(t, err, "expected to create tag object successfully")
278+
279+
_, _, err = ghClient.Git.CreateRef(context.Background(), currentOwner, repoName, &github.Reference{
280+
Ref: github.Ptr("refs/tags/v0.0.1"),
281+
Object: &github.GitObject{
282+
SHA: tagObj.SHA,
283+
},
284+
})
285+
require.NoError(t, err, "expected to create tag ref successfully")
286+
287+
// List the tags
288+
listTagsRequest := mcp.CallToolRequest{}
289+
listTagsRequest.Params.Name = "list_tags"
290+
listTagsRequest.Params.Arguments = map[string]any{
291+
"owner": currentOwner,
292+
"repo": repoName,
293+
}
294+
295+
t.Logf("Listing tags for %s/%s...", currentOwner, repoName)
296+
resp, err = mcpClient.CallTool(ctx, listTagsRequest)
297+
require.NoError(t, err, "expected to call 'list_tags' tool successfully")
298+
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))
299+
300+
require.False(t, resp.IsError, "expected result not to be an error")
301+
require.Len(t, resp.Content, 1, "expected content to have one item")
302+
303+
textContent, ok = resp.Content[0].(mcp.TextContent)
304+
require.True(t, ok, "expected content to be of type TextContent")
305+
306+
var trimmedTags []struct {
307+
Name string `json:"name"`
308+
Commit struct {
309+
SHA string `json:"sha"`
310+
} `json:"commit"`
311+
}
312+
err = json.Unmarshal([]byte(textContent.Text), &trimmedTags)
313+
require.NoError(t, err, "expected to unmarshal text content successfully")
314+
315+
require.Len(t, trimmedTags, 1, "expected to find one tag")
316+
require.Equal(t, "v0.0.1", trimmedTags[0].Name, "expected tag name to match")
317+
require.Equal(t, *ref.Object.SHA, trimmedTags[0].Commit.SHA, "expected tag SHA to match")
318+
319+
// And fetch an individual tag
320+
getTagRequest := mcp.CallToolRequest{}
321+
getTagRequest.Params.Name = "get_tag"
322+
getTagRequest.Params.Arguments = map[string]any{
323+
"owner": currentOwner,
324+
"repo": repoName,
325+
"tag": "v0.0.1",
326+
}
327+
328+
t.Logf("Getting tag %s/%s:%s...", currentOwner, repoName, "v0.0.1")
329+
resp, err = mcpClient.CallTool(ctx, getTagRequest)
330+
require.NoError(t, err, "expected to call 'get_tag' tool successfully")
331+
require.False(t, resp.IsError, "expected result not to be an error")
332+
333+
var trimmedTag []struct { // don't understand why this is an array
334+
Name string `json:"name"`
335+
Commit struct {
336+
SHA string `json:"sha"`
337+
} `json:"commit"`
338+
}
339+
err = json.Unmarshal([]byte(textContent.Text), &trimmedTag)
340+
require.NoError(t, err, "expected to unmarshal text content successfully")
341+
require.Len(t, trimmedTag, 1, "expected to find one tag")
342+
require.Equal(t, "v0.0.1", trimmedTag[0].Name, "expected tag name to match")
343+
require.Equal(t, *ref.Object.SHA, trimmedTag[0].Commit.SHA, "expected tag SHA to match")
344+
}

0 commit comments

Comments
 (0)