From 7c67d1e86b570a02d2f14be24c37ff44df1a03ca Mon Sep 17 00:00:00 2001 From: Brian Gibbins Date: Mon, 15 Mar 2021 16:02:54 +0000 Subject: [PATCH] Download go modules before building (#20) Fixes #14 --- internal/builder/main.go | 62 ++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/internal/builder/main.go b/internal/builder/main.go index 45bebb2ee38..b199c012897 100644 --- a/internal/builder/main.go +++ b/internal/builder/main.go @@ -21,6 +21,7 @@ import ( "os/exec" "path/filepath" "text/template" + "time" "github.com/open-telemetry/opentelemetry-collector-builder/internal/scaffold" ) @@ -33,12 +34,17 @@ var ( ErrGoNotFound = errors.New("Go binary not found") ) -// GenerateAndCompile will generate the source files based on the given configuration and will compile it into a binary +// GenerateAndCompile will generate the source files based on the given configuration, update go mod, and will compile into a binary func GenerateAndCompile(cfg Config) error { if err := Generate(cfg); err != nil { return err } + // run go get to update go.mod and go.sum files + if err := GetModules(cfg); err != nil { + return err + } + return Compile(cfg) } @@ -83,15 +89,10 @@ func Generate(cfg Config) error { // Compile generates a binary from the sources based on the configuration func Compile(cfg Config) error { - goBinary := cfg.Distribution.Go // first, we test to check if we have Go at all - if _, err := exec.Command(goBinary, "env").CombinedOutput(); err != nil { - path, err := exec.LookPath("go") - if err != nil { - return ErrGoNotFound - } - goBinary = path - cfg.Logger.Info("Using go from PATH", "Go executable", path) + goBinary, err := getGoPath(cfg) + if err != nil { + return err } cfg.Logger.Info("Compiling") @@ -105,6 +106,49 @@ func Compile(cfg Config) error { return nil } +// GetModules retrieves the go modules, updating go.mod and go.sum in the process +func GetModules(cfg Config) error { + // first, we test to check if we have Go at all + goBinary, err := getGoPath(cfg) + if err != nil { + return err + } + + cfg.Logger.Info("Getting go modules") + cmd := exec.Command(goBinary, "mod", "download") + cmd.Dir = cfg.Distribution.OutputPath + + // basic retry if error from go mod command (in case of transient network error). This could be improved + // retry 3 times with 5 second spacing interval + retries := 3 + failReason := "unknown" + for i := 1; i <= retries; i++ { + if out, err := cmd.CombinedOutput(); err != nil { + failReason = fmt.Sprintf("%s. Output: %q", err, out) + cfg.Logger.Info("Failed modules download", "retry", fmt.Sprintf("%d/%d", i, retries)) + time.Sleep(5 * time.Second) + continue + } + return nil + } + return fmt.Errorf("failed to download go modules: %s", failReason) +} + +// getGoPath checks if go is present and correct, and returns a useable go bin location +func getGoPath(cfg Config) (string, error) { + goBinary := cfg.Distribution.Go + if _, err := exec.Command(goBinary, "env").CombinedOutput(); err != nil { + path, err := exec.LookPath("go") + if err != nil { + return "", ErrGoNotFound + } + goBinary = path + cfg.Logger.Info("Using go from PATH", "Go executable", path) + } + + return goBinary, nil +} + func processAndWrite(cfg Config, tmpl string, outFile string, tmplParams interface{}) error { t, err := template.New("template").Parse(tmpl) if err != nil {