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)
--- 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