Merge pull request #5741 from pulumi/vl/GoVersion

Pulumi-language-go and pulumi new now checks go version is at least 1.14.0
This commit is contained in:
Vivek Lakshmanan 2020-11-12 15:40:57 -08:00 committed by GitHub
commit 9d6e380680
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 115 additions and 7 deletions

View file

@ -24,6 +24,9 @@ CHANGELOG
- Support python 3.9 on Windows.
[#5739](https://github.com/pulumi/pulumi/pull/5739)
- `pulumi-language-go` and `pulumi new` now explicitly requires Go 1.14.0.
[#5741](https://github.com/pulumi/pulumi/pull/5741)
## 2.13.2 (2020-11-06)
- Fix a bug that was causing errors when (de)serializing custom resources.

View file

@ -43,6 +43,7 @@ import (
"github.com/pulumi/pulumi/sdk/v2/go/common/util/cmdutil"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/contract"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/executable"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/goversion"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/logging"
"github.com/pulumi/pulumi/sdk/v2/go/common/workspace"
"github.com/pulumi/pulumi/sdk/v2/nodejs/npm"
@ -575,8 +576,7 @@ func installDependencies(proj *workspace.Project, root string) error {
return dotnetInstallDependenciesAndBuild(proj, root)
} else if strings.EqualFold(proj.Runtime.Name(), "go") {
if err := goInstallDependencies(); err != nil {
return errors.Wrapf(err, "`go mod download` failed to install dependencies; rerun manually to try again, "+
"then run 'pulumi up' to perform an initial deployment")
return err
}
}
@ -649,12 +649,17 @@ func goInstallDependencies() error {
return err
}
if err = goversion.CheckMinimumGoVersion(gobin); err != nil {
return err
}
cmd := exec.Command(gobin, "mod", "download")
cmd.Env = os.Environ()
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
return err
return errors.Wrapf(err, "`go mod download` failed to install dependencies; rerun manually to try again, "+
"then run 'pulumi up' to perform an initial deployment")
}
fmt.Println("Finished installing dependencies")

View file

@ -0,0 +1,45 @@
package goversion
import (
"github.com/blang/semver"
"github.com/pkg/errors"
"os/exec"
"strings"
)
var minGoVersion = semver.MustParse("1.14.0")
// CheckMinimumGoVersion checks to make sure we are running at least minGoVersion
func CheckMinimumGoVersion(gobin string) error {
cmd := exec.Command(gobin, "version")
stdout, err := cmd.Output()
if err != nil {
return errors.Wrap(err, "determining go version")
}
return checkMinimumGoVersion(string(stdout))
}
// checkMinimumGoVersion checks to make sure we are running at least go 1.14.0
// expected format of goVersionOutput: go version go<version> <os/arch>
func checkMinimumGoVersion(goVersionOutput string) error {
split := strings.Split(goVersionOutput, " ")
if len(split) <= 2 {
return errors.Errorf("unexpected format for go version output: \"%s\"", goVersionOutput)
}
version := strings.TrimSpace(split[2])
if strings.HasPrefix(version, "go") {
version = version[2:]
}
currVersion, err := semver.ParseTolerant(version)
if err != nil {
return errors.Wrap(err, "parsing go version")
}
if currVersion.LT(minGoVersion) {
return errors.Errorf("go version must be %s or higher (%s detected)", minGoVersion.String(), version)
}
return nil
}

View file

@ -0,0 +1,51 @@
package goversion
import (
"errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)
func Test_checkMinimumGoVersion(t *testing.T) {
tests := []struct {
name string
goVersionOutput string
err error
}{
{
name: "ExactVersion",
goVersionOutput: "go version go1.14.0 darwin/amd64",
},
{
name: "NewerVersion",
goVersionOutput: "go version go1.15.1 darwin/amd64",
},
{
name: "OlderGoVersion",
goVersionOutput: "go version go1.13.8 linux/amd64",
err: errors.New("go version must be 1.14.0 or higher (1.13.8 detected)"),
},
{
name: "MalformedVersion",
goVersionOutput: "go version xyz",
err: errors.New("parsing go version: Invalid character(s) found in major number \"xyz\""),
},
{
name: "GarbageVersionOutput",
goVersionOutput: "gobble gobble",
err: errors.New("unexpected format for go version output: \"gobble gobble\""),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := checkMinimumGoVersion(tt.goVersionOutput)
if err != nil {
require.Error(t, err)
assert.EqualError(t, err, tt.err.Error())
return
}
require.NoError(t, err)
})
}
}

View file

@ -35,6 +35,7 @@ import (
"github.com/pulumi/pulumi/sdk/v2/go/common/util/buildutil"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/cmdutil"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/executable"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/goversion"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/logging"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/rpcutil"
"github.com/pulumi/pulumi/sdk/v2/go/common/version"
@ -179,7 +180,8 @@ func (m *modInfo) getPlugin() (*pulumirpc.PluginDependency, error) {
// GetRequiredPlugins computes the complete set of anticipated plugins required by a program.
// We're lenient here as this relies on the `go list` command and the use of modules.
// If the consumer insists on using some other form of dependency management tool like
// dep or glide, the list command fails with "go list -m: not using modules"
// dep or glide, the list command fails with "go list -m: not using modules".
// However, we do enforce that go 1.14.0 or higher is installed.
func (host *goLanguageHost) GetRequiredPlugins(ctx context.Context,
req *pulumirpc.GetRequiredPluginsRequest) (*pulumirpc.GetRequiredPluginsResponse, error) {
@ -190,14 +192,16 @@ func (host *goLanguageHost) GetRequiredPlugins(ctx context.Context,
return nil, errors.Wrap(err, "couldn't find go binary")
}
if err = goversion.CheckMinimumGoVersion(gobin); err != nil {
return nil, err
}
// don't wire up stderr so non-module users don't see error output from list
cmd := exec.Command(gobin, "list", "-m", "-json", "-mod=mod", "all")
cmd.Env = os.Environ()
stdout, err := cmd.Output()
if err != nil {
// will err if the project isn't using modules
logging.V(5).Infof("GetRequiredPlugins: Error discovering plugin requirements: %s", err.Error())
logging.V(5).Infof("GetRequiredPlugins: Error discovering plugin requirements using go modules: %s", err.Error())
return &pulumirpc.GetRequiredPluginsResponse{}, nil
}