From 5e6d1261f768a5c3f3af71ba8a98a89c9102bdc9 Mon Sep 17 00:00:00 2001 From: Sam Alba Date: Fri, 22 Oct 2021 15:37:28 -0700 Subject: [PATCH] mod: lock the version of universe for updates of package Signed-off-by: Sam Alba --- mod/file.go | 28 +++++++++++++++------------- mod/mod.go | 27 +++++++++++++++++++++++---- mod/repo.go | 38 ++++++++++++++++++++++++++++---------- mod/repo_test.go | 17 +++++++++++------ state/project.go | 15 +++++++-------- 5 files changed, 84 insertions(+), 41 deletions(-) diff --git a/mod/file.go b/mod/file.go index 733d1051..1cd4d89b 100644 --- a/mod/file.go +++ b/mod/file.go @@ -2,6 +2,7 @@ package mod import ( "bytes" + "context" "errors" "fmt" "io" @@ -15,11 +16,13 @@ import ( "github.com/spf13/viper" ) -const modFilePath = "./cue.mod/dagger.mod" -const sumFilePath = "./cue.mod/dagger.sum" -const lockFilePath = "./cue.mod/dagger.lock" -const destBasePath = "./cue.mod/pkg" -const tmpBasePath = "./cue.mod/tmp" +const ( + modFilePath = "./cue.mod/dagger.mod" + sumFilePath = "./cue.mod/dagger.sum" + lockFilePath = "./cue.mod/dagger.lock" + destBasePath = "./cue.mod/pkg" + tmpBasePath = "./cue.mod/tmp" +) // file is the parsed, interpreted form of dagger.mod file. type file struct { @@ -127,20 +130,19 @@ func nonEmptyLines(b []byte) []string { } trimmed = spaceRgx.ReplaceAllString(trimmed, " ") - lines = append(lines, trimmed) } return lines } -func (f *file) install(req *Require) error { +func (f *file) install(ctx context.Context, req *Require) error { // cleaning up possible leftovers tmpPath := path.Join(f.workspacePath, tmpBasePath, req.fullPath()) defer os.RemoveAll(tmpPath) // clone to a tmp directory - r, err := clone(req, tmpPath, viper.GetString("private-key-file"), viper.GetString("private-key-password")) + r, err := clone(ctx, req, tmpPath, viper.GetString("private-key-file"), viper.GetString("private-key-password")) if err != nil { return fmt.Errorf("error downloading package %s: %w", req, err) } @@ -169,7 +171,7 @@ func (f *file) install(req *Require) error { // checkout the cloned repo to that tag, change the version in the existing requirement and // replace the code in the /pkg folder existing.version = req.version - if err = r.checkout(req.version); err != nil { + if err = r.checkout(ctx, req.version); err != nil { return err } @@ -187,7 +189,7 @@ func (f *file) install(req *Require) error { return nil } -func (f *file) updateToLatest(req *Require) (*Require, error) { +func (f *file) updateToLatest(ctx context.Context, req *Require) (*Require, error) { // check if it doesn't exist existing := f.searchInstalledRequire(req) if existing == nil { @@ -199,13 +201,13 @@ func (f *file) updateToLatest(req *Require) (*Require, error) { defer os.RemoveAll(tmpPath) // clone to a tmp directory - gitRepo, err := clone(existing, tmpPath, viper.GetString("private-key-file"), viper.GetString("private-key-password")) + gitRepo, err := clone(ctx, existing, tmpPath, viper.GetString("private-key-file"), viper.GetString("private-key-password")) if err != nil { return nil, fmt.Errorf("error downloading package %s: %w", existing, err) } // checkout the latest tag - latestTag, err := gitRepo.latestTag(req.versionConstraint) + latestTag, err := gitRepo.latestTag(ctx, req.versionConstraint) if err != nil { return nil, err } @@ -220,7 +222,7 @@ func (f *file) updateToLatest(req *Require) (*Require, error) { } existing.version = latestTag - if err = gitRepo.checkout(existing.version); err != nil { + if err = gitRepo.checkout(ctx, existing.version); err != nil { return nil, err } diff --git a/mod/mod.go b/mod/mod.go index 57892b7e..22c841f5 100644 --- a/mod/mod.go +++ b/mod/mod.go @@ -3,15 +3,29 @@ package mod import ( "context" "path" + "strings" "github.com/gofrs/flock" "github.com/rs/zerolog/log" ) +const ( + UniverseVersionConstraint = ">= 0.1.0, < 0.2" +) + +func isUniverse(repoName string) bool { + return strings.HasPrefix(strings.ToLower(repoName), "alpha.dagger.io") +} + func Install(ctx context.Context, workspace, repoName, versionConstraint string) (*Require, error) { lg := log.Ctx(ctx) - lg.Info().Str("name", repoName).Msg("installing module") + if isUniverse(repoName) { + // override versionConstraint to lock the version of universe we vendor + versionConstraint = UniverseVersionConstraint + } + + lg.Debug().Str("name", repoName).Msg("installing module") require, err := newRequire(repoName, versionConstraint) if err != nil { return nil, err @@ -27,7 +41,7 @@ func Install(ctx context.Context, workspace, repoName, versionConstraint string) return nil, err } - err = modfile.install(require) + err = modfile.install(ctx, require) if err != nil { return nil, err } @@ -63,7 +77,12 @@ func InstallAll(ctx context.Context, workspace string, repoNames []string) ([]*R func Update(ctx context.Context, workspace, repoName, versionConstraint string) (*Require, error) { lg := log.Ctx(ctx) - lg.Info().Str("name", repoName).Msg("updating module") + if isUniverse(repoName) { + // override versionConstraint to lock the version of universe we vendor + versionConstraint = UniverseVersionConstraint + } + + lg.Debug().Str("name", repoName).Msg("updating module") require, err := newRequire(repoName, versionConstraint) if err != nil { return nil, err @@ -79,7 +98,7 @@ func Update(ctx context.Context, workspace, repoName, versionConstraint string) return nil, err } - updatedRequire, err := modfile.updateToLatest(require) + updatedRequire, err := modfile.updateToLatest(ctx, require) if err != nil { return nil, err } diff --git a/mod/repo.go b/mod/repo.go index 09257054..efc894d3 100644 --- a/mod/repo.go +++ b/mod/repo.go @@ -1,12 +1,14 @@ package mod import ( + "context" "fmt" "os" "sort" "strings" "github.com/go-git/go-git/v5/plumbing/transport/ssh" + "github.com/rs/zerolog/log" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" @@ -15,9 +17,10 @@ import ( type repo struct { contents *git.Repository + require *Require } -func clone(require *Require, dir string, privateKeyFile, privateKeyPassword string) (*repo, error) { +func clone(ctx context.Context, require *Require, dir string, privateKeyFile, privateKeyPassword string) (*repo, error) { if err := os.RemoveAll(dir); err != nil { return nil, fmt.Errorf("error cleaning up tmp directory") } @@ -46,10 +49,11 @@ func clone(require *Require, dir string, privateKeyFile, privateKeyPassword stri rr := &repo{ contents: r, + require: require, } if require.version == "" { - latestTag, err := rr.latestTag(require.versionConstraint) + latestTag, err := rr.latestTag(ctx, require.versionConstraint) if err != nil { return nil, err } @@ -57,19 +61,23 @@ func clone(require *Require, dir string, privateKeyFile, privateKeyPassword stri require.version = latestTag } - if err := rr.checkout(require.version); err != nil { + if err := rr.checkout(ctx, require.version); err != nil { return nil, err } return rr, nil } -func (r *repo) checkout(version string) error { +func (r *repo) checkout(ctx context.Context, version string) error { + lg := log.Ctx(ctx) + h, err := r.contents.ResolveRevision(plumbing.Revision(version)) if err != nil { return err } + lg.Debug().Str("repository", r.require.repo).Str("version", version).Str("commit", h.String()).Msg("checkout repo") + w, err := r.contents.Worktree() if err != nil { return err @@ -85,7 +93,12 @@ func (r *repo) checkout(version string) error { return nil } -func (r *repo) listTagVersions(versionConstraint string) ([]string, error) { +func (r *repo) listTagVersions(ctx context.Context, versionConstraint string) ([]string, error) { + lg := log.Ctx(ctx).With(). + Str("repository", r.require.repo). + Str("versionConstraint", versionConstraint). + Logger() + if versionConstraint == "" { versionConstraint = ">= 0" } @@ -105,19 +118,22 @@ func (r *repo) listTagVersions(versionConstraint string) ([]string, error) { tagV := ref.Name().Short() if !strings.HasPrefix(tagV, "v") { - // ignore wrong formatted tags + lg.Debug().Str("tag", tagV).Msg("tag version ignored, wrong format") return nil } v, err := version.NewVersion(tagV) if err != nil { - // ignore invalid tag + lg.Debug().Str("tag", tagV).Err(err).Msg("tag version ignored, parsing error") return nil } if constraint.Check(v) { // Add tag if it matches the version constraint tags = append(tags, ref.Name().Short()) + lg.Debug().Str("tag", tagV).Msg("version added") + } else { + lg.Debug().Str("tag", tagV).Msg("tag version ignored, does not satisfy constraint") } return nil @@ -130,8 +146,8 @@ func (r *repo) listTagVersions(versionConstraint string) ([]string, error) { return tags, nil } -func (r *repo) latestTag(versionConstraint string) (string, error) { - versionsRaw, err := r.listTagVersions(versionConstraint) +func (r *repo) latestTag(ctx context.Context, versionConstraint string) (string, error) { + versionsRaw, err := r.listTagVersions(ctx, versionConstraint) if err != nil { return "", err } @@ -147,5 +163,7 @@ func (r *repo) latestTag(versionConstraint string) (string, error) { } sort.Sort(sort.Reverse(version.Collection(versions))) - return versions[0].Original(), nil + version := versions[0].Original() + + return version, nil } diff --git a/mod/repo_test.go b/mod/repo_test.go index efd6c747..54603037 100644 --- a/mod/repo_test.go +++ b/mod/repo_test.go @@ -1,6 +1,7 @@ package mod import ( + "context" "io/ioutil" "os" "testing" @@ -50,7 +51,7 @@ func TestClone(t *testing.T) { defer os.Remove(tmpDir) - _, err = clone(&c.require, tmpDir, c.privateKeyFile, c.privateKeyPassword) + _, err = clone(context.TODO(), &c.require, tmpDir, c.privateKeyFile, c.privateKeyPassword) if err != nil { t.Error(err) } @@ -65,7 +66,9 @@ func TestListTags(t *testing.T) { } defer os.Remove(tmpDir) - r, err := clone(&Require{ + ctx := context.TODO() + + r, err := clone(ctx, &Require{ cloneRepo: "github.com/dagger/universe", clonePath: "stdlib", version: "", @@ -74,7 +77,7 @@ func TestListTags(t *testing.T) { t.Fatal(err) } - tags, err := r.listTagVersions("") + tags, err := r.listTagVersions(ctx, "") if err != nil { t.Error(err) } @@ -91,7 +94,9 @@ func TestVersionConstraint(t *testing.T) { } defer os.Remove(tmpDir) - r, err := clone(&Require{ + ctx := context.TODO() + + r, err := clone(ctx, &Require{ cloneRepo: "github.com/dagger/universe", clonePath: "stdlib", version: "", @@ -100,7 +105,7 @@ func TestVersionConstraint(t *testing.T) { t.Fatal(err) } - tagVersion, err := r.latestTag("<= 0.1.0") + tagVersion, err := r.latestTag(ctx, "<= 0.1.0") if err != nil { t.Error(err) } @@ -111,7 +116,7 @@ func TestVersionConstraint(t *testing.T) { } // Make sure an invalid constraint (version out of range) returns an error - _, err = r.latestTag("> 99999") + _, err = r.latestTag(ctx, "> 99999") if err == nil { t.Error("selected wrong version based on constraint") } diff --git a/state/project.go b/state/project.go index adc72da3..de208ea2 100644 --- a/state/project.go +++ b/state/project.go @@ -25,13 +25,12 @@ var ( ) const ( - daggerDir = ".dagger" - envDir = "env" - stateDir = "state" - planDir = "plan" - manifestFile = "values.yaml" - computedFile = "computed.json" - universeVersionConstraint = ">= 0.1, < 0.2" + daggerDir = ".dagger" + envDir = "env" + stateDir = "state" + planDir = "plan" + manifestFile = "values.yaml" + computedFile = "computed.json" ) type Project struct { @@ -398,7 +397,7 @@ func vendorUniverse(ctx context.Context, p string) error { } log.Ctx(ctx).Debug().Str("mod", p).Msg("vendoring universe") - if _, err := mod.Install(ctx, p, "alpha.dagger.io", universeVersionConstraint); err != nil { + if _, err := mod.Install(ctx, p, "alpha.dagger.io", ""); err != nil { return err }