Skip to content

Commit 7b962fd

Browse files
committed
fix(actions): allow run_id alone to get all job logs
Allow get_job_logs tool to return logs for all jobs in a workflow run when only run_id is provided (without failed_only parameter). This matches the documented behavior where: - run_id + failed_only=true returns only failed job logs - run_id alone (or with failed_only=false) returns all job logs Fixes #2389
1 parent 50dc9b9 commit 7b962fd

1 file changed

Lines changed: 63 additions & 7 deletions

File tree

pkg/github/actions.go

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,61 @@ func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo
125125
return utils.NewToolResultText(string(r)), nil, nil
126126
}
127127

128+
// handleAllJobLogs gets logs for all jobs in a workflow run
129+
func handleAllJobLogs(ctx context.Context, client *github.Client, owner, repo string, runID int64, returnContent bool, tailLines int, contentWindowSize int) (*mcp.CallToolResult, any, error) {
130+
// First, get all jobs for the workflow run
131+
jobs, resp, err := client.Actions.ListWorkflowJobs(ctx, owner, repo, runID, &github.ListWorkflowJobsOptions{
132+
Filter: "latest",
133+
})
134+
if err != nil {
135+
return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to list workflow jobs", resp, err), nil, nil
136+
}
137+
defer func() { _ = resp.Body.Close() }()
138+
139+
if len(jobs.Jobs) == 0 {
140+
result := map[string]any{
141+
"message": "No jobs found in this workflow run",
142+
"run_id": runID,
143+
"total_jobs": 0,
144+
}
145+
r, _ := json.Marshal(result)
146+
return utils.NewToolResultText(string(r)), nil, nil
147+
}
148+
149+
// Collect logs for all jobs
150+
var logResults []map[string]any
151+
for _, job := range jobs.Jobs {
152+
jobResult, resp, err := getJobLogData(ctx, client, owner, repo, job.GetID(), job.GetName(), returnContent, tailLines, contentWindowSize)
153+
if err != nil {
154+
// Continue with other jobs even if one fails
155+
jobResult = map[string]any{
156+
"job_id": job.GetID(),
157+
"job_name": job.GetName(),
158+
"error": err.Error(),
159+
}
160+
// Enable reporting of status codes and error causes
161+
_, _ = ghErrors.NewGitHubAPIErrorToCtx(ctx, "failed to get job logs", resp, err) // Explicitly ignore error for graceful handling
162+
}
163+
164+
logResults = append(logResults, jobResult)
165+
}
166+
167+
result := map[string]any{
168+
"message": fmt.Sprintf("Retrieved logs for %d jobs", len(jobs.Jobs)),
169+
"run_id": runID,
170+
"total_jobs": len(jobs.Jobs),
171+
"logs": logResults,
172+
"return_format": map[string]bool{"content": returnContent, "urls": !returnContent},
173+
}
174+
175+
r, err := json.Marshal(result)
176+
if err != nil {
177+
return nil, nil, fmt.Errorf("failed to marshal response: %w", err)
178+
}
179+
180+
return utils.NewToolResultText(string(r)), nil, nil
181+
}
182+
128183
// getJobLogData retrieves log data for a single job, either as URL or content
129184
func getJobLogData(ctx context.Context, client *github.Client, owner, repo string, jobID int64, jobName string, returnContent bool, tailLines int, contentWindowSize int) (map[string]any, *github.Response, error) {
130185
// Get the download URL for the job logs
@@ -716,19 +771,20 @@ For single job logs, provide job_id. For all failed jobs in a run, provide run_i
716771
if failedOnly && runID == 0 {
717772
return utils.NewToolResultError("run_id is required when failed_only is true"), nil, nil
718773
}
719-
if !failedOnly && jobID == 0 {
720-
return utils.NewToolResultError("job_id is required when failed_only is false"), nil, nil
721-
}
722774

723-
if failedOnly && runID > 0 {
724-
// Handle failed-only mode: get logs for all failed jobs in the workflow run
725-
return handleFailedJobLogs(ctx, client, owner, repo, int64(runID), returnContent, tailLines, deps.GetContentWindowSize())
775+
if runID > 0 {
776+
if failedOnly {
777+
// Handle failed-only mode: get logs for all failed jobs in the workflow run
778+
return handleFailedJobLogs(ctx, client, owner, repo, int64(runID), returnContent, tailLines, deps.GetContentWindowSize())
779+
}
780+
// Handle all jobs mode: get logs for all jobs in the workflow run
781+
return handleAllJobLogs(ctx, client, owner, repo, int64(runID), returnContent, tailLines, deps.GetContentWindowSize())
726782
} else if jobID > 0 {
727783
// Handle single job mode
728784
return handleSingleJobLogs(ctx, client, owner, repo, int64(jobID), returnContent, tailLines, deps.GetContentWindowSize())
729785
}
730786

731-
return utils.NewToolResultError("Either job_id must be provided for single job logs, or run_id with failed_only=true for failed job logs"), nil, nil
787+
return utils.NewToolResultError("Either job_id or run_id must be provided"), nil, nil
732788
},
733789
)
734790
return tool

0 commit comments

Comments
 (0)