2017-08-05 20:37:14 +02:00
|
|
|
// Copyright 2016-2017, Pulumi Corporation. All rights reserved.
|
|
|
|
|
|
|
|
package integration
|
2017-07-13 21:19:17 +02:00
|
|
|
|
|
|
|
import (
|
2018-02-04 01:17:51 +01:00
|
|
|
"context"
|
2017-07-13 21:19:17 +02:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2017-08-06 02:49:48 +02:00
|
|
|
"io/ioutil"
|
2017-07-13 21:19:17 +02:00
|
|
|
"os"
|
2018-02-04 01:17:51 +01:00
|
|
|
"os/exec"
|
2017-11-15 06:02:47 +01:00
|
|
|
"path"
|
2017-08-06 02:49:48 +02:00
|
|
|
"path/filepath"
|
2017-12-01 02:23:58 +01:00
|
|
|
"strconv"
|
2017-07-13 21:19:17 +02:00
|
|
|
"strings"
|
|
|
|
"testing"
|
2018-02-04 01:17:51 +01:00
|
|
|
"time"
|
2017-07-13 21:19:17 +02:00
|
|
|
|
2017-10-28 05:03:38 +02:00
|
|
|
"github.com/pkg/errors"
|
2017-07-13 21:19:17 +02:00
|
|
|
"github.com/stretchr/testify/assert"
|
2017-08-06 02:49:48 +02:00
|
|
|
|
2017-11-16 16:49:07 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/engine"
|
2018-01-08 22:01:40 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/pack"
|
2017-12-14 01:09:14 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/resource"
|
|
|
|
"github.com/pulumi/pulumi/pkg/resource/deploy"
|
2017-10-16 21:04:35 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/resource/stack"
|
2017-10-28 05:03:38 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/tokens"
|
2017-09-22 04:18:21 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/contract"
|
2017-11-30 17:14:47 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/fsutil"
|
2018-02-04 01:17:51 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/retry"
|
2017-10-23 14:27:26 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/workspace"
|
2017-07-13 21:19:17 +02:00
|
|
|
)
|
|
|
|
|
2017-12-14 01:09:14 +01:00
|
|
|
// RuntimeValidationStackInfo contains details related to the stack that runtime validation logic may want to use.
|
|
|
|
type RuntimeValidationStackInfo struct {
|
|
|
|
Checkpoint stack.Checkpoint
|
|
|
|
Snapshot deploy.Snapshot
|
|
|
|
RootResource resource.State
|
|
|
|
Outputs map[string]interface{}
|
|
|
|
}
|
|
|
|
|
2017-10-27 01:01:28 +02:00
|
|
|
// EditDir is an optional edit to apply to the example, as subsequent deployments.
|
|
|
|
type EditDir struct {
|
|
|
|
Dir string
|
2017-12-14 01:09:14 +01:00
|
|
|
ExtraRuntimeValidation func(t *testing.T, stack RuntimeValidationStackInfo)
|
2017-12-15 02:10:05 +01:00
|
|
|
|
2018-01-10 01:47:17 +01:00
|
|
|
// Additive is true if Dir should be copied *on top* of the test directory.
|
|
|
|
// Otherwise Dir *replaces* the test directory, except we keep .pulumi/ and Pulumi.yaml.
|
|
|
|
Additive bool
|
|
|
|
|
2017-12-20 21:10:46 +01:00
|
|
|
// ExpectFailure is true if we expect this test to fail. This is very coarse grained, and will essentially
|
|
|
|
// tolerate *any* failure in the program (IDEA: in the future, offer a way to narrow this down more).
|
|
|
|
ExpectFailure bool
|
|
|
|
|
2017-12-15 02:10:05 +01:00
|
|
|
// Stdout is the writer to use for all stdout messages.
|
|
|
|
Stdout io.Writer
|
|
|
|
// Stderr is the writer to use for all stderr messages.
|
|
|
|
Stderr io.Writer
|
|
|
|
// Verbose may be set to true to print messages as they occur, rather than buffering and showing upon failure.
|
|
|
|
Verbose bool
|
2017-10-27 01:01:28 +02:00
|
|
|
}
|
|
|
|
|
2017-11-14 18:33:22 +01:00
|
|
|
// TestCommandStats is a collection of data related to running a single command during a test.
|
|
|
|
type TestCommandStats struct {
|
|
|
|
// StartTime is the time at which the command was started
|
|
|
|
StartTime string `json:"startTime"`
|
|
|
|
// EndTime is the time at which the command exited
|
|
|
|
EndTime string `json:"endTime"`
|
|
|
|
// ElapsedSeconds is the time at which the command exited
|
|
|
|
ElapsedSeconds float64 `json:"elapsedSeconds"`
|
|
|
|
// StackName is the name of the stack
|
|
|
|
StackName string `json:"stackName"`
|
|
|
|
// TestId is the unique ID of the test run
|
|
|
|
TestID string `json:"testId"`
|
|
|
|
// StepName is the command line which was invoked1
|
|
|
|
StepName string `json:"stepName"`
|
|
|
|
// CommandLine is the command line which was invoked1
|
|
|
|
CommandLine string `json:"commandLine"`
|
|
|
|
// TestName is the name of the directory in which the test was executed
|
|
|
|
TestName string `json:"testName"`
|
|
|
|
// IsError is true if the command failed
|
|
|
|
IsError bool `json:"isError"`
|
2018-01-30 22:10:32 +01:00
|
|
|
// The Cloud that the test was run against, or empty for local deployments
|
|
|
|
CloudURL string `json:"cloudURL"`
|
|
|
|
// The PPC that the test was run against, or empty for local deployments or for the default PPC
|
|
|
|
CloudPPC string `json:"cloudPPC"`
|
2017-11-14 18:33:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// TestStatsReporter reports results and metadata from a test run.
|
|
|
|
type TestStatsReporter interface {
|
|
|
|
ReportCommand(stats TestCommandStats)
|
|
|
|
}
|
|
|
|
|
2017-12-08 21:59:39 +01:00
|
|
|
// ProgramTestOptions provides options for ProgramTest
|
2017-10-23 03:54:29 +02:00
|
|
|
type ProgramTestOptions struct {
|
2017-08-06 02:49:48 +02:00
|
|
|
// Dir is the program directory to test.
|
|
|
|
Dir string
|
2017-09-22 04:18:21 +02:00
|
|
|
// Array of NPM packages which must be `yarn linked` (e.g. {"pulumi", "@pulumi/aws"})
|
2017-07-13 21:19:17 +02:00
|
|
|
Dependencies []string
|
2017-10-23 03:54:29 +02:00
|
|
|
// Map of config keys and values to set (e.g. {"aws:config:region": "us-east-2"})
|
2017-07-13 21:19:17 +02:00
|
|
|
Config map[string]string
|
2017-10-19 00:37:18 +02:00
|
|
|
// Map of secure config keys and values to set on the Lumi stack (e.g. {"aws:config:region": "us-east-2"})
|
|
|
|
Secrets map[string]string
|
2017-08-06 02:49:48 +02:00
|
|
|
// EditDirs is an optional list of edits to apply to the example, as subsequent deployments.
|
2017-10-27 01:01:28 +02:00
|
|
|
EditDirs []EditDir
|
2017-08-18 07:12:58 +02:00
|
|
|
// ExtraRuntimeValidation is an optional callback for additional validation, called before applying edits.
|
2017-12-14 01:09:14 +01:00
|
|
|
ExtraRuntimeValidation func(t *testing.T, stack RuntimeValidationStackInfo)
|
2017-11-15 06:02:47 +01:00
|
|
|
// RelativeWorkDir is an optional path relative to `Dir` which should be used as working directory during tests.
|
|
|
|
RelativeWorkDir string
|
2017-12-20 21:10:46 +01:00
|
|
|
// ExpectFailure is true if we expect this test to fail. This is very coarse grained, and will essentially
|
|
|
|
// tolerate *any* failure in the program (IDEA: in the future, offer a way to narrow this down more).
|
|
|
|
ExpectFailure bool
|
2017-11-16 17:15:56 +01:00
|
|
|
// Quick can be set to true to run a "quick" test that skips any non-essential steps (e.g., empty updates).
|
|
|
|
Quick bool
|
2017-12-20 20:17:25 +01:00
|
|
|
// UpdateCommandlineFlags specifies flags to add to the `pulumi update` command line (e.g. "--color=raw")
|
|
|
|
UpdateCommandlineFlags []string
|
2017-08-06 02:49:48 +02:00
|
|
|
|
2018-01-04 06:26:50 +01:00
|
|
|
// CloudURL is an optional URL to a Pulumi Service API. If set, the program test will attempt to login
|
|
|
|
// to that CloudURL (assuming PULUMI_ACCESS_TOKEN is set) and create the stack using that hosted service.
|
|
|
|
// If nil, will test Pulumi using the fire-and-forget mode.
|
|
|
|
CloudURL string
|
|
|
|
// Owner and Repo are optional values to specify during calls to `pulumi init`. Otherwise the --owner and
|
|
|
|
// --repo flags will not be set.
|
|
|
|
Owner string
|
|
|
|
Repo string
|
|
|
|
// PPCName is the name of the PPC to use when running a test against the hosted service. If
|
|
|
|
// not set, the --ppc flag will not be set on `pulumi stack init`.
|
|
|
|
PPCName string
|
|
|
|
|
2017-12-15 02:10:05 +01:00
|
|
|
// StackName allows the stack name to be explicitly provided instead of computed from the
|
|
|
|
// environment during tests.
|
|
|
|
StackName string
|
|
|
|
|
2017-11-14 18:33:22 +01:00
|
|
|
// ReportStats optionally specifies how to report results from the test for external collection.
|
|
|
|
ReportStats TestStatsReporter
|
|
|
|
|
2017-08-06 02:49:48 +02:00
|
|
|
// Stdout is the writer to use for all stdout messages.
|
|
|
|
Stdout io.Writer
|
|
|
|
// Stderr is the writer to use for all stderr messages.
|
|
|
|
Stderr io.Writer
|
2017-11-06 02:28:12 +01:00
|
|
|
// Verbose may be set to true to print messages as they occur, rather than buffering and showing upon failure.
|
|
|
|
Verbose bool
|
2017-08-06 02:49:48 +02:00
|
|
|
|
2017-12-01 02:23:58 +01:00
|
|
|
// DebugLogging may be set to anything >0 to enable excessively verbose debug logging from `pulumi`. This is
|
|
|
|
// equivalent to `--logtostderr -v=N`, where N is the value of DebugLogLevel. This may also be enabled by setting
|
|
|
|
// the environment variable PULUMI_TEST_DEBUG_LOG_LEVEL.
|
|
|
|
DebugLogLevel int
|
2017-11-28 20:03:34 +01:00
|
|
|
// DebugUpdates may be set to true to enable debug logging from `pulumi preview`, `pulumi update`, and
|
2017-12-01 02:23:58 +01:00
|
|
|
// `pulumi destroy`. This may also be enabled by setting the environment variable PULUMI_TEST_DEBUG_UPDATES.
|
2017-11-25 00:21:43 +01:00
|
|
|
DebugUpdates bool
|
|
|
|
|
2017-10-23 03:54:29 +02:00
|
|
|
// Bin is a location of a `pulumi` executable to be run. Taken from the $PATH if missing.
|
|
|
|
Bin string
|
2017-08-06 02:49:48 +02:00
|
|
|
// YarnBin is a location of a `yarn` executable to be run. Taken from the $PATH if missing.
|
|
|
|
YarnBin string
|
|
|
|
}
|
|
|
|
|
2017-12-09 01:59:28 +01:00
|
|
|
func (opts *ProgramTestOptions) GetDebugLogLevel() int {
|
2017-12-01 02:23:58 +01:00
|
|
|
if opts.DebugLogLevel > 0 {
|
|
|
|
return opts.DebugLogLevel
|
|
|
|
}
|
|
|
|
if du := os.Getenv("PULUMI_TEST_DEBUG_LOG_LEVEL"); du != "" {
|
2017-12-01 03:55:18 +01:00
|
|
|
if n, _ := strconv.Atoi(du); n > 0 { // nolint: gas
|
2017-12-01 02:23:58 +01:00
|
|
|
return n
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2017-12-09 01:59:28 +01:00
|
|
|
func (opts *ProgramTestOptions) GetDebugUpdates() bool {
|
2017-12-01 02:23:58 +01:00
|
|
|
return opts.DebugUpdates || os.Getenv("PULUMI_TEST_DEBUG_UPDATES") != ""
|
|
|
|
}
|
|
|
|
|
2017-12-15 02:10:05 +01:00
|
|
|
// GetStackName returns a stack name to use for this test.
|
|
|
|
func (opts *ProgramTestOptions) GetStackName() tokens.QName {
|
|
|
|
if opts.StackName == "" {
|
|
|
|
// Fetch the host and test dir names, cleaned so to contain just [a-zA-Z0-9-_] chars.
|
|
|
|
hostname, err := os.Hostname()
|
|
|
|
contract.AssertNoErrorf(err, "failure to fetch hostname for stack prefix")
|
|
|
|
var host string
|
|
|
|
for _, c := range hostname {
|
|
|
|
if len(host) >= 10 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
|
|
|
(c >= '0' && c <= '9') || c == '-' || c == '_' {
|
|
|
|
host += string(c)
|
|
|
|
}
|
2017-11-06 16:23:07 +01:00
|
|
|
}
|
2017-11-16 16:49:07 +01:00
|
|
|
|
2017-12-15 02:10:05 +01:00
|
|
|
var test string
|
|
|
|
for _, c := range filepath.Base(opts.Dir) {
|
|
|
|
if len(test) >= 10 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
|
|
|
(c >= '0' && c <= '9') || c == '-' || c == '_' {
|
|
|
|
test += string(c)
|
|
|
|
}
|
2017-11-06 16:23:07 +01:00
|
|
|
}
|
2017-12-15 02:10:05 +01:00
|
|
|
|
|
|
|
opts.StackName = strings.ToLower("p-it-" + host + "-" + test)
|
2017-11-06 16:23:07 +01:00
|
|
|
}
|
2017-11-16 16:49:07 +01:00
|
|
|
|
2017-12-15 02:10:05 +01:00
|
|
|
return tokens.QName(opts.StackName)
|
2017-11-06 16:23:07 +01:00
|
|
|
}
|
|
|
|
|
2017-08-06 02:49:48 +02:00
|
|
|
// With combines a source set of options with a set of overrides.
|
2017-10-23 03:54:29 +02:00
|
|
|
func (opts ProgramTestOptions) With(overrides ProgramTestOptions) ProgramTestOptions {
|
2017-08-06 02:49:48 +02:00
|
|
|
if overrides.Dir != "" {
|
|
|
|
opts.Dir = overrides.Dir
|
|
|
|
}
|
|
|
|
if overrides.Dependencies != nil {
|
|
|
|
opts.Dependencies = overrides.Dependencies
|
|
|
|
}
|
|
|
|
for k, v := range overrides.Config {
|
|
|
|
if opts.Config == nil {
|
|
|
|
opts.Config = make(map[string]string)
|
|
|
|
}
|
|
|
|
opts.Config[k] = v
|
|
|
|
}
|
2017-11-14 18:33:22 +01:00
|
|
|
for k, v := range overrides.Secrets {
|
|
|
|
if opts.Secrets == nil {
|
|
|
|
opts.Secrets = make(map[string]string)
|
|
|
|
}
|
|
|
|
opts.Secrets[k] = v
|
|
|
|
}
|
2018-01-04 06:26:50 +01:00
|
|
|
if overrides.CloudURL != "" {
|
|
|
|
opts.CloudURL = overrides.CloudURL
|
|
|
|
}
|
|
|
|
if overrides.Owner != "" {
|
|
|
|
opts.Owner = overrides.Owner
|
|
|
|
}
|
|
|
|
if overrides.Repo != "" {
|
|
|
|
opts.Repo = overrides.Repo
|
|
|
|
}
|
|
|
|
if overrides.PPCName != "" {
|
|
|
|
opts.PPCName = overrides.PPCName
|
|
|
|
}
|
2017-08-06 02:49:48 +02:00
|
|
|
if overrides.EditDirs != nil {
|
|
|
|
opts.EditDirs = overrides.EditDirs
|
|
|
|
}
|
2017-11-14 18:33:22 +01:00
|
|
|
if overrides.ExtraRuntimeValidation != nil {
|
|
|
|
opts.ExtraRuntimeValidation = overrides.ExtraRuntimeValidation
|
|
|
|
}
|
2017-11-15 06:02:47 +01:00
|
|
|
if overrides.RelativeWorkDir != "" {
|
|
|
|
opts.RelativeWorkDir = overrides.RelativeWorkDir
|
|
|
|
}
|
2017-11-14 18:33:22 +01:00
|
|
|
if overrides.ReportStats != nil {
|
|
|
|
opts.ReportStats = overrides.ReportStats
|
|
|
|
}
|
2017-08-06 02:49:48 +02:00
|
|
|
return opts
|
2017-07-13 21:19:17 +02:00
|
|
|
}
|
|
|
|
|
2017-12-08 21:59:39 +01:00
|
|
|
// ProgramTest runs a lifecycle of Pulumi commands in a program working directory, using the `pulumi` and `yarn`
|
|
|
|
// binaries available on PATH. It essentially executes the following workflow:
|
2017-10-23 14:27:26 +02:00
|
|
|
//
|
2017-12-08 21:59:39 +01:00
|
|
|
// yarn install
|
|
|
|
// yarn link <each opts.Depencies>
|
|
|
|
// yarn run build
|
|
|
|
// pulumi init
|
2018-01-04 06:26:50 +01:00
|
|
|
// (*) pulumi login
|
2017-12-08 21:59:39 +01:00
|
|
|
// pulumi stack init integrationtesting
|
|
|
|
// pulumi config set <each opts.Config>
|
|
|
|
// pulumi config set --secret <each opts.Secrets>
|
|
|
|
// pulumi preview
|
|
|
|
// pulumi update
|
|
|
|
// pulumi preview (expected to be empty)
|
|
|
|
// pulumi update (expected to be empty)
|
|
|
|
// pulumi destroy --yes
|
|
|
|
// pulumi stack rm --yes integrationtesting
|
2018-01-04 06:26:50 +01:00
|
|
|
// (*) pulumi logout
|
|
|
|
//
|
|
|
|
// (*) Only if ProgramTestOptions.CloudURL is not empty.
|
2017-10-23 14:27:26 +02:00
|
|
|
//
|
2017-12-20 21:10:46 +01:00
|
|
|
// All commands must return success return codes for the test to succeed, unless ExpectFailure is true.
|
2017-12-09 01:59:28 +01:00
|
|
|
func ProgramTest(t *testing.T, opts *ProgramTestOptions) {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
t.Parallel()
|
|
|
|
|
2018-01-20 08:07:38 +01:00
|
|
|
// If the test panics, recover and log instead of letting the panic escape the test. Even though *this* test will
|
|
|
|
// have run deferred functions and cleaned up, if the panic reaches toplevel it will kill the process and prevent
|
|
|
|
// other tests running in parallel from cleaning up.
|
|
|
|
defer func() {
|
|
|
|
if failure := recover(); failure != nil {
|
|
|
|
t.Errorf("panic testing %v: %v", opts.Dir, failure)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
pt := newProgramTester(t, opts)
|
|
|
|
err := pt.testLifeCycleInitAndDestroy()
|
2017-12-20 21:10:46 +01:00
|
|
|
assert.NoError(t, err)
|
2017-12-11 23:42:42 +01:00
|
|
|
}
|
|
|
|
|
2018-01-17 02:32:49 +01:00
|
|
|
// fprintf works like fmt.FPrintf, except it explicitly drops the return values. This keeps the linters happy, since
|
|
|
|
// they don't like to see errors dropped on the floor. It is possible that our call to fmt.Fprintf will fail, even
|
|
|
|
// for "standard" streams like `stdout` and `stderr`, if they have been set to non-blocking by an external process.
|
|
|
|
// In that case, we just drop the error on the floor and continue. We see this behavior in Travis when we try to write
|
|
|
|
// a lot of messages quickly (as we do when logging test failures)
|
|
|
|
func fprintf(w io.Writer, format string, a ...interface{}) {
|
|
|
|
_, err := fmt.Fprintf(w, format, a...)
|
|
|
|
contract.IgnoreError(err)
|
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
// programTester contains state associated with running a single test pass.
|
|
|
|
type programTester struct {
|
|
|
|
t *testing.T // the Go tester for this run.
|
|
|
|
opts *ProgramTestOptions // options that control this test run.
|
|
|
|
bin string // the `pulumi` binary we are using.
|
|
|
|
yarnBin string // the `yarn` binary we are using.
|
2018-01-06 02:40:41 +01:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func newProgramTester(t *testing.T, opts *ProgramTestOptions) *programTester {
|
|
|
|
return &programTester{t: t, opts: opts}
|
|
|
|
}
|
2017-12-11 23:42:42 +01:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) getBin() (string, error) {
|
|
|
|
return getCmdBin(&pt.bin, "pulumi", pt.opts.Bin)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pt *programTester) getYarnBin() (string, error) {
|
|
|
|
return getCmdBin(&pt.yarnBin, "yarn", pt.opts.YarnBin)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pt *programTester) pulumiCmd(args []string) ([]string, error) {
|
|
|
|
bin, err := pt.getBin()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
cmd := []string{bin}
|
|
|
|
if du := pt.opts.GetDebugLogLevel(); du > 0 {
|
|
|
|
cmd = append(cmd, "--logtostderr")
|
|
|
|
cmd = append(cmd, "-v="+strconv.Itoa(du))
|
|
|
|
}
|
|
|
|
return append(cmd, args...), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pt *programTester) yarnCmd(args []string) ([]string, error) {
|
|
|
|
bin, err := pt.getYarnBin()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
result := []string{bin}
|
|
|
|
result = append(result, args...)
|
|
|
|
return withOptionalYarnFlags(result), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pt *programTester) runCommand(name string, args []string, wd string) error {
|
|
|
|
return RunCommand(pt.t, name, args, wd, pt.opts)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pt *programTester) runPulumiCommand(name string, args []string, wd string) error {
|
|
|
|
cmd, err := pt.pulumiCmd(args)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return pt.runCommand(name, cmd, wd)
|
|
|
|
}
|
2017-08-06 02:49:48 +02:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) runYarnCommand(name string, args []string, wd string) error {
|
|
|
|
cmd, err := pt.yarnCmd(args)
|
2018-01-06 01:39:13 +01:00
|
|
|
if err != nil {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
return err
|
|
|
|
}
|
2018-02-04 01:17:51 +01:00
|
|
|
|
|
|
|
_, _, err = retry.Until(context.Background(), retry.Acceptor{
|
|
|
|
Accept: func(try int, nextRetryTime time.Duration) (bool, interface{}, error) {
|
|
|
|
runerr := pt.runCommand(name, cmd, wd)
|
|
|
|
if runerr == nil {
|
|
|
|
return true, nil, nil
|
|
|
|
} else if _, ok := runerr.(*exec.ExitError); ok {
|
|
|
|
// yarn failed, let's try again, assuming we haven't failed a few times.
|
|
|
|
if try > 3 {
|
|
|
|
return false, nil, errors.Errorf("%v did not complete after %v tries", cmd, try)
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// someother error, fail
|
|
|
|
return false, nil, runerr
|
|
|
|
},
|
|
|
|
})
|
|
|
|
return err
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (pt *programTester) testLifeCycleInitAndDestroy() error {
|
|
|
|
dir, err := pt.copyTestToTemporaryDirectory()
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "copying test to temp dir")
|
2018-01-06 01:39:13 +01:00
|
|
|
}
|
|
|
|
|
2018-01-10 08:25:49 +01:00
|
|
|
// Keep the temporary test directory around for debugging unless
|
|
|
|
// the test completes successfully.
|
|
|
|
keepTestDir := true
|
2018-01-06 01:39:13 +01:00
|
|
|
defer func() {
|
2018-01-10 08:25:49 +01:00
|
|
|
if keepTestDir {
|
|
|
|
// Maybe copy to "failed tests" directory.
|
2018-01-07 06:05:42 +01:00
|
|
|
failedTestsDir := os.Getenv("PULUMI_FAILED_TESTS_DIR")
|
|
|
|
if failedTestsDir != "" {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
dest := filepath.Join(failedTestsDir, pt.t.Name()+uniqueSuffix())
|
2018-01-07 06:05:42 +01:00
|
|
|
contract.IgnoreError(fsutil.CopyFile(dest, dir, nil))
|
|
|
|
}
|
2018-01-06 01:39:13 +01:00
|
|
|
} else {
|
|
|
|
contract.IgnoreError(os.RemoveAll(dir))
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
err = pt.testLifeCycleInitialize(dir)
|
2017-12-09 01:59:28 +01:00
|
|
|
if err != nil {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
return errors.Wrap(err, "initializing test project")
|
2017-12-09 01:59:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that before we exit, we attempt to destroy and remove the stack.
|
|
|
|
defer func() {
|
2017-12-22 15:57:37 +01:00
|
|
|
if dir != "" {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
destroyErr := pt.testLifeCycleDestroy(dir)
|
|
|
|
assert.NoError(pt.t, destroyErr)
|
2017-12-22 15:57:37 +01:00
|
|
|
}
|
2017-12-09 01:59:28 +01:00
|
|
|
}()
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err = pt.testPreviewUpdateAndEdits(dir); err != nil {
|
|
|
|
return errors.Wrap(err, "running test preview, update, and edits")
|
2018-01-10 08:25:49 +01:00
|
|
|
}
|
|
|
|
|
2018-02-02 08:35:49 +01:00
|
|
|
// Ran to completion. Delete the test directory if the test passed.
|
|
|
|
keepTestDir = pt.t.Failed()
|
|
|
|
|
2018-01-10 08:25:49 +01:00
|
|
|
return nil
|
2017-12-09 01:59:28 +01:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) testLifeCycleInitialize(dir string) error {
|
|
|
|
stackName := pt.opts.GetStackName()
|
2017-12-09 01:59:28 +01:00
|
|
|
|
2017-11-15 06:02:47 +01:00
|
|
|
// If RelativeWorkDir is specified, apply that relative to the temp folder for use as working directory during tests.
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if pt.opts.RelativeWorkDir != "" {
|
|
|
|
dir = path.Join(dir, pt.opts.RelativeWorkDir)
|
2017-11-15 06:02:47 +01:00
|
|
|
}
|
|
|
|
|
2017-10-16 21:04:35 +02:00
|
|
|
// Ensure all links are present, the stack is created, and all configs are applied.
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(pt.opts.Stdout, "Initializing project (dir %s; stack %s)\n", dir, stackName)
|
2018-01-04 06:26:50 +01:00
|
|
|
|
|
|
|
initArgs := []string{"init"}
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
initArgs = addFlagIfNonNil(initArgs, "--owner", pt.opts.Owner)
|
|
|
|
initArgs = addFlagIfNonNil(initArgs, "--name", pt.opts.Repo)
|
|
|
|
if err := pt.runPulumiCommand("pulumi-init", initArgs, dir); err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-11-06 18:04:38 +01:00
|
|
|
}
|
2017-12-09 01:59:28 +01:00
|
|
|
|
2018-01-04 06:26:50 +01:00
|
|
|
// Login as needed.
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if pt.opts.CloudURL != "" {
|
2018-01-04 06:26:50 +01:00
|
|
|
if os.Getenv("PULUMI_ACCESS_TOKEN") == "" {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
pt.t.Fatalf("Unable to run pulumi login. PULUMI_ACCESS_TOKEN environment variable not set.")
|
2018-01-04 06:26:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set the "use alt location" flag so this test doesn't interact with any credentials already on the machine.
|
|
|
|
// e.g. replacing the current user's with that of a test account.
|
2018-01-06 01:39:13 +01:00
|
|
|
if err := os.Setenv(workspace.UseAltCredentialsLocationEnvVar, "1"); err != nil {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
pt.t.Fatalf("error setting env var '%s': %v", workspace.UseAltCredentialsLocationEnvVar, err)
|
2018-01-04 06:26:50 +01:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err := pt.runPulumiCommand("pulumi-login",
|
|
|
|
append([]string{"login", "--cloud-url", pt.opts.CloudURL}), dir); err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2018-01-04 06:26:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stack init
|
|
|
|
stackInitArgs := []string{"stack", "init", string(stackName)}
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if pt.opts.CloudURL == "" {
|
2018-01-04 06:26:50 +01:00
|
|
|
stackInitArgs = append(stackInitArgs, "--local")
|
|
|
|
} else {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
stackInitArgs = addFlagIfNonNil(stackInitArgs, "--cloud-url", pt.opts.CloudURL)
|
|
|
|
stackInitArgs = addFlagIfNonNil(stackInitArgs, "--ppc", pt.opts.PPCName)
|
2018-01-04 06:26:50 +01:00
|
|
|
}
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err := pt.runPulumiCommand("pulumi-stack-init", stackInitArgs, dir); err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-11-06 18:04:38 +01:00
|
|
|
}
|
2017-12-09 01:59:28 +01:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
for key, value := range pt.opts.Config {
|
|
|
|
if err := pt.runPulumiCommand("pulumi-config",
|
|
|
|
[]string{"config", "set", key, value}, dir); err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-11-06 18:04:38 +01:00
|
|
|
}
|
2017-10-19 00:37:18 +02:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
for key, value := range pt.opts.Secrets {
|
|
|
|
if err := pt.runPulumiCommand("pulumi-config",
|
|
|
|
[]string{"config", "set", "--secret", key, value}, dir); err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-11-06 18:04:38 +01:00
|
|
|
}
|
2017-08-06 02:49:48 +02:00
|
|
|
}
|
|
|
|
|
2018-01-06 01:39:13 +01:00
|
|
|
return nil
|
2017-12-09 01:59:28 +01:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) testLifeCycleDestroy(dir string) error {
|
|
|
|
stackName := pt.opts.GetStackName()
|
2017-12-09 01:59:28 +01:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
// Destroy and remove the stack.
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(pt.opts.Stdout, "Destroying stack\n")
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
destroy := []string{"destroy", "--yes"}
|
|
|
|
if pt.opts.GetDebugUpdates() {
|
2017-11-25 00:21:43 +01:00
|
|
|
destroy = append(destroy, "-d")
|
|
|
|
}
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err := pt.runPulumiCommand("pulumi-destroy", destroy, dir); err != nil {
|
2017-12-20 21:10:46 +01:00
|
|
|
return err
|
|
|
|
}
|
2018-01-04 06:26:50 +01:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err := pt.runPulumiCommand("pulumi-stack-rm",
|
|
|
|
[]string{"stack", "rm", "--yes", string(stackName)}, dir); err != nil {
|
2018-01-04 06:26:50 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if pt.opts.CloudURL != "" {
|
|
|
|
return pt.runPulumiCommand("pulumi-logout",
|
|
|
|
[]string{"logout", "--cloud-url", pt.opts.CloudURL}, dir)
|
2018-01-04 06:26:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2017-12-09 01:59:28 +01:00
|
|
|
}
|
2017-12-08 21:59:39 +01:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) testPreviewUpdateAndEdits(dir string) error {
|
2017-12-11 23:42:42 +01:00
|
|
|
// Now preview and update the real changes.
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(pt.opts.Stdout, "Performing primary preview and update\n")
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
initErr := pt.previewAndUpdate(dir, "initial", pt.opts.ExpectFailure)
|
2017-12-11 23:42:42 +01:00
|
|
|
|
|
|
|
// If the initial preview/update failed, just exit without trying the rest (but make sure to destroy).
|
|
|
|
if initErr != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return initErr
|
2017-12-11 23:42:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Perform an empty preview and update; nothing is expected to happen here.
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if !pt.opts.Quick {
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(pt.opts.Stdout, "Performing empty preview and update (no changes expected)\n")
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err := pt.previewAndUpdate(dir, "empty", false); err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-12-11 23:42:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run additional validation provided by the test options, passing in the checkpoint info.
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err := pt.performExtraRuntimeValidation(pt.opts.ExtraRuntimeValidation, dir); err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-12-11 23:42:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// If there are any edits, apply them and run a preview and update for each one.
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
return pt.testEdits(dir)
|
2017-12-11 23:42:42 +01:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) previewAndUpdate(dir string, name string, shouldFail bool) error {
|
|
|
|
preview := []string{"preview"}
|
|
|
|
update := []string{"update"}
|
|
|
|
if pt.opts.GetDebugUpdates() {
|
2017-12-09 01:59:28 +01:00
|
|
|
preview = append(preview, "-d")
|
|
|
|
update = append(update, "-d")
|
2017-08-06 02:49:48 +02:00
|
|
|
}
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if pt.opts.UpdateCommandlineFlags != nil {
|
|
|
|
update = append(update, pt.opts.UpdateCommandlineFlags...)
|
2017-12-20 20:17:25 +01:00
|
|
|
}
|
2017-08-06 02:49:48 +02:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if !pt.opts.Quick {
|
|
|
|
if err := pt.runPulumiCommand("pulumi-preview-"+name, preview, dir); err != nil {
|
2017-12-20 21:10:46 +01:00
|
|
|
if shouldFail {
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(pt.opts.Stdout, "Permitting failure (ExpectFailure=true for this preview)\n")
|
2017-12-20 21:10:46 +01:00
|
|
|
return nil
|
|
|
|
}
|
2017-12-09 01:59:28 +01:00
|
|
|
return err
|
2017-11-16 17:15:56 +01:00
|
|
|
}
|
2017-11-06 18:04:38 +01:00
|
|
|
}
|
2017-08-06 02:49:48 +02:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err := pt.runPulumiCommand("pulumi-update-"+name, update, dir); err != nil {
|
2017-12-20 21:10:46 +01:00
|
|
|
if shouldFail {
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(pt.opts.Stdout, "Permitting failure (ExpectFailure=true for this update)\n")
|
2017-12-20 21:10:46 +01:00
|
|
|
return nil
|
|
|
|
}
|
2017-12-09 01:59:28 +01:00
|
|
|
return err
|
2017-12-08 01:29:48 +01:00
|
|
|
}
|
|
|
|
|
2017-12-20 21:10:46 +01:00
|
|
|
// If we expected a failure, but none occurred, return an error.
|
|
|
|
if shouldFail {
|
|
|
|
return errors.New("expected this step to fail, but it succeeded")
|
|
|
|
}
|
|
|
|
|
2017-12-09 01:59:28 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) testEdits(dir string) error {
|
|
|
|
for i, edit := range pt.opts.EditDirs {
|
2017-12-21 20:01:30 +01:00
|
|
|
var err error
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err = pt.testEdit(dir, i, edit); err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-12-20 21:10:46 +01:00
|
|
|
}
|
2017-12-12 00:48:45 +01:00
|
|
|
}
|
2018-01-06 01:39:13 +01:00
|
|
|
return nil
|
2017-12-12 00:48:45 +01:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) testEdit(dir string, i int, edit EditDir) error {
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(pt.opts.Stdout, "Applying edit '%v' and rerunning preview and update\n", edit.Dir)
|
2017-12-12 00:48:45 +01:00
|
|
|
|
2018-01-10 01:47:17 +01:00
|
|
|
if edit.Additive {
|
|
|
|
// Just copy new files into dir
|
|
|
|
if err := fsutil.CopyFile(dir, edit.Dir, nil); err != nil {
|
|
|
|
return errors.Wrapf(err, "Couldn't copy %v into %v", edit.Dir, dir)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Create a new temporary directory
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
newDir, err := ioutil.TempDir("", pt.opts.StackName+"-")
|
2018-01-10 01:47:17 +01:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "Couldn't create new temporary directory")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete whichever copy of the test is unused when we return
|
|
|
|
dirToDelete := newDir
|
|
|
|
defer func() {
|
|
|
|
contract.IgnoreError(os.RemoveAll(dirToDelete))
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Copy everything except Pulumi.yaml and .pulumi from source into new directory
|
|
|
|
exclusions := make(map[string]bool)
|
|
|
|
projectYaml := workspace.ProjectFile + ".yaml"
|
|
|
|
exclusions[workspace.BookkeepingDir] = true
|
|
|
|
exclusions[projectYaml] = true
|
|
|
|
|
|
|
|
if err := fsutil.CopyFile(newDir, edit.Dir, exclusions); err != nil {
|
|
|
|
return errors.Wrapf(err, "Couldn't copy %v into %v", edit.Dir, newDir)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy Pulumi.yaml and .pulumi from old directory to new directory
|
|
|
|
oldProjectYaml := filepath.Join(dir, projectYaml)
|
|
|
|
newProjectYaml := filepath.Join(newDir, projectYaml)
|
|
|
|
|
|
|
|
oldProjectDir := filepath.Join(dir, workspace.BookkeepingDir)
|
|
|
|
newProjectDir := filepath.Join(newDir, workspace.BookkeepingDir)
|
|
|
|
|
|
|
|
if err := fsutil.CopyFile(newProjectYaml, oldProjectYaml, nil); err != nil {
|
|
|
|
return errors.Wrapf(err, "Couldn't copy Pulumi.yaml")
|
|
|
|
}
|
|
|
|
if err := fsutil.CopyFile(newProjectDir, oldProjectDir, nil); err != nil {
|
|
|
|
return errors.Wrapf(err, "Couldn't copy .pulumi")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, replace our current temp directory with the new one.
|
|
|
|
dirOld := dir + ".old"
|
|
|
|
if err := os.Rename(dir, dirOld); err != nil {
|
|
|
|
return errors.Wrapf(err, "Couldn't rename %v to %v", dir, dirOld)
|
|
|
|
}
|
|
|
|
|
|
|
|
// There's a brief window here where the old temp dir name could be taken from us.
|
|
|
|
|
|
|
|
if err := os.Rename(newDir, dir); err != nil {
|
|
|
|
return errors.Wrapf(err, "Couldn't rename %v to %v", newDir, dir)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keep dir, delete oldDir
|
|
|
|
dirToDelete = dirOld
|
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
err := pt.prepareProject(dir)
|
2017-12-20 21:10:46 +01:00
|
|
|
if err != nil {
|
2018-01-10 01:47:17 +01:00
|
|
|
return errors.Wrapf(err, "Couldn't prepare project in %v", dir)
|
2017-12-12 00:48:45 +01:00
|
|
|
}
|
2017-12-15 02:10:05 +01:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
oldStdOut := pt.opts.Stdout
|
|
|
|
oldStderr := pt.opts.Stderr
|
|
|
|
oldVerbose := pt.opts.Verbose
|
2017-12-15 02:10:05 +01:00
|
|
|
if edit.Stdout != nil {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
pt.opts.Stdout = edit.Stdout
|
2017-12-15 02:10:05 +01:00
|
|
|
}
|
|
|
|
if edit.Stderr != nil {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
pt.opts.Stderr = edit.Stderr
|
2017-12-15 02:10:05 +01:00
|
|
|
}
|
|
|
|
if edit.Verbose {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
pt.opts.Verbose = true
|
2017-12-15 02:10:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
defer func() {
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
pt.opts.Stdout = oldStdOut
|
|
|
|
pt.opts.Stderr = oldStderr
|
|
|
|
pt.opts.Verbose = oldVerbose
|
2017-12-15 02:10:05 +01:00
|
|
|
}()
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if err = pt.previewAndUpdate(dir, fmt.Sprintf("edit-%d", i), edit.ExpectFailure); err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-12-12 00:48:45 +01:00
|
|
|
}
|
2018-01-25 03:22:41 +01:00
|
|
|
return pt.performExtraRuntimeValidation(edit.ExtraRuntimeValidation, dir)
|
2017-09-25 23:03:16 +02:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) performExtraRuntimeValidation(
|
2017-12-14 01:09:14 +01:00
|
|
|
extraRuntimeValidation func(t *testing.T, stack RuntimeValidationStackInfo), dir string) error {
|
2017-12-09 01:59:28 +01:00
|
|
|
|
|
|
|
if extraRuntimeValidation == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
stackName := pt.opts.GetStackName()
|
2017-12-09 01:59:28 +01:00
|
|
|
|
2017-10-28 04:42:17 +02:00
|
|
|
// Load up the checkpoint file from .pulumi/stacks/<project-name>/<stack-name>.json.
|
Improve the overall cloud CLI experience
This improves the overall cloud CLI experience workflow.
Now whether a stack is local or cloud is inherent to the stack
itself. If you interact with a cloud stack, we transparently talk
to the cloud; if you interact with a local stack, we just do the
right thing, and perform all operations locally. Aside from sometimes
seeing a cloud emoji pop-up ☁️, the experience is quite similar.
For example, to initialize a new cloud stack, simply:
$ pulumi login
Logging into Pulumi Cloud: https://pulumi.com/
Enter Pulumi access token: <enter your token>
$ pulumi stack init my-cloud-stack
Note that you may log into a specific cloud if you'd like. For
now, this is just for our own testing purposes, but someday when we
support custom clouds (e.g., Enterprise), you can just say:
$ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873
The cloud is now the default. If you instead prefer a "fire and
forget" style of stack, you can skip the login and pass `--local`:
$ pulumi stack init my-faf-stack --local
If you are logged in and run `pulumi`, we tell you as much:
$ pulumi
Usage:
pulumi [command]
// as before...
Currently logged into the Pulumi Cloud ☁️
https://pulumi.com/
And if you list your stacks, we tell you which one is local or not:
$ pulumi stack ls
NAME LAST UPDATE RESOURCE COUNT CLOUD URL
my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/
my-faf-stack n/a 0 n/a
And `pulumi stack` by itself prints information like your cloud org,
PPC name, and so on, in addition to the usuals.
I shall write up more details and make sure to document these changes.
This change also fairly significantly refactors the layout of cloud
versus local logic, so that the cmd/ package is resonsible for CLI
things, and the new pkg/backend/ package is responsible for the
backends. The following is the overall resulting package architecture:
* The backend.Backend interface can be implemented to substitute
a new backend. This has operations to get and list stacks,
perform updates, and so on.
* The backend.Stack struct is a wrapper around a stack that has
or is being manipulated by a Backend. It resembles our existing
Stack notions in the engine, but carries additional metadata
about its source. Notably, it offers functions that allow
operations like updating and deleting on the Backend from which
it came.
* There is very little else in the pkg/backend/ package.
* A new package, pkg/backend/local/, encapsulates all local state
management for "fire and forget" scenarios. It simply implements
the above logic and contains anything specific to the local
experience.
* A peer package, pkg/backend/cloud/, encapsulates all logic
required for the cloud experience. This includes its subpackage
apitype/ which contains JSON schema descriptions required for
REST calls against the cloud backend. It also contains handy
functions to list which clouds we have authenticated with.
* A subpackage here, pkg/backend/state/, is not a provider at all.
Instead, it contains all of the state management functions that
are currently shared between local and cloud backends. This
includes configuration logic -- including encryption -- as well
as logic pertaining to which stacks are known to the workspace.
This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 16:29:46 +01:00
|
|
|
ws, err := workspace.NewFrom(dir)
|
2017-12-20 21:10:46 +01:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "expected to load project workspace at %v", dir)
|
2017-10-27 01:01:28 +02:00
|
|
|
}
|
2017-11-06 16:23:07 +01:00
|
|
|
chk, err := stack.GetCheckpoint(ws, stackName)
|
2017-12-20 21:10:46 +01:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "expected to load checkpoint file for target %v: %v", stackName)
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
} else if !assert.NotNil(pt.t, chk, "expected checkpoint file to be populated from %v: %v", stackName, err) {
|
2017-10-28 05:03:38 +02:00
|
|
|
return errors.New("missing checkpoint")
|
2017-10-27 01:01:28 +02:00
|
|
|
}
|
2017-12-14 01:09:14 +01:00
|
|
|
|
|
|
|
// Deserialize snapshot from checkpoint
|
|
|
|
snapshot, err := stack.DeserializeCheckpoint(chk)
|
2017-12-20 21:10:46 +01:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "expected checkpoint deserialization to succeed")
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
} else if !assert.NotNil(pt.t, snapshot, "expected snapshot to be populated from checkpoint file %v", stackName) {
|
2017-12-14 01:09:14 +01:00
|
|
|
return errors.New("missing snapshot")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get root resources from snapshot
|
|
|
|
rootResource, outputs := stack.GetRootStackResource(snapshot)
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if !assert.NotNil(pt.t, rootResource, "expected root resource to be populated from snapshot file %v", stackName) {
|
2017-12-14 01:09:14 +01:00
|
|
|
return errors.New("missing root resource")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Populate stack info object with all of this data to pass to the validation function
|
|
|
|
stackInfo := RuntimeValidationStackInfo{
|
|
|
|
Checkpoint: *chk,
|
|
|
|
Snapshot: *snapshot,
|
|
|
|
RootResource: *rootResource,
|
|
|
|
Outputs: outputs,
|
|
|
|
}
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
extraRuntimeValidation(pt.t, stackInfo)
|
2017-10-27 01:01:28 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
// copyTestToTemporaryDirectory creates a temporary directory to run the test in and copies the test to it.
|
|
|
|
func (pt *programTester) copyTestToTemporaryDirectory() (dir string, err error) {
|
2017-09-25 23:03:16 +02:00
|
|
|
// Set up a prefix so that all output has the test directory name in it. This is important for debugging
|
|
|
|
// because we run tests in parallel, and so all output will be interleaved and difficult to follow otherwise.
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
sourceDir := pt.opts.Dir
|
2017-11-16 16:49:07 +01:00
|
|
|
var prefix string
|
2018-01-10 01:45:40 +01:00
|
|
|
if len(sourceDir) <= 30 {
|
2018-01-06 01:39:13 +01:00
|
|
|
prefix = fmt.Sprintf("[ %30.30s ] ", sourceDir)
|
2017-11-16 16:49:07 +01:00
|
|
|
} else {
|
2018-01-06 01:39:13 +01:00
|
|
|
prefix = fmt.Sprintf("[ %30.30s ] ", sourceDir[len(sourceDir)-30:])
|
2017-11-16 16:49:07 +01:00
|
|
|
}
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
stdout := pt.opts.Stdout
|
2017-09-25 23:03:16 +02:00
|
|
|
if stdout == nil {
|
|
|
|
stdout = newPrefixer(os.Stdout, prefix)
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
pt.opts.Stdout = stdout
|
2017-09-25 23:03:16 +02:00
|
|
|
}
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
stderr := pt.opts.Stderr
|
2017-09-25 23:03:16 +02:00
|
|
|
if stderr == nil {
|
|
|
|
stderr = newPrefixer(os.Stderr, prefix)
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
pt.opts.Stderr = stderr
|
2017-09-25 23:03:16 +02:00
|
|
|
}
|
|
|
|
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(pt.opts.Stdout, "sample: %v\n", sourceDir)
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
bin, err := pt.getBin()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(pt.opts.Stdout, "pulumi: %v\n", bin)
|
2017-09-25 23:03:16 +02:00
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
stackName := string(pt.opts.GetStackName())
|
2018-01-06 01:39:13 +01:00
|
|
|
targetDir, err := ioutil.TempDir("", stackName+"-")
|
|
|
|
if err != nil {
|
|
|
|
return "", errors.Wrap(err, "Couldn't create temporary directory")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up the temporary directory on failure
|
2018-01-10 08:22:35 +01:00
|
|
|
deleteTargetDir := true
|
2018-01-06 01:39:13 +01:00
|
|
|
defer func() {
|
2018-01-10 08:22:35 +01:00
|
|
|
if deleteTargetDir {
|
2018-01-06 01:39:13 +01:00
|
|
|
contract.IgnoreError(os.RemoveAll(targetDir))
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2018-01-10 01:47:17 +01:00
|
|
|
// Copy the source project
|
2018-01-10 08:22:35 +01:00
|
|
|
if err = fsutil.CopyFile(targetDir, sourceDir, nil); err != nil {
|
|
|
|
return "", err
|
2018-01-10 01:47:17 +01:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
err = pt.prepareProject(targetDir)
|
2017-12-20 21:10:46 +01:00
|
|
|
if err != nil {
|
2018-01-10 08:22:35 +01:00
|
|
|
return "", errors.Wrapf(err, "Failed to prepare %v", targetDir)
|
2017-09-25 23:03:16 +02:00
|
|
|
}
|
2017-12-11 23:42:42 +01:00
|
|
|
|
2018-01-17 02:32:49 +01:00
|
|
|
fprintf(stdout, "projdir: %v\n", targetDir)
|
2018-01-10 08:22:35 +01:00
|
|
|
deleteTargetDir = false
|
2018-01-06 01:39:13 +01:00
|
|
|
return targetDir, nil
|
2017-07-13 21:19:17 +02:00
|
|
|
}
|
|
|
|
|
2018-01-10 01:47:17 +01:00
|
|
|
// prepareProject runs setup necessary to get the project ready for `pulumi` commands.
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
func (pt *programTester) prepareProject(projectDir string) error {
|
2017-10-16 23:20:16 +02:00
|
|
|
// Write a .yarnrc file to pass --mutex network to all yarn invocations, since tests
|
|
|
|
// may run concurrently and yarn may fail if invoked concurrently
|
|
|
|
// https://github.com/yarnpkg/yarn/issues/683
|
2018-01-29 18:29:02 +01:00
|
|
|
// Also add --network-concurrency 1 since we've been seeing
|
|
|
|
// https://github.com/yarnpkg/yarn/issues/4563 as well
|
|
|
|
yarnrcerr := ioutil.WriteFile(filepath.Join(projectDir, ".yarnrc"),
|
|
|
|
[]byte("--mutex network\n--network-concurrency 1\n"), 0644)
|
2017-10-16 23:20:16 +02:00
|
|
|
if yarnrcerr != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return yarnrcerr
|
2017-10-16 23:20:16 +02:00
|
|
|
}
|
|
|
|
|
2017-11-16 16:49:07 +01:00
|
|
|
// Load up the package so we can run Yarn in the correct location.
|
2018-01-10 01:47:17 +01:00
|
|
|
projfile := filepath.Join(projectDir, workspace.ProjectFile+".yaml")
|
2018-01-08 22:01:40 +01:00
|
|
|
pkg, err := pack.Load(projfile)
|
2017-11-16 16:49:07 +01:00
|
|
|
if err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-11-16 16:49:07 +01:00
|
|
|
}
|
2018-01-10 01:47:17 +01:00
|
|
|
pkginfo := &engine.Pkginfo{Pkg: pkg, Root: projectDir}
|
2017-11-16 16:49:07 +01:00
|
|
|
cwd, _, err := pkginfo.GetPwdMain()
|
|
|
|
if err != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return err
|
2017-11-16 16:49:07 +01:00
|
|
|
}
|
|
|
|
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if rwd := pt.opts.RelativeWorkDir; rwd != "" {
|
|
|
|
cwd = path.Join(cwd, rwd)
|
2017-11-15 06:02:47 +01:00
|
|
|
}
|
|
|
|
|
2017-08-06 02:49:48 +02:00
|
|
|
// Now ensure dependencies are present.
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
if insterr := pt.runYarnCommand("yarn-install", []string{"install", "--verbose"}, cwd); insterr != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return insterr
|
2017-11-06 18:04:38 +01:00
|
|
|
}
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
for _, dependency := range pt.opts.Dependencies {
|
|
|
|
if linkerr := pt.runYarnCommand("yarn-link", []string{"link", dependency}, cwd); linkerr != nil {
|
2018-01-06 01:39:13 +01:00
|
|
|
return linkerr
|
2017-11-06 18:04:38 +01:00
|
|
|
}
|
2017-08-06 02:49:48 +02:00
|
|
|
}
|
|
|
|
|
2017-08-31 19:21:17 +02:00
|
|
|
// And finally compile it using whatever build steps are in the package.json file.
|
Restructure test framework to ease multiple languages (#799)
This change restructures the test framework code a bit, to make it
easier to introduce additional languages. Our knowledge of Yarn and
Node.js project structure, for instance, was previously baked in to
the test logic, in a way that was hard to make, for instance, Yarn
optional. (In Python, of course, it will not be used.) To better
support this, I've moved some state onto a new programTester struct
that we can use to lazily find binaries required during the testing
(such as Yarn, Pip, and so on). I'm committing this separately so
that I can minimize merge conflicts in the Python work.
2018-01-13 02:10:53 +01:00
|
|
|
return pt.runYarnCommand("yarn-build", []string{"run", "build"}, cwd)
|
2017-07-13 21:19:17 +02:00
|
|
|
}
|