github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/run/shared/artifacts.go (about)

     1  package shared
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"regexp"
     8  
     9  	"github.com/ungtb10d/cli/v2/api"
    10  	"github.com/ungtb10d/cli/v2/internal/ghinstance"
    11  	"github.com/ungtb10d/cli/v2/internal/ghrepo"
    12  )
    13  
    14  type Artifact struct {
    15  	Name        string `json:"name"`
    16  	Size        uint64 `json:"size_in_bytes"`
    17  	DownloadURL string `json:"archive_download_url"`
    18  	Expired     bool   `json:"expired"`
    19  }
    20  
    21  type artifactsPayload struct {
    22  	Artifacts []Artifact
    23  }
    24  
    25  func ListArtifacts(httpClient *http.Client, repo ghrepo.Interface, runID string) ([]Artifact, error) {
    26  	var results []Artifact
    27  
    28  	perPage := 100
    29  	path := fmt.Sprintf("repos/%s/%s/actions/artifacts?per_page=%d", repo.RepoOwner(), repo.RepoName(), perPage)
    30  	if runID != "" {
    31  		path = fmt.Sprintf("repos/%s/%s/actions/runs/%s/artifacts?per_page=%d", repo.RepoOwner(), repo.RepoName(), runID, perPage)
    32  	}
    33  
    34  	url := fmt.Sprintf("%s%s", ghinstance.RESTPrefix(repo.RepoHost()), path)
    35  
    36  	for {
    37  		var payload artifactsPayload
    38  		nextURL, err := apiGet(httpClient, url, &payload)
    39  		if err != nil {
    40  			return nil, err
    41  		}
    42  		results = append(results, payload.Artifacts...)
    43  
    44  		if nextURL == "" {
    45  			break
    46  		}
    47  		url = nextURL
    48  	}
    49  
    50  	return results, nil
    51  }
    52  
    53  func apiGet(httpClient *http.Client, url string, data interface{}) (string, error) {
    54  	req, err := http.NewRequest("GET", url, nil)
    55  	if err != nil {
    56  		return "", err
    57  	}
    58  
    59  	resp, err := httpClient.Do(req)
    60  	if err != nil {
    61  		return "", err
    62  	}
    63  	defer resp.Body.Close()
    64  
    65  	if resp.StatusCode > 299 {
    66  		return "", api.HandleHTTPError(resp)
    67  	}
    68  
    69  	dec := json.NewDecoder(resp.Body)
    70  	if err := dec.Decode(data); err != nil {
    71  		return "", err
    72  	}
    73  
    74  	return findNextPage(resp), nil
    75  }
    76  
    77  var linkRE = regexp.MustCompile(`<([^>]+)>;\s*rel="([^"]+)"`)
    78  
    79  func findNextPage(resp *http.Response) string {
    80  	for _, m := range linkRE.FindAllStringSubmatch(resp.Header.Get("Link"), -1) {
    81  		if len(m) > 2 && m[2] == "next" {
    82  			return m[1]
    83  		}
    84  	}
    85  	return ""
    86  }