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 }