Skip to content

Commit 983285f

Browse files
authored
Add download capability for workflow run attempt logs (#2716)
Fixes: #2715.
1 parent 6bba7a4 commit 983285f

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

github/actions_workflow_runs.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,26 @@ func (s *ActionsService) GetWorkflowRunAttempt(ctx context.Context, owner, repo
204204
return run, resp, nil
205205
}
206206

207+
// GetWorkflowRunAttemptLogs gets a redirect URL to download a plain text file of logs for a workflow run for attempt number.
208+
//
209+
// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#download-workflow-run-attempt-logs
210+
func (s *ActionsService) GetWorkflowRunAttemptLogs(ctx context.Context, owner, repo string, runID int64, attemptNumber int, followRedirects bool) (*url.URL, *Response, error) {
211+
u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/attempts/%v/logs", owner, repo, runID, attemptNumber)
212+
213+
resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, followRedirects)
214+
if err != nil {
215+
return nil, nil, err
216+
}
217+
defer resp.Body.Close()
218+
219+
if resp.StatusCode != http.StatusFound {
220+
return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status)
221+
}
222+
223+
parsedURL, err := url.Parse(resp.Header.Get("Location"))
224+
return parsedURL, newResponse(resp), err
225+
}
226+
207227
// RerunWorkflowByID re-runs a workflow by ID.
208228
//
209229
// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#re-run-a-workflow

github/actions_workflow_runs_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,89 @@ func TestActionsService_GetWorkflowRunAttempt(t *testing.T) {
188188
})
189189
}
190190

191+
func TestActionsService_GetWorkflowRunAttemptLogs(t *testing.T) {
192+
client, mux, _, teardown := setup()
193+
defer teardown()
194+
195+
mux.HandleFunc("/repos/o/r/actions/runs/399444496/attempts/2/logs", func(w http.ResponseWriter, r *http.Request) {
196+
testMethod(t, r, "GET")
197+
http.Redirect(w, r, "http://github.com/a", http.StatusFound)
198+
})
199+
200+
ctx := context.Background()
201+
url, resp, err := client.Actions.GetWorkflowRunAttemptLogs(ctx, "o", "r", 399444496, 2, true)
202+
if err != nil {
203+
t.Errorf("Actions.GetWorkflowRunAttemptLogs returned error: %v", err)
204+
}
205+
if resp.StatusCode != http.StatusFound {
206+
t.Errorf("Actions.GetWorkflowRunAttemptLogs returned status: %d, want %d", resp.StatusCode, http.StatusFound)
207+
}
208+
want := "http://github.com/a"
209+
if url.String() != want {
210+
t.Errorf("Actions.GetWorkflowRunAttemptLogs returned %+v, want %+v", url.String(), want)
211+
}
212+
213+
const methodName = "GetWorkflowRunAttemptLogs"
214+
testBadOptions(t, methodName, func() (err error) {
215+
_, _, err = client.Actions.GetWorkflowRunAttemptLogs(ctx, "\n", "\n", 399444496, 2, true)
216+
return err
217+
})
218+
}
219+
220+
func TestActionsService_GetWorkflowRunAttemptLogs_StatusMovedPermanently_dontFollowRedirects(t *testing.T) {
221+
client, mux, _, teardown := setup()
222+
defer teardown()
223+
224+
mux.HandleFunc("/repos/o/r/actions/runs/399444496/attempts/2/logs", func(w http.ResponseWriter, r *http.Request) {
225+
testMethod(t, r, "GET")
226+
http.Redirect(w, r, "http://github.com/a", http.StatusMovedPermanently)
227+
})
228+
229+
ctx := context.Background()
230+
_, resp, _ := client.Actions.GetWorkflowRunAttemptLogs(ctx, "o", "r", 399444496, 2, false)
231+
if resp.StatusCode != http.StatusMovedPermanently {
232+
t.Errorf("Actions.GetWorkflowRunAttemptLogs returned status: %d, want %d", resp.StatusCode, http.StatusMovedPermanently)
233+
}
234+
}
235+
236+
func TestActionsService_GetWorkflowRunAttemptLogs_StatusMovedPermanently_followRedirects(t *testing.T) {
237+
client, mux, serverURL, teardown := setup()
238+
defer teardown()
239+
240+
// Mock a redirect link, which leads to an archive link
241+
mux.HandleFunc("/repos/o/r/actions/runs/399444496/attempts/2/logs", func(w http.ResponseWriter, r *http.Request) {
242+
testMethod(t, r, "GET")
243+
redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect")
244+
http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently)
245+
})
246+
247+
mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
248+
testMethod(t, r, "GET")
249+
http.Redirect(w, r, "http://github.com/a", http.StatusFound)
250+
})
251+
252+
ctx := context.Background()
253+
url, resp, err := client.Actions.GetWorkflowRunAttemptLogs(ctx, "o", "r", 399444496, 2, true)
254+
if err != nil {
255+
t.Errorf("Actions.GetWorkflowRunAttemptLogs returned error: %v", err)
256+
}
257+
258+
if resp.StatusCode != http.StatusFound {
259+
t.Errorf("Actions.GetWorkflowRunAttemptLogs returned status: %d, want %d", resp.StatusCode, http.StatusFound)
260+
}
261+
262+
want := "http://github.com/a"
263+
if url.String() != want {
264+
t.Errorf("Actions.GetWorkflowRunAttemptLogs returned %+v, want %+v", url.String(), want)
265+
}
266+
267+
const methodName = "GetWorkflowRunAttemptLogs"
268+
testBadOptions(t, methodName, func() (err error) {
269+
_, _, err = client.Actions.GetWorkflowRunAttemptLogs(ctx, "\n", "\n", 399444496, 2, true)
270+
return err
271+
})
272+
}
273+
191274
func TestActionsService_RerunWorkflowRunByID(t *testing.T) {
192275
client, mux, _, teardown := setup()
193276
defer teardown()

0 commit comments

Comments
 (0)