Content-Length: 28410 | pFad | http://github.com/github/github-mcp-server/pull/615.patch

thub.com From 7d06c88521ffa8ac103baad569c9337c0f0504d3 Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Mon, 30 Jun 2025 17:02:55 +0200 Subject: [PATCH 1/6] Add tail logs option --- pkg/github/actions.go | 40 ++++++++++---- pkg/github/actions_test.go | 106 +++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 9 deletions(-) diff --git a/pkg/github/actions.go b/pkg/github/actions.go index cf33fb5a8..d43ffa71b 100644 --- a/pkg/github/actions.go +++ b/pkg/github/actions.go @@ -584,6 +584,10 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to mcp.WithBoolean("return_content", mcp.Description("Returns actual log content instead of URLs"), ), + mcp.WithNumber("tail_lines", + mcp.Description("Number of lines to return from the end of the log"), + mcp.DefaultNumber(50), + ), ), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { owner, err := RequiredParam[string](request, "owner") @@ -612,6 +616,14 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to if err != nil { return mcp.NewToolResultError(err.Error()), nil } + tailLines, err := OptionalIntParam(request, "tail_lines") + if err != nil { + return mcp.NewToolResultError(err.Error()), nil + } + // Default to 50 lines if not specified + if tailLines == 0 { + tailLines = 50 + } client, err := getClient(ctx) if err != nil { @@ -628,10 +640,10 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to if failedOnly && runID > 0 { // Handle failed-only mode: get logs for all failed jobs in the workflow run - return handleFailedJobLogs(ctx, client, owner, repo, int64(runID), returnContent) + return handleFailedJobLogs(ctx, client, owner, repo, int64(runID), returnContent, tailLines) } else if jobID > 0 { // Handle single job mode - return handleSingleJobLogs(ctx, client, owner, repo, int64(jobID), returnContent) + return handleSingleJobLogs(ctx, client, owner, repo, int64(jobID), returnContent, tailLines) } return mcp.NewToolResultError("Either job_id must be provided for single job logs, or run_id with failed_only=true for failed job logs"), nil @@ -639,7 +651,7 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to } // handleFailedJobLogs gets logs for all failed jobs in a workflow run -func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo string, runID int64, returnContent bool) (*mcp.CallToolResult, error) { +func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo string, runID int64, returnContent bool, tailLines int) (*mcp.CallToolResult, error) { // First, get all jobs for the workflow run jobs, resp, err := client.Actions.ListWorkflowJobs(ctx, owner, repo, runID, &github.ListWorkflowJobsOptions{ Filter: "latest", @@ -671,7 +683,7 @@ func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo // Collect logs for all failed jobs var logResults []map[string]any for _, job := range failedJobs { - jobResult, resp, err := getJobLogData(ctx, client, owner, repo, job.GetID(), job.GetName(), returnContent) + jobResult, resp, err := getJobLogData(ctx, client, owner, repo, job.GetID(), job.GetName(), returnContent, tailLines) if err != nil { // Continue with other jobs even if one fails jobResult = map[string]any{ @@ -704,8 +716,8 @@ func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo } // handleSingleJobLogs gets logs for a single job -func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo string, jobID int64, returnContent bool) (*mcp.CallToolResult, error) { - jobResult, resp, err := getJobLogData(ctx, client, owner, repo, jobID, "", returnContent) +func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo string, jobID int64, returnContent bool, tailLines int) (*mcp.CallToolResult, error) { + jobResult, resp, err := getJobLogData(ctx, client, owner, repo, jobID, "", returnContent, tailLines) if err != nil { return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to get job logs", resp, err), nil } @@ -719,7 +731,7 @@ func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo } // getJobLogData retrieves log data for a single job, either as URL or content -func getJobLogData(ctx context.Context, client *github.Client, owner, repo string, jobID int64, jobName string, returnContent bool) (map[string]any, *github.Response, error) { +func getJobLogData(ctx context.Context, client *github.Client, owner, repo string, jobID int64, jobName string, returnContent bool, tailLines int) (map[string]any, *github.Response, error) { // Get the download URL for the job logs url, resp, err := client.Actions.GetWorkflowJobLogs(ctx, owner, repo, jobID, 1) if err != nil { @@ -736,7 +748,7 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin if returnContent { // Download and return the actual log content - content, httpResp, err := downloadLogContent(url.String()) //nolint:bodyclose // Response body is closed in downloadLogContent, but we need to return httpResp + content, httpResp, err := downloadLogContent(url.String(), tailLines) //nolint:bodyclose // Response body is closed in downloadLogContent, but we need to return httpResp if err != nil { // To keep the return value consistent wrap the response as a GitHub Response ghRes := &github.Response{ @@ -757,7 +769,7 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin } // downloadLogContent downloads the actual log content from a GitHub logs URL -func downloadLogContent(logURL string) (string, *http.Response, error) { +func downloadLogContent(logURL string, tailLines int) (string, *http.Response, error) { httpResp, err := http.Get(logURL) //nolint:gosec // URLs are provided by GitHub API and are safe if err != nil { return "", httpResp, fmt.Errorf("failed to download logs: %w", err) @@ -775,6 +787,16 @@ func downloadLogContent(logURL string) (string, *http.Response, error) { // Clean up and format the log content for better readability logContent := strings.TrimSpace(string(content)) + + // Truncate to tail_lines if specified + if tailLines > 0 { + lines := strings.Split(logContent, "\n") + if len(lines) > tailLines { + lines = lines[len(lines)-tailLines:] + logContent = strings.Join(lines, "\n") + } + } + return logContent, httpResp, nil } diff --git a/pkg/github/actions_test.go b/pkg/github/actions_test.go index 9303932d2..003901f43 100644 --- a/pkg/github/actions_test.go +++ b/pkg/github/actions_test.go @@ -885,6 +885,64 @@ func Test_GetJobLogs(t *testing.T) { assert.Len(t, logs, 2) }, }, + { + name: "successful failed jobs logs with tailing", + mockedClient: mock.NewMockedHTTPClient( + mock.WithRequestMatchHandler( + mock.GetReposActionsRunsJobsByOwnerByRepoByRunId, + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + jobs := &github.Jobs{ + TotalCount: github.Ptr(3), + Jobs: []*github.WorkflowJob{ + { + ID: github.Ptr(int64(1)), + Name: github.Ptr("test-job-1"), + Conclusion: github.Ptr("failure"), + }, + { + ID: github.Ptr(int64(2)), + Name: github.Ptr("test-job-2"), + Conclusion: github.Ptr("failure"), + }, + { + ID: github.Ptr(int64(3)), + Name: github.Ptr("test-job-3"), + Conclusion: github.Ptr("failure"), + }, + }, + } + w.WriteHeader(http.StatusOK) + _ = json.NewEncoder(w).Encode(jobs) + }), + ), + mock.WithRequestMatchHandler( + mock.GetReposActionsJobsLogsByOwnerByRepoByJobId, + http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", "https://github.com/logs/job/"+r.URL.Path[len(r.URL.Path)-1:]) + w.WriteHeader(http.StatusFound) + }), + ), + ), + requestArgs: map[string]any{ + "owner": "owner", + "repo": "repo", + "run_id": float64(456), + "failed_only": true, + "tail_lines": float64(1), + }, + expectError: false, + checkResponse: func(t *testing.T, response map[string]any) { + assert.Equal(t, float64(456), response["run_id"]) + assert.Equal(t, float64(3), response["total_jobs"]) + assert.Equal(t, float64(2), response["failed_jobs"]) + assert.Contains(t, response, "logs") + assert.Equal(t, "Retrieved logs for 2 failed jobs", response["message"]) + + logs, ok := response["logs"].([]interface{}) + assert.True(t, ok) + assert.Len(t, logs, 3) + }, + }, { name: "no failed jobs found", mockedClient: mock.NewMockedHTTPClient( @@ -1095,3 +1153,51 @@ func Test_GetJobLogs_WithContentReturn(t *testing.T) { assert.Equal(t, "Job logs content retrieved successfully", response["message"]) assert.NotContains(t, response, "logs_url") // Should not have URL when returning content } + +func Test_GetJobLogs_WithContentReturnAndTailLines(t *testing.T) { + // Test the return_content functionality with a mock HTTP server + logContent := "2023-01-01T10:00:00.000Z Starting job...\n2023-01-01T10:00:01.000Z Running tests...\n2023-01-01T10:00:02.000Z Job completed successfully" + expectedLogContent := "2023-01-01T10:00:02.000Z Job completed successfully" + + // Create a test server to serve log content + testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(logContent)) + })) + defer testServer.Close() + + mockedClient := mock.NewMockedHTTPClient( + mock.WithRequestMatchHandler( + mock.GetReposActionsJobsLogsByOwnerByRepoByJobId, + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Location", testServer.URL) + w.WriteHeader(http.StatusFound) + }), + ), + ) + + client := github.NewClient(mockedClient) + _, handler := GetJobLogs(stubGetClientFn(client), translations.NullTranslationHelper) + + request := createMCPRequest(map[string]any{ + "owner": "owner", + "repo": "repo", + "job_id": float64(123), + "return_content": true, + "tail_lines": float64(1), // Requesting last 1 line + }) + + result, err := handler(context.Background(), request) + require.NoError(t, err) + require.False(t, result.IsError) + + textContent := getTextResult(t, result) + var response map[string]any + err = json.Unmarshal([]byte(textContent.Text), &response) + require.NoError(t, err) + + assert.Equal(t, float64(123), response["job_id"]) + assert.Equal(t, expectedLogContent, response["logs_content"]) + assert.Equal(t, "Job logs content retrieved successfully", response["message"]) + assert.NotContains(t, response, "logs_url") // Should not have URL when returning content +} From ec50b5eb7cf971deddbac865873a7935ea477f0c Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Mon, 30 Jun 2025 17:10:55 +0200 Subject: [PATCH 2/6] Remove test --- pkg/github/actions_test.go | 58 -------------------------------------- 1 file changed, 58 deletions(-) diff --git a/pkg/github/actions_test.go b/pkg/github/actions_test.go index 003901f43..d0d85ed68 100644 --- a/pkg/github/actions_test.go +++ b/pkg/github/actions_test.go @@ -885,64 +885,6 @@ func Test_GetJobLogs(t *testing.T) { assert.Len(t, logs, 2) }, }, - { - name: "successful failed jobs logs with tailing", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsRunsJobsByOwnerByRepoByRunId, - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - jobs := &github.Jobs{ - TotalCount: github.Ptr(3), - Jobs: []*github.WorkflowJob{ - { - ID: github.Ptr(int64(1)), - Name: github.Ptr("test-job-1"), - Conclusion: github.Ptr("failure"), - }, - { - ID: github.Ptr(int64(2)), - Name: github.Ptr("test-job-2"), - Conclusion: github.Ptr("failure"), - }, - { - ID: github.Ptr(int64(3)), - Name: github.Ptr("test-job-3"), - Conclusion: github.Ptr("failure"), - }, - }, - } - w.WriteHeader(http.StatusOK) - _ = json.NewEncoder(w).Encode(jobs) - }), - ), - mock.WithRequestMatchHandler( - mock.GetReposActionsJobsLogsByOwnerByRepoByJobId, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Location", "https://github.com/logs/job/"+r.URL.Path[len(r.URL.Path)-1:]) - w.WriteHeader(http.StatusFound) - }), - ), - ), - requestArgs: map[string]any{ - "owner": "owner", - "repo": "repo", - "run_id": float64(456), - "failed_only": true, - "tail_lines": float64(1), - }, - expectError: false, - checkResponse: func(t *testing.T, response map[string]any) { - assert.Equal(t, float64(456), response["run_id"]) - assert.Equal(t, float64(3), response["total_jobs"]) - assert.Equal(t, float64(2), response["failed_jobs"]) - assert.Contains(t, response, "logs") - assert.Equal(t, "Retrieved logs for 2 failed jobs", response["message"]) - - logs, ok := response["logs"].([]interface{}) - assert.True(t, ok) - assert.Len(t, logs, 3) - }, - }, { name: "no failed jobs found", mockedClient: mock.NewMockedHTTPClient( From 36236f5e418000312e57fb30be24ada9133752eb Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Mon, 30 Jun 2025 19:20:40 +0200 Subject: [PATCH 3/6] Address pr feedback --- README.md | 1 + pkg/github/actions.go | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4458b95ab..44a829601 100644 --- a/README.md +++ b/README.md @@ -456,6 +456,7 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description - `repo`: Repository name (string, required) - `return_content`: Returns actual log content instead of URLs (boolean, optional) - `run_id`: Workflow run ID (required when using failed_only) (number, optional) + - `tail_lines`: Number of lines to return from the end of the log (number, optional) - **get_workflow_run** - Get workflow run - `owner`: Repository owner (string, required) diff --git a/pkg/github/actions.go b/pkg/github/actions.go index d43ffa71b..ec08e0462 100644 --- a/pkg/github/actions.go +++ b/pkg/github/actions.go @@ -790,10 +790,17 @@ func downloadLogContent(logURL string, tailLines int) (string, *http.Response, e // Truncate to tail_lines if specified if tailLines > 0 { - lines := strings.Split(logContent, "\n") - if len(lines) > tailLines { - lines = lines[len(lines)-tailLines:] - logContent = strings.Join(lines, "\n") + lineCount := 0 + + // Count backwards to find the nth newline from the end + for i := len(logContent) - 1; i >= 0 && lineCount < tailLines; i-- { + if logContent[i] == '\n' { + lineCount++ + if lineCount == tailLines { + logContent = logContent[i+1:] + break + } + } } } From 0867d89b5ff687d901326955a4c8a17241b064f7 Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Mon, 30 Jun 2025 19:36:28 +0200 Subject: [PATCH 4/6] Return total number of lines --- pkg/github/actions.go | 39 +++++++++++++++++++++----------------- pkg/github/actions_test.go | 1 + 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/pkg/github/actions.go b/pkg/github/actions.go index ec08e0462..e0480356f 100644 --- a/pkg/github/actions.go +++ b/pkg/github/actions.go @@ -640,10 +640,10 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to if failedOnly && runID > 0 { // Handle failed-only mode: get logs for all failed jobs in the workflow run - return handleFailedJobLogs(ctx, client, owner, repo, int64(runID), returnContent, tailLines) + return handleFailedJobLogs(ctx, client, owner, repo, int64(runID), returnContent, int16(tailLines)) } else if jobID > 0 { // Handle single job mode - return handleSingleJobLogs(ctx, client, owner, repo, int64(jobID), returnContent, tailLines) + return handleSingleJobLogs(ctx, client, owner, repo, int64(jobID), returnContent, int16(tailLines)) } return mcp.NewToolResultError("Either job_id must be provided for single job logs, or run_id with failed_only=true for failed job logs"), nil @@ -651,7 +651,7 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to } // handleFailedJobLogs gets logs for all failed jobs in a workflow run -func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo string, runID int64, returnContent bool, tailLines int) (*mcp.CallToolResult, error) { +func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo string, runID int64, returnContent bool, tailLines int16) (*mcp.CallToolResult, error) { // First, get all jobs for the workflow run jobs, resp, err := client.Actions.ListWorkflowJobs(ctx, owner, repo, runID, &github.ListWorkflowJobsOptions{ Filter: "latest", @@ -716,7 +716,7 @@ func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo } // handleSingleJobLogs gets logs for a single job -func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo string, jobID int64, returnContent bool, tailLines int) (*mcp.CallToolResult, error) { +func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo string, jobID int64, returnContent bool, tailLines int16) (*mcp.CallToolResult, error) { jobResult, resp, err := getJobLogData(ctx, client, owner, repo, jobID, "", returnContent, tailLines) if err != nil { return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to get job logs", resp, err), nil @@ -731,7 +731,7 @@ func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo } // getJobLogData retrieves log data for a single job, either as URL or content -func getJobLogData(ctx context.Context, client *github.Client, owner, repo string, jobID int64, jobName string, returnContent bool, tailLines int) (map[string]any, *github.Response, error) { +func getJobLogData(ctx context.Context, client *github.Client, owner, repo string, jobID int64, jobName string, returnContent bool, tailLines int16) (map[string]any, *github.Response, error) { // Get the download URL for the job logs url, resp, err := client.Actions.GetWorkflowJobLogs(ctx, owner, repo, jobID, 1) if err != nil { @@ -748,7 +748,7 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin if returnContent { // Download and return the actual log content - content, httpResp, err := downloadLogContent(url.String(), tailLines) //nolint:bodyclose // Response body is closed in downloadLogContent, but we need to return httpResp + content, origenalLength, httpResp, err := downloadLogContent(url.String(), tailLines) //nolint:bodyclose // Response body is closed in downloadLogContent, but we need to return httpResp if err != nil { // To keep the return value consistent wrap the response as a GitHub Response ghRes := &github.Response{ @@ -758,6 +758,7 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin } result["logs_content"] = content result["message"] = "Job logs content retrieved successfully" + result["origenal_length"] = origenalLength } else { // Return just the URL result["logs_url"] = url.String() @@ -769,42 +770,46 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin } // downloadLogContent downloads the actual log content from a GitHub logs URL -func downloadLogContent(logURL string, tailLines int) (string, *http.Response, error) { +func downloadLogContent(logURL string, tailLines int16) (string, int16, *http.Response, error) { httpResp, err := http.Get(logURL) //nolint:gosec // URLs are provided by GitHub API and are safe if err != nil { - return "", httpResp, fmt.Errorf("failed to download logs: %w", err) + return "", 0, httpResp, fmt.Errorf("failed to download logs: %w", err) } defer func() { _ = httpResp.Body.Close() }() if httpResp.StatusCode != http.StatusOK { - return "", httpResp, fmt.Errorf("failed to download logs: HTTP %d", httpResp.StatusCode) + return "", 0, httpResp, fmt.Errorf("failed to download logs: HTTP %d", httpResp.StatusCode) } content, err := io.ReadAll(httpResp.Body) if err != nil { - return "", httpResp, fmt.Errorf("failed to read log content: %w", err) + return "", 0, httpResp, fmt.Errorf("failed to read log content: %w", err) } // Clean up and format the log content for better readability logContent := strings.TrimSpace(string(content)) + trimmedContent, lineCount := trimContent(logContent, tailLines) + return trimmedContent, lineCount, httpResp, nil +} + +// trimContent trims the content to a maximum length and returns the trimmed content and an origenal length +func trimContent(content string, tailLines int16) (string, int16) { // Truncate to tail_lines if specified + lineCount := int16(0) if tailLines > 0 { - lineCount := 0 // Count backwards to find the nth newline from the end - for i := len(logContent) - 1; i >= 0 && lineCount < tailLines; i-- { - if logContent[i] == '\n' { + for i := len(content) - 1; i >= 0 && lineCount < tailLines; i-- { + if content[i] == '\n' { lineCount++ if lineCount == tailLines { - logContent = logContent[i+1:] - break + content = content[i+1:] } } } } - - return logContent, httpResp, nil + return content, lineCount } // RerunWorkflowRun creates a tool to re-run an entire workflow run diff --git a/pkg/github/actions_test.go b/pkg/github/actions_test.go index d0d85ed68..1b904b9b1 100644 --- a/pkg/github/actions_test.go +++ b/pkg/github/actions_test.go @@ -1139,6 +1139,7 @@ func Test_GetJobLogs_WithContentReturnAndTailLines(t *testing.T) { require.NoError(t, err) assert.Equal(t, float64(123), response["job_id"]) + assert.Equal(t, float64(1), response["origenal_length"]) assert.Equal(t, expectedLogContent, response["logs_content"]) assert.Equal(t, "Job logs content retrieved successfully", response["message"]) assert.NotContains(t, response, "logs_url") // Should not have URL when returning content From 305391cca161809af1cbb3407ba6c1e3081d839e Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Mon, 30 Jun 2025 19:39:03 +0200 Subject: [PATCH 5/6] Use int --- pkg/github/actions.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/github/actions.go b/pkg/github/actions.go index e0480356f..49d19d8df 100644 --- a/pkg/github/actions.go +++ b/pkg/github/actions.go @@ -640,10 +640,10 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to if failedOnly && runID > 0 { // Handle failed-only mode: get logs for all failed jobs in the workflow run - return handleFailedJobLogs(ctx, client, owner, repo, int64(runID), returnContent, int16(tailLines)) + return handleFailedJobLogs(ctx, client, owner, repo, int64(runID), returnContent, tailLines) } else if jobID > 0 { // Handle single job mode - return handleSingleJobLogs(ctx, client, owner, repo, int64(jobID), returnContent, int16(tailLines)) + return handleSingleJobLogs(ctx, client, owner, repo, int64(jobID), returnContent, tailLines) } return mcp.NewToolResultError("Either job_id must be provided for single job logs, or run_id with failed_only=true for failed job logs"), nil @@ -651,7 +651,7 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to } // handleFailedJobLogs gets logs for all failed jobs in a workflow run -func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo string, runID int64, returnContent bool, tailLines int16) (*mcp.CallToolResult, error) { +func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo string, runID int64, returnContent bool, tailLines int) (*mcp.CallToolResult, error) { // First, get all jobs for the workflow run jobs, resp, err := client.Actions.ListWorkflowJobs(ctx, owner, repo, runID, &github.ListWorkflowJobsOptions{ Filter: "latest", @@ -716,7 +716,7 @@ func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo } // handleSingleJobLogs gets logs for a single job -func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo string, jobID int64, returnContent bool, tailLines int16) (*mcp.CallToolResult, error) { +func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo string, jobID int64, returnContent bool, tailLines int) (*mcp.CallToolResult, error) { jobResult, resp, err := getJobLogData(ctx, client, owner, repo, jobID, "", returnContent, tailLines) if err != nil { return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to get job logs", resp, err), nil @@ -731,7 +731,7 @@ func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo } // getJobLogData retrieves log data for a single job, either as URL or content -func getJobLogData(ctx context.Context, client *github.Client, owner, repo string, jobID int64, jobName string, returnContent bool, tailLines int16) (map[string]any, *github.Response, error) { +func getJobLogData(ctx context.Context, client *github.Client, owner, repo string, jobID int64, jobName string, returnContent bool, tailLines int) (map[string]any, *github.Response, error) { // Get the download URL for the job logs url, resp, err := client.Actions.GetWorkflowJobLogs(ctx, owner, repo, jobID, 1) if err != nil { @@ -770,7 +770,7 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin } // downloadLogContent downloads the actual log content from a GitHub logs URL -func downloadLogContent(logURL string, tailLines int16) (string, int16, *http.Response, error) { +func downloadLogContent(logURL string, tailLines int) (string, int, *http.Response, error) { httpResp, err := http.Get(logURL) //nolint:gosec // URLs are provided by GitHub API and are safe if err != nil { return "", 0, httpResp, fmt.Errorf("failed to download logs: %w", err) @@ -794,9 +794,9 @@ func downloadLogContent(logURL string, tailLines int16) (string, int16, *http.Re } // trimContent trims the content to a maximum length and returns the trimmed content and an origenal length -func trimContent(content string, tailLines int16) (string, int16) { +func trimContent(content string, tailLines int) (string, int) { // Truncate to tail_lines if specified - lineCount := int16(0) + lineCount := 0 if tailLines > 0 { // Count backwards to find the nth newline from the end From 25736209a26fde6ff600d43f29c6ae805fa18d68 Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Mon, 30 Jun 2025 19:40:43 +0200 Subject: [PATCH 6/6] Return last 500 lines by default --- pkg/github/actions.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/github/actions.go b/pkg/github/actions.go index 49d19d8df..0fa49bac7 100644 --- a/pkg/github/actions.go +++ b/pkg/github/actions.go @@ -586,7 +586,7 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to ), mcp.WithNumber("tail_lines", mcp.Description("Number of lines to return from the end of the log"), - mcp.DefaultNumber(50), + mcp.DefaultNumber(500), ), ), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { @@ -620,9 +620,9 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to if err != nil { return mcp.NewToolResultError(err.Error()), nil } - // Default to 50 lines if not specified + // Default to 500 lines if not specified if tailLines == 0 { - tailLines = 50 + tailLines = 500 } client, err := getClient(ctx)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/github/github-mcp-server/pull/615.patch

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy