fix: run 'go version' command in build.Dir (#2411)

Currently, the 'goVersion' function is run without any directory set.
This is problematic when a build uses the 'dir' config in combination
with the 'gobinary' config. When 'gobinary' is a relative path (like a
script in the current repository), goVersion silently fails, returning
an empty string.

This commit refactors 'goVersion' to execute the command with '.Dir' set
to the 'build.Dir', in addition to now returning an error, so that
issues may be bubbled up in the build log, rather than silently failing.

It also adds a new helper function to facilitate running 'goVersion' by
creating a temporary executable that outputs a given 'version' string.
This function is only currently used by 'TestWithDefaults'.

Co-authored-by: Rob Prentiss <prentiss@apple.com>
This commit is contained in:
Rob Prentiss
2021-08-21 10:56:54 -03:00
committed by GitHub
co-authored by Rob Prentiss
parent 5e006eb236
commit 013bd69126
4 changed files with 48 additions and 4 deletions
+5 -1
View File
@@ -59,7 +59,11 @@ func (*Builder) WithDefaults(build config.Build) (config.Build, error) {
if len(build.Gomips) == 0 {
build.Gomips = []string{"hardfloat"}
}
targets, err := matrix(build, goVersion(build))
version, err := goVersion(build)
if err != nil {
return build, err
}
targets, err := matrix(build, version)
build.Targets = targets
if err != nil {
return build, err
+26
View File
@@ -90,6 +90,9 @@ func TestWithDefaults(t *testing.T) {
},
} {
t.Run(name, func(t *testing.T) {
if testcase.build.GoBinary != "" && testcase.build.GoBinary != "go" {
helperCreateGoVersionExe(t, testcase.build.GoBinary, "go1.17")
}
config := config.Project{
Builds: []config.Build{
testcase.build,
@@ -105,6 +108,29 @@ func TestWithDefaults(t *testing.T) {
}
}
// helperCreateGoVersionExe creates a temporary executable with the given 'name', which will output
// a 'go version' string with the given 'version'. The temporary directory created by this function
// will be placed in the PATH variable for the duration of (and cleaned up at the end of) the
// current test run.
func helperCreateGoVersionExe(t *testing.T, name, version string) {
t.Helper()
d := t.TempDir()
f, err := os.Create(filepath.Join(d, name))
if err != nil {
t.Fatalf("unable to create temporary GoBinary file for testing: %v", err)
}
fmt.Fprintf(f, "#!/bin/sh\necho \"go version %s %s/%s\"\n", version, runtime.GOOS, runtime.GOARCH)
if err := f.Chmod(0o0755); err != nil {
t.Fatalf("unable to create temporary GoBinary file for testing: %v", err)
}
if err := f.Close(); err != nil {
t.Fatalf("unable to create temporary GoBinary file for testing: %v", err)
}
currentPath := os.Getenv("PATH")
t.Cleanup(func() { os.Setenv("PATH", currentPath) })
os.Setenv("PATH", fmt.Sprintf("%s%c%s", d, os.PathListSeparator, currentPath))
}
func TestInvalidTargets(t *testing.T) {
type testcase struct {
build config.Build
+8 -3
View File
@@ -131,9 +131,14 @@ var (
go117re = regexp.MustCompile(`go version go1.1[7-9]`)
)
func goVersion(build config.Build) []byte {
bts, _ := exec.Command(build.GoBinary, "version").CombinedOutput()
return bts
func goVersion(build config.Build) ([]byte, error) {
cmd := exec.Command(build.GoBinary, "version")
cmd.Dir = build.Dir // Set Dir to build directory in case of reletive path to GoBinary
bts, err := cmd.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("unable to determine version of go binary (%s): %w", build.GoBinary, err)
}
return bts, nil
}
func valid(target target) bool {
+9
View File
@@ -330,6 +330,15 @@ func TestDefaultPartialBuilds(t *testing.T) {
},
},
}
// Create any 'Dir' paths necessary for builds.
cwd, _ := os.Getwd()
t.Cleanup(func() { os.Chdir(cwd) })
os.Chdir(t.TempDir())
for _, b := range ctx.Config.Builds {
if b.Dir != "" {
os.Mkdir(b.Dir, 0o755)
}
}
require.NoError(t, Pipe{}.Default(ctx))
t.Run("build0", func(t *testing.T) {
build := ctx.Config.Builds[0]