github.com/google/go-github/v33@v33.0.0/github/actions_workflow_jobs.go (about) 1 // Copyright 2020 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "fmt" 11 "net/http" 12 "net/url" 13 ) 14 15 // TaskStep represents a single task step from a sequence of tasks of a job. 16 type TaskStep struct { 17 Name *string `json:"name,omitempty"` 18 Status *string `json:"status,omitempty"` 19 Conclusion *string `json:"conclusion,omitempty"` 20 Number *int64 `json:"number,omitempty"` 21 StartedAt *Timestamp `json:"started_at,omitempty"` 22 CompletedAt *Timestamp `json:"completed_at,omitempty"` 23 } 24 25 // WorkflowJob represents a repository action workflow job. 26 type WorkflowJob struct { 27 ID *int64 `json:"id,omitempty"` 28 RunID *int64 `json:"run_id,omitempty"` 29 RunURL *string `json:"run_url,omitempty"` 30 NodeID *string `json:"node_id,omitempty"` 31 HeadSHA *string `json:"head_sha,omitempty"` 32 URL *string `json:"url,omitempty"` 33 HTMLURL *string `json:"html_url,omitempty"` 34 Status *string `json:"status,omitempty"` 35 Conclusion *string `json:"conclusion,omitempty"` 36 StartedAt *Timestamp `json:"started_at,omitempty"` 37 CompletedAt *Timestamp `json:"completed_at,omitempty"` 38 Name *string `json:"name,omitempty"` 39 Steps []*TaskStep `json:"steps,omitempty"` 40 CheckRunURL *string `json:"check_run_url,omitempty"` 41 } 42 43 // Jobs represents a slice of repository action workflow job. 44 type Jobs struct { 45 TotalCount *int `json:"total_count,omitempty"` 46 Jobs []*WorkflowJob `json:"jobs,omitempty"` 47 } 48 49 // ListWorkflowJobsOptions specifies optional parameters to ListWorkflowJobs. 50 type ListWorkflowJobsOptions struct { 51 // Filter specifies how jobs should be filtered by their completed_at timestamp. 52 // Possible values are: 53 // latest - Returns jobs from the most recent execution of the workflow run 54 // all - Returns all jobs for a workflow run, including from old executions of the workflow run 55 // 56 // Default value is "latest". 57 Filter string `url:"filter,omitempty"` 58 ListOptions 59 } 60 61 // ListWorkflowJobs lists all jobs for a workflow run. 62 // 63 // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/actions/#list-jobs-for-a-workflow-run 64 func (s *ActionsService) ListWorkflowJobs(ctx context.Context, owner, repo string, runID int64, opts *ListWorkflowJobsOptions) (*Jobs, *Response, error) { 65 u := fmt.Sprintf("repos/%s/%s/actions/runs/%v/jobs", owner, repo, runID) 66 u, err := addOptions(u, opts) 67 if err != nil { 68 return nil, nil, err 69 } 70 71 req, err := s.client.NewRequest("GET", u, nil) 72 if err != nil { 73 return nil, nil, err 74 } 75 76 jobs := new(Jobs) 77 resp, err := s.client.Do(ctx, req, &jobs) 78 if err != nil { 79 return nil, resp, err 80 } 81 82 return jobs, resp, nil 83 } 84 85 // GetWorkflowJobByID gets a specific job in a workflow run by ID. 86 // 87 // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/actions/#get-a-job-for-a-workflow-run 88 func (s *ActionsService) GetWorkflowJobByID(ctx context.Context, owner, repo string, jobID int64) (*WorkflowJob, *Response, error) { 89 u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v", owner, repo, jobID) 90 91 req, err := s.client.NewRequest("GET", u, nil) 92 if err != nil { 93 return nil, nil, err 94 } 95 96 job := new(WorkflowJob) 97 resp, err := s.client.Do(ctx, req, job) 98 if err != nil { 99 return nil, resp, err 100 } 101 102 return job, resp, nil 103 } 104 105 // GetWorkflowJobLogs gets a redirect URL to download a plain text file of logs for a workflow job. 106 // 107 // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/actions/#download-job-logs-for-a-workflow-run 108 func (s *ActionsService) GetWorkflowJobLogs(ctx context.Context, owner, repo string, jobID int64, followRedirects bool) (*url.URL, *Response, error) { 109 u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v/logs", owner, repo, jobID) 110 111 resp, err := s.getWorkflowLogsFromURL(ctx, u, followRedirects) 112 if err != nil { 113 return nil, nil, err 114 } 115 116 if resp.StatusCode != http.StatusFound { 117 return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) 118 } 119 parsedURL, err := url.Parse(resp.Header.Get("Location")) 120 return parsedURL, newResponse(resp), err 121 } 122 123 func (s *ActionsService) getWorkflowLogsFromURL(ctx context.Context, u string, followRedirects bool) (*http.Response, error) { 124 req, err := s.client.NewRequest("GET", u, nil) 125 if err != nil { 126 return nil, err 127 } 128 129 var resp *http.Response 130 // Use http.DefaultTransport if no custom Transport is configured 131 req = withContext(ctx, req) 132 if s.client.client.Transport == nil { 133 resp, err = http.DefaultTransport.RoundTrip(req) 134 } else { 135 resp, err = s.client.client.Transport.RoundTrip(req) 136 } 137 if err != nil { 138 return nil, err 139 } 140 resp.Body.Close() 141 142 // If redirect response is returned, follow it 143 if followRedirects && resp.StatusCode == http.StatusMovedPermanently { 144 u = resp.Header.Get("Location") 145 resp, err = s.getWorkflowLogsFromURL(ctx, u, false) 146 } 147 return resp, err 148 149 }