...

Source file src/edge-infra.dev/pkg/f8n/devinfra/github/ghfs/fetcher.go

Documentation: edge-infra.dev/pkg/f8n/devinfra/github/ghfs

     1  package ghfs
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"io/fs"
     8  
     9  	"github.com/google/go-github/v47/github"
    10  )
    11  
    12  // fetcher defines the operations we need to take against GitHub so that we can
    13  // easily provide alternative implementations
    14  type fetcher interface {
    15  	getContents(name string) (*github.RepositoryContent, []*github.RepositoryContent, error)
    16  	downloadContents(c *github.RepositoryContent) (io.ReadCloser, error)
    17  }
    18  
    19  // ghFetcher talks to GitHub and is used by default
    20  type ghFetcher struct {
    21  	gh               *github.Client
    22  	ctx              context.Context
    23  	owner, repo, ref string
    24  }
    25  
    26  func (f *ghFetcher) getContents(name string) (
    27  	*github.RepositoryContent, []*github.RepositoryContent, error,
    28  ) {
    29  	file, dir, res, err := f.gh.Repositories.GetContents(
    30  		f.ctx,
    31  		f.owner,
    32  		f.repo,
    33  		name,
    34  		&github.RepositoryContentGetOptions{Ref: f.ref},
    35  	)
    36  
    37  	if err := f.responseToErr(name, res, err); err != nil {
    38  		return nil, nil, err
    39  	}
    40  
    41  	return file, dir, nil
    42  }
    43  
    44  func (f *ghFetcher) downloadContents(file *github.RepositoryContent) (io.ReadCloser, error) {
    45  	if file.GetDownloadURL() == "" {
    46  		return nil, fmt.Errorf("unexpected state: file has no download URL")
    47  	}
    48  	dlRes, err := f.gh.Client().Get(file.GetDownloadURL())
    49  	if err := f.responseToErr(file.GetPath(), &github.Response{Response: dlRes}, err); err != nil {
    50  		return nil, err
    51  	}
    52  	return dlRes.Body, nil
    53  }
    54  
    55  // responseToErr checks the response and error from a GitHub operation and
    56  // consolidates it into a single error to check
    57  func (f *ghFetcher) responseToErr(name string, res *github.Response, err error) error {
    58  	// Failure response codes, explicitly check because the request can fail with
    59  	// a nil err.
    60  	switch {
    61  	case res.StatusCode == 404:
    62  		return fmt.Errorf("%w: %s not found in %s/%s@%s",
    63  			fs.ErrNotExist, name, f.owner, f.repo, f.ref)
    64  	case res.StatusCode == 403:
    65  		return fmt.Errorf("%w: failed to retrieve %s from %s/%s@%s",
    66  			fs.ErrPermission, name, f.owner, f.repo, f.ref)
    67  	case err != nil:
    68  		return fmt.Errorf("failed to retrieve %s from %s/%s@%s: %w",
    69  			name, f.owner, f.repo, f.ref, err)
    70  	default:
    71  		return nil
    72  	}
    73  }
    74  

View as plain text