github.com/google/go-github/v74@v74.0.0/github/actions_artifacts.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  // ArtifactWorkflowRun represents a GitHub artifact's workflow run.
    16  //
    17  // GitHub API docs: https://docs.github.com/rest/actions/artifacts
    18  type ArtifactWorkflowRun struct {
    19  	ID               *int64  `json:"id,omitempty"`
    20  	RepositoryID     *int64  `json:"repository_id,omitempty"`
    21  	HeadRepositoryID *int64  `json:"head_repository_id,omitempty"`
    22  	HeadBranch       *string `json:"head_branch,omitempty"`
    23  	HeadSHA          *string `json:"head_sha,omitempty"`
    24  }
    25  
    26  // Artifact represents a GitHub artifact.  Artifacts allow sharing
    27  // data between jobs in a workflow and provide storage for data
    28  // once a workflow is complete.
    29  //
    30  // GitHub API docs: https://docs.github.com/rest/actions/artifacts
    31  type Artifact struct {
    32  	ID                 *int64     `json:"id,omitempty"`
    33  	NodeID             *string    `json:"node_id,omitempty"`
    34  	Name               *string    `json:"name,omitempty"`
    35  	SizeInBytes        *int64     `json:"size_in_bytes,omitempty"`
    36  	URL                *string    `json:"url,omitempty"`
    37  	ArchiveDownloadURL *string    `json:"archive_download_url,omitempty"`
    38  	Expired            *bool      `json:"expired,omitempty"`
    39  	CreatedAt          *Timestamp `json:"created_at,omitempty"`
    40  	UpdatedAt          *Timestamp `json:"updated_at,omitempty"`
    41  	ExpiresAt          *Timestamp `json:"expires_at,omitempty"`
    42  	// Digest is the SHA256 digest of the artifact.
    43  	// This field will only be populated on artifacts uploaded with upload-artifact v4 or newer.
    44  	// For older versions, this field will be null.
    45  	Digest      *string              `json:"digest,omitempty"`
    46  	WorkflowRun *ArtifactWorkflowRun `json:"workflow_run,omitempty"`
    47  }
    48  
    49  // ArtifactList represents a list of GitHub artifacts.
    50  //
    51  // GitHub API docs: https://docs.github.com/rest/actions/artifacts#artifacts
    52  type ArtifactList struct {
    53  	TotalCount *int64      `json:"total_count,omitempty"`
    54  	Artifacts  []*Artifact `json:"artifacts,omitempty"`
    55  }
    56  
    57  // ListArtifactsOptions specifies the optional parameters to the
    58  // ActionsService.ListArtifacts method.
    59  type ListArtifactsOptions struct {
    60  	// Name represents the name field of an artifact.
    61  	// When specified, only artifacts with this name will be returned.
    62  	Name *string `url:"name,omitempty"`
    63  
    64  	ListOptions
    65  }
    66  
    67  // ListArtifacts lists all artifacts that belong to a repository.
    68  //
    69  // GitHub API docs: https://docs.github.com/rest/actions/artifacts#list-artifacts-for-a-repository
    70  //
    71  //meta:operation GET /repos/{owner}/{repo}/actions/artifacts
    72  func (s *ActionsService) ListArtifacts(ctx context.Context, owner, repo string, opts *ListArtifactsOptions) (*ArtifactList, *Response, error) {
    73  	u := fmt.Sprintf("repos/%v/%v/actions/artifacts", owner, repo)
    74  	u, err := addOptions(u, opts)
    75  	if err != nil {
    76  		return nil, nil, err
    77  	}
    78  
    79  	req, err := s.client.NewRequest("GET", u, nil)
    80  	if err != nil {
    81  		return nil, nil, err
    82  	}
    83  
    84  	artifactList := new(ArtifactList)
    85  	resp, err := s.client.Do(ctx, req, artifactList)
    86  	if err != nil {
    87  		return nil, resp, err
    88  	}
    89  
    90  	return artifactList, resp, nil
    91  }
    92  
    93  // ListWorkflowRunArtifacts lists all artifacts that belong to a workflow run.
    94  //
    95  // GitHub API docs: https://docs.github.com/rest/actions/artifacts#list-workflow-run-artifacts
    96  //
    97  //meta:operation GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts
    98  func (s *ActionsService) ListWorkflowRunArtifacts(ctx context.Context, owner, repo string, runID int64, opts *ListOptions) (*ArtifactList, *Response, error) {
    99  	u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/artifacts", owner, repo, runID)
   100  	u, err := addOptions(u, opts)
   101  	if err != nil {
   102  		return nil, nil, err
   103  	}
   104  
   105  	req, err := s.client.NewRequest("GET", u, nil)
   106  	if err != nil {
   107  		return nil, nil, err
   108  	}
   109  
   110  	artifactList := new(ArtifactList)
   111  	resp, err := s.client.Do(ctx, req, artifactList)
   112  	if err != nil {
   113  		return nil, resp, err
   114  	}
   115  
   116  	return artifactList, resp, nil
   117  }
   118  
   119  // GetArtifact gets a specific artifact for a workflow run.
   120  //
   121  // GitHub API docs: https://docs.github.com/rest/actions/artifacts#get-an-artifact
   122  //
   123  //meta:operation GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}
   124  func (s *ActionsService) GetArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Artifact, *Response, error) {
   125  	u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID)
   126  
   127  	req, err := s.client.NewRequest("GET", u, nil)
   128  	if err != nil {
   129  		return nil, nil, err
   130  	}
   131  
   132  	artifact := new(Artifact)
   133  	resp, err := s.client.Do(ctx, req, artifact)
   134  	if err != nil {
   135  		return nil, resp, err
   136  	}
   137  
   138  	return artifact, resp, nil
   139  }
   140  
   141  // DownloadArtifact gets a redirect URL to download an archive for a repository.
   142  //
   143  // GitHub API docs: https://docs.github.com/rest/actions/artifacts#download-an-artifact
   144  //
   145  //meta:operation GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}
   146  func (s *ActionsService) DownloadArtifact(ctx context.Context, owner, repo string, artifactID int64, maxRedirects int) (*url.URL, *Response, error) {
   147  	u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v/zip", owner, repo, artifactID)
   148  
   149  	if s.client.RateLimitRedirectionalEndpoints {
   150  		return s.downloadArtifactWithRateLimit(ctx, u, maxRedirects)
   151  	}
   152  
   153  	return s.downloadArtifactWithoutRateLimit(ctx, u, maxRedirects)
   154  }
   155  
   156  func (s *ActionsService) downloadArtifactWithoutRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) {
   157  	resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects)
   158  	if err != nil {
   159  		return nil, nil, err
   160  	}
   161  	defer resp.Body.Close()
   162  
   163  	if resp.StatusCode != http.StatusFound {
   164  		return nil, newResponse(resp), fmt.Errorf("unexpected status code: %v", resp.Status)
   165  	}
   166  
   167  	parsedURL, err := url.Parse(resp.Header.Get("Location"))
   168  	if err != nil {
   169  		return nil, newResponse(resp), err
   170  	}
   171  
   172  	return parsedURL, newResponse(resp), nil
   173  }
   174  
   175  func (s *ActionsService) downloadArtifactWithRateLimit(ctx context.Context, u string, maxRedirects int) (*url.URL, *Response, error) {
   176  	req, err := s.client.NewRequest("GET", u, nil)
   177  	if err != nil {
   178  		return nil, nil, err
   179  	}
   180  
   181  	url, resp, err := s.client.bareDoUntilFound(ctx, req, maxRedirects)
   182  	if err != nil {
   183  		return nil, resp, err
   184  	}
   185  	defer resp.Body.Close()
   186  
   187  	// If we didn't receive a valid Location in a 302 response
   188  	if url == nil {
   189  		return nil, resp, fmt.Errorf("unexpected status code: %v", resp.Status)
   190  	}
   191  
   192  	return url, resp, nil
   193  }
   194  
   195  // DeleteArtifact deletes a workflow run artifact.
   196  //
   197  // GitHub API docs: https://docs.github.com/rest/actions/artifacts#delete-an-artifact
   198  //
   199  //meta:operation DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id}
   200  func (s *ActionsService) DeleteArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Response, error) {
   201  	u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID)
   202  
   203  	req, err := s.client.NewRequest("DELETE", u, nil)
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  
   208  	return s.client.Do(ctx, req, nil)
   209  }