github.com/replicatedcom/ship@v0.50.0/pkg/specs/replicatedapp/local.go (about)

     1  // local.go has methods for resolving a local ship.yaml file, and patching in api.Release info
     2  // that would usually be returned by pg.replicated.com
     3  package replicatedapp
     4  
     5  import (
     6  	"bytes"
     7  	"crypto/sha256"
     8  	"encoding/base64"
     9  	"fmt"
    10  	"os"
    11  	"strings"
    12  
    13  	"github.com/go-kit/kit/log"
    14  	"github.com/go-kit/kit/log/level"
    15  	"github.com/pkg/errors"
    16  	"github.com/replicatedhq/ship/pkg/constants"
    17  	"github.com/replicatedhq/ship/pkg/state"
    18  )
    19  
    20  func (r *resolver) resolveRunbookRelease(selector *Selector) (*state.ShipRelease, error) {
    21  	debug := level.Debug(log.With(r.Logger, "method", "resolveRunbookRelease"))
    22  	debug.Log("phase", "load-specs", "from", "runbook", "file", r.Runbook)
    23  
    24  	specYAML, err := r.FS.ReadFile(r.Runbook)
    25  	if err != nil {
    26  		return nil, errors.Wrapf(err, "read specs from %s", r.Runbook)
    27  	}
    28  	debug.Log("phase", "load-specs", "from", "runbook", "file", r.Runbook, "spec", specYAML)
    29  
    30  	if err := r.persistSpec(specYAML); err != nil {
    31  		return nil, errors.Wrapf(err, "serialize last-used YAML to disk")
    32  	}
    33  	debug.Log("phase", "write-yaml", "from", r.Runbook, "write-location", constants.ReleasePath)
    34  
    35  	fakeGithubContents, err := r.loadLocalGitHubContents()
    36  	if err != nil {
    37  		return nil, errors.Wrapf(err, "load fake github contents")
    38  	}
    39  
    40  	fakeEntitlements, err := r.loadFakeEntitlements()
    41  	if err != nil {
    42  		return nil, errors.Wrapf(err, "load fake entitlements")
    43  	}
    44  
    45  	var semver string
    46  	if r.RunbookReleaseSemver != "" {
    47  		semver = r.RunbookReleaseSemver
    48  	} else {
    49  		semver = selector.ReleaseSemver
    50  	}
    51  
    52  	return &state.ShipRelease{
    53  		Spec:           string(specYAML),
    54  		ChannelName:    r.SetChannelName,
    55  		ChannelIcon:    r.SetChannelIcon,
    56  		Semver:         semver,
    57  		GithubContents: fakeGithubContents,
    58  		Entitlements:   *fakeEntitlements,
    59  		Images:         []state.Image{},
    60  	}, nil
    61  }
    62  
    63  func (r *resolver) loadLocalGitHubContents() ([]state.GithubContent, error) {
    64  	debug := level.Debug(log.With(r.Logger, "method", "loadLocalGitHubContents"))
    65  	fakeGithubContents := []state.GithubContent{}
    66  	for _, content := range r.SetGitHubContents {
    67  		debug.Log("event", "githubcontents.set", "received", content)
    68  		split := strings.Split(content, ":")
    69  		if len(split) != 4 {
    70  			return nil, errors.Errorf("set-github-contents %q invalid, expected a REPO:REPO_PATH:REF:LOCAL_PATH", content)
    71  		}
    72  		repo := split[0]
    73  		repoPath := split[1]
    74  		ref := split[2]
    75  		localpath := split[3]
    76  
    77  		debug.Log("event", "githubcontents.loadFiles", "localPath", localpath)
    78  		files, err := r.loadLocalGithubFiles(localpath, repoPath)
    79  		if err != nil {
    80  			return nil, errors.Wrapf(err, "set github files")
    81  		}
    82  
    83  		fakeGithubContents = append(fakeGithubContents, state.GithubContent{
    84  			Repo:  repo,
    85  			Path:  repoPath,
    86  			Ref:   ref,
    87  			Files: files,
    88  		})
    89  		debug.Log("event", "githubcontents.set.finished", "received", content)
    90  	}
    91  	return fakeGithubContents, nil
    92  }
    93  
    94  func (r *resolver) loadLocalGithubFiles(localpath string, repoPath string) ([]state.GithubFile, error) {
    95  	debug := level.Debug(log.With(r.Logger, "method", "loadLocalGitHubFiles"))
    96  	var files []state.GithubFile
    97  	err := r.FS.Walk(localpath, func(path string, info os.FileInfo, err error) error {
    98  		if err != nil {
    99  			return errors.Wrapf(err, "walk %+v from %s", info, path)
   100  		}
   101  
   102  		if info.IsDir() {
   103  			return nil
   104  		}
   105  
   106  		walkRepoPath := strings.TrimPrefix(path, localpath)
   107  		if !strings.HasPrefix(strings.Trim(walkRepoPath, "/"), strings.Trim(repoPath, "/")) {
   108  			return nil
   109  		}
   110  
   111  		contents, err := r.FS.ReadFile(path)
   112  		if err != nil {
   113  			return errors.Wrapf(err, "read %s from %s", info.Name(), path)
   114  		}
   115  		debug.Log("event", "githubcontents.loadFile.complete", "path", path, "name", info.Name())
   116  
   117  		encodedData := &bytes.Buffer{}
   118  		encoder := base64.NewEncoder(base64.StdEncoding, encodedData)
   119  		encoder.Write(contents)
   120  		encoder.Close()
   121  		sha := fmt.Sprintf("%x", sha256.Sum256(contents))
   122  		files = append(files, state.GithubFile{
   123  			Name: info.Name(),
   124  			Path: walkRepoPath,
   125  			Sha:  sha,
   126  			Size: info.Size(),
   127  			Data: encodedData.String(),
   128  		})
   129  		return nil
   130  	})
   131  	return files, err
   132  }