Skip to content

Commit fbcf77a

Browse files
committed
fix: update job logs schema snapshot
1 parent 19faf85 commit fbcf77a

3 files changed

Lines changed: 76 additions & 23 deletions

File tree

pkg/github/__toolsnaps__/get_job_logs.snap

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
{
22
"annotations": {
33
"readOnlyHint": true,
4-
"title": "Get job logs"
4+
"title": "Get GitHub Actions workflow job logs"
55
},
6-
"description": "Download logs for a specific workflow job or efficiently get all failed job logs for a workflow run",
6+
"description": "Get logs for GitHub Actions workflow jobs.\nUse this tool to retrieve logs for a specific job or all jobs in a workflow run.\nProvide job_id for one job, or run_id for all jobs in a run. Set failed_only=true to restrict either mode to failed jobs only.\n",
77
"inputSchema": {
88
"properties": {
99
"failed_only": {
10-
"description": "When true, gets logs for all failed jobs in run_id",
10+
"description": "When true, only returns logs for failed jobs. With job_id, the job must have failed. With run_id, only failed jobs in the run are included.",
1111
"type": "boolean"
1212
},
1313
"job_id": {
14-
"description": "The unique identifier of the workflow job (required for single job logs)",
14+
"description": "The unique identifier of the workflow job. Provide either job_id or run_id, not both.",
1515
"type": "number"
1616
},
1717
"owner": {
@@ -27,7 +27,7 @@
2727
"type": "boolean"
2828
},
2929
"run_id": {
30-
"description": "Workflow run ID (required when using failed_only)",
30+
"description": "The unique identifier of the workflow run. Provide either run_id or job_id, not both.",
3131
"type": "number"
3232
},
3333
"tail_lines": {

pkg/github/actions.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ func handleRunJobLogs(ctx context.Context, client *github.Client, owner, repo st
5757

5858
// Filter jobs when requested. Otherwise return logs for every job in the run.
5959
var selectedJobs []*github.WorkflowJob
60+
failedJobsCount := 0
6061
for _, job := range jobs.Jobs {
61-
if !failedOnly || job.GetConclusion() == "failure" {
62+
failed := job.GetConclusion() == "failure"
63+
if failed {
64+
failedJobsCount++
65+
}
66+
if !failedOnly || failed {
6267
selectedJobs = append(selectedJobs, job)
6368
}
6469
}
@@ -69,12 +74,10 @@ func handleRunJobLogs(ctx context.Context, client *github.Client, owner, repo st
6974
message = "No failed jobs found in this workflow run"
7075
}
7176
result := map[string]any{
72-
"message": message,
73-
"run_id": runID,
74-
"total_jobs": len(jobs.Jobs),
75-
}
76-
if failedOnly {
77-
result["failed_jobs"] = 0
77+
"message": message,
78+
"run_id": runID,
79+
"total_jobs": len(jobs.Jobs),
80+
"failed_jobs": failedJobsCount,
7881
}
7982
r, _ := json.Marshal(result)
8083
return utils.NewToolResultText(string(r)), nil, nil
@@ -106,12 +109,10 @@ func handleRunJobLogs(ctx context.Context, client *github.Client, owner, repo st
106109
"message": message,
107110
"run_id": runID,
108111
"total_jobs": len(jobs.Jobs),
112+
"failed_jobs": failedJobsCount,
109113
"logs": logResults,
110114
"return_format": map[string]bool{"content": returnContent, "urls": !returnContent},
111115
}
112-
if failedOnly {
113-
result["failed_jobs"] = len(selectedJobs)
114-
}
115116

116117
r, err := json.Marshal(result)
117118
if err != nil {

pkg/github/actions_test.go

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,7 @@ func Test_ActionsGetJobLogs(t *testing.T) {
529529
// Verify tool definition once
530530
toolDef := ActionsGetJobLogs(translations.NullTranslationHelper)
531531

532-
// Note: consolidated ActionsGetJobLogs has same tool name "get_job_logs" as the individual tool
533-
// but with different descriptions. We skip toolsnap validation here since the individual
534-
// tool's toolsnap already exists and is tested in Test_GetJobLogs.
535-
// The consolidated tool has FeatureFlagEnable set, so only one will be active at a time.
532+
require.NoError(t, toolsnaps.Test(toolDef.Tool.Name, toolDef.Tool))
536533
assert.Equal(t, "get_job_logs", toolDef.Tool.Name)
537534
assert.NotEmpty(t, toolDef.Tool.Description)
538535
inputSchema := toolDef.Tool.InputSchema.(*jsonschema.Schema)
@@ -599,7 +596,7 @@ func Test_ActionsGetJobLogs_SingleJob(t *testing.T) {
599596
}),
600597
})
601598

602-
client := github.NewClient(mockedClient)
599+
client := mustNewGHClient(t, mockedClient)
603600
deps := BaseDeps{
604601
Client: client,
605602
ContentWindowSize: 5000,
@@ -638,7 +635,7 @@ func Test_ActionsGetJobLogs_SingleJob(t *testing.T) {
638635
}),
639636
})
640637

641-
client := github.NewClient(mockedClient)
638+
client := mustNewGHClient(t, mockedClient)
642639
deps := BaseDeps{
643640
Client: client,
644641
ContentWindowSize: 5000,
@@ -689,7 +686,7 @@ func Test_ActionsGetJobLogs_FailedJobs(t *testing.T) {
689686
}),
690687
})
691688

692-
client := github.NewClient(mockedClient)
689+
client := mustNewGHClient(t, mockedClient)
693690
deps := BaseDeps{
694691
Client: client,
695692
ContentWindowSize: 5000,
@@ -712,6 +709,7 @@ func Test_ActionsGetJobLogs_FailedJobs(t *testing.T) {
712709
require.NoError(t, err)
713710
assert.Equal(t, float64(456), response["run_id"])
714711
assert.Equal(t, float64(2), response["total_jobs"])
712+
assert.Equal(t, float64(1), response["failed_jobs"])
715713
assert.Len(t, response["logs"], 2)
716714
assert.Contains(t, response["message"], "Retrieved logs for 2 jobs")
717715
})
@@ -771,10 +769,64 @@ func Test_ActionsGetJobLogs_FailedJobs(t *testing.T) {
771769
err = json.Unmarshal([]byte(textContent.Text), &response)
772770
require.NoError(t, err)
773771
assert.Equal(t, float64(456), response["run_id"])
772+
assert.Equal(t, float64(2), response["failed_jobs"])
774773
assert.Contains(t, response, "logs")
775774
assert.Contains(t, response["message"], "Retrieved logs for")
776775
})
777776

777+
t.Run("successful failed-only logs when all jobs failed", func(t *testing.T) {
778+
mockedClient := MockHTTPClientWithHandlers(map[string]http.HandlerFunc{
779+
GetReposActionsRunsJobsByOwnerByRepoByRunID: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
780+
jobs := &github.Jobs{
781+
TotalCount: github.Ptr(2),
782+
Jobs: []*github.WorkflowJob{
783+
{
784+
ID: github.Ptr(int64(1)),
785+
Name: github.Ptr("test-job-1"),
786+
Conclusion: github.Ptr("failure"),
787+
},
788+
{
789+
ID: github.Ptr(int64(2)),
790+
Name: github.Ptr("test-job-2"),
791+
Conclusion: github.Ptr("failure"),
792+
},
793+
},
794+
}
795+
w.WriteHeader(http.StatusOK)
796+
_ = json.NewEncoder(w).Encode(jobs)
797+
}),
798+
GetReposActionsJobsLogsByOwnerByRepoByJobID: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
799+
w.Header().Set("Location", "https://github.com/logs/job/"+r.URL.Path[len(r.URL.Path)-1:])
800+
w.WriteHeader(http.StatusFound)
801+
}),
802+
})
803+
804+
client := mustNewGHClient(t, mockedClient)
805+
deps := BaseDeps{
806+
Client: client,
807+
ContentWindowSize: 5000,
808+
}
809+
handler := toolDef.Handler(deps)
810+
811+
request := createMCPRequest(map[string]any{
812+
"owner": "owner",
813+
"repo": "repo",
814+
"run_id": float64(456),
815+
"failed_only": true,
816+
})
817+
result, err := handler(ContextWithDeps(context.Background(), deps), &request)
818+
819+
require.NoError(t, err)
820+
require.False(t, result.IsError)
821+
822+
textContent := getTextResult(t, result)
823+
var response map[string]any
824+
err = json.Unmarshal([]byte(textContent.Text), &response)
825+
require.NoError(t, err)
826+
assert.Equal(t, float64(2), response["failed_jobs"])
827+
assert.Len(t, response["logs"], 2)
828+
})
829+
778830
t.Run("no failed jobs found", func(t *testing.T) {
779831
mockedClient := MockHTTPClientWithHandlers(map[string]http.HandlerFunc{
780832
GetReposActionsRunsJobsByOwnerByRepoByRunID: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
@@ -826,7 +878,7 @@ func Test_ActionsGetJobLogs_FailedJobs(t *testing.T) {
826878

827879
func Test_ActionsGetJobLogs_Validation(t *testing.T) {
828880
toolDef := ActionsGetJobLogs(translations.NullTranslationHelper)
829-
client := github.NewClient(MockHTTPClientWithHandlers(map[string]http.HandlerFunc{}))
881+
client := mustNewGHClient(t, MockHTTPClientWithHandlers(map[string]http.HandlerFunc{}))
830882
deps := BaseDeps{
831883
Client: client,
832884
ContentWindowSize: 5000,

0 commit comments

Comments
 (0)