github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/test/integration/deploy_int_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  	"runtime"
     9  	"testing"
    10  
    11  	"github.com/ActiveState/cli/internal/testhelpers/suite"
    12  	"github.com/google/uuid"
    13  
    14  	"github.com/ActiveState/cli/internal/config"
    15  	"github.com/ActiveState/cli/internal/constants"
    16  	"github.com/ActiveState/cli/internal/fileutils"
    17  	"github.com/ActiveState/cli/internal/subshell"
    18  	"github.com/ActiveState/cli/internal/testhelpers/e2e"
    19  	"github.com/ActiveState/cli/internal/testhelpers/tagsuite"
    20  )
    21  
    22  type DeployIntegrationTestSuite struct {
    23  	tagsuite.Suite
    24  }
    25  
    26  var symlinkExt = ""
    27  
    28  func init() {
    29  	if runtime.GOOS == "windows" {
    30  		symlinkExt = ".lnk"
    31  	}
    32  }
    33  
    34  func (suite *DeployIntegrationTestSuite) deploy(ts *e2e.Session, prj string, targetPath string, targetID string) {
    35  	var cp *e2e.SpawnedCmd
    36  	switch runtime.GOOS {
    37  	case "windows":
    38  		cp = ts.SpawnWithOpts(
    39  			e2e.OptArgs("deploy", prj, "--path", targetPath),
    40  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
    41  		)
    42  	case "darwin":
    43  		// On MacOS the command is the same as Linux, however some binaries
    44  		// already exist at /usr/local/bin so we use the --force flag
    45  		cp = ts.SpawnWithOpts(
    46  			e2e.OptArgs("deploy", prj, "--path", targetPath, "--force"),
    47  			e2e.OptAppendEnv("SHELL=bash"),
    48  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
    49  		)
    50  	default:
    51  		cp = ts.SpawnWithOpts(
    52  			e2e.OptArgs("deploy", prj, "--path", targetPath),
    53  			e2e.OptAppendEnv("SHELL=bash"),
    54  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
    55  		)
    56  	}
    57  
    58  	cp.Expect("Installing", e2e.RuntimeSourcingTimeoutOpt)
    59  	cp.Expect("Configuring")
    60  	if runtime.GOOS != "windows" {
    61  		cp.Expect("Symlinking")
    62  	}
    63  	cp.Expect("Deployment Information")
    64  	cp.Expect(targetID) // expect bin dir
    65  	if runtime.GOOS == "windows" {
    66  		cp.Expect("log out")
    67  	} else {
    68  		cp.Expect("restart")
    69  	}
    70  	cp.ExpectExitCode(0)
    71  }
    72  
    73  func (suite *DeployIntegrationTestSuite) TestDeployPerl() {
    74  	suite.OnlyRunForTags(tagsuite.Perl, tagsuite.Deploy)
    75  	if !e2e.RunningOnCI() {
    76  		suite.T().Skipf("Skipping DeployIntegrationTestSuite when not running on CI, as it modifies bashrc/registry")
    77  	}
    78  
    79  	if runtime.GOOS == "darwin" {
    80  		suite.T().Skip("Perl is not supported on Mac OS yet.")
    81  	}
    82  
    83  	ts := e2e.New(suite.T(), false)
    84  	defer ts.Close()
    85  
    86  	targetID, err := uuid.NewUUID()
    87  	suite.Require().NoError(err)
    88  	targetPath, err := fileutils.ResolveUniquePath(filepath.Join(ts.Dirs.Work, targetID.String()))
    89  	suite.Require().NoError(err)
    90  
    91  	suite.deploy(ts, "ActiveState-CLI/Perl", targetPath, targetID.String())
    92  
    93  	suite.checkSymlink("perl", ts.Dirs.Bin, targetID.String())
    94  
    95  	var cp *e2e.SpawnedCmd
    96  	if runtime.GOOS == "windows" {
    97  		cp = ts.SpawnCmdWithOpts(
    98  			"cmd.exe",
    99  			e2e.OptArgs("/k", filepath.Join(targetPath, "bin", "shell.bat")),
   100  			e2e.OptAppendEnv("PATHEXT=.COM;.EXE;.BAT;.LNK", "SHELL="),
   101  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   102  		)
   103  	} else {
   104  		cp = ts.SpawnCmdWithOpts(
   105  			"/bin/bash",
   106  			e2e.OptAppendEnv("PROMPT_COMMAND="),
   107  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   108  		)
   109  		cp.SendLine(fmt.Sprintf("source %s\n", filepath.Join(targetPath, "bin", "shell.sh")))
   110  	}
   111  
   112  	errorLevel := "echo $?"
   113  	if runtime.GOOS == "windows" {
   114  		errorLevel = `echo %ERRORLEVEL%`
   115  	}
   116  	// check that some of the installed binaries are use-able
   117  	cp.SendLine("perl --version")
   118  	cp.Expect("This is perl 5")
   119  	cp.SendLine(errorLevel)
   120  	cp.Expect("0")
   121  
   122  	cp.SendLine("ptar -h")
   123  	cp.Expect("a tar-like program written in perl")
   124  
   125  	cp.SendLine("exit 0")
   126  	cp.ExpectExitCode(0)
   127  }
   128  
   129  func (suite *DeployIntegrationTestSuite) checkSymlink(name string, binDir, targetID string) {
   130  	if runtime.GOOS != "Linux" {
   131  		return
   132  	}
   133  	// Linux symlinks to /usr/local/bin or the first write-able directory in PATH, so we can verify right away
   134  	execPath, err := exec.LookPath(name)
   135  	// If not on PATH it needs to exist in the temporary directory
   136  	var execDir string
   137  	if err == nil {
   138  		execDir, _ = filepath.Split(execPath)
   139  	}
   140  	if err != nil || (execDir != "/usr/local/bin/" && execDir != "/usr/bin/") {
   141  		execPath = filepath.Join(binDir, name)
   142  		if !fileutils.FileExists(execPath) {
   143  			suite.Fail("Expected to find %s on PATH", name)
   144  		}
   145  	}
   146  	link, err := os.Readlink(execPath)
   147  	suite.Require().NoError(err)
   148  	suite.Contains(link, targetID, "%s executable resolves to the one on our target dir", name)
   149  }
   150  
   151  func (suite *DeployIntegrationTestSuite) TestDeployPython() {
   152  	suite.OnlyRunForTags(tagsuite.Deploy, tagsuite.Python, tagsuite.Critical)
   153  	if !e2e.RunningOnCI() {
   154  		suite.T().Skipf("Skipping DeployIntegrationTestSuite when not running on CI, as it modifies bashrc/registry")
   155  	}
   156  
   157  	ts := e2e.New(suite.T(), false)
   158  	defer ts.Close()
   159  
   160  	ts.SetupRCFile()
   161  	suite.T().Setenv("ACTIVESTATE_HOME", ts.Dirs.HomeDir)
   162  
   163  	targetID, err := uuid.NewUUID()
   164  	suite.Require().NoError(err)
   165  	targetPath, err := fileutils.ResolveUniquePath(filepath.Join(ts.Dirs.Work, targetID.String()))
   166  	suite.Require().NoError(err)
   167  
   168  	suite.deploy(ts, "ActiveState-CLI/Python3", targetPath, targetID.String())
   169  
   170  	suite.checkSymlink("python3", ts.Dirs.Bin, targetID.String())
   171  
   172  	var cp *e2e.SpawnedCmd
   173  	if runtime.GOOS == "windows" {
   174  		cp = ts.SpawnCmdWithOpts(
   175  			"cmd.exe",
   176  			e2e.OptArgs("/k", filepath.Join(targetPath, "bin", "shell.bat")),
   177  			e2e.OptAppendEnv("PATHEXT=.COM;.EXE;.BAT;.LNK", "SHELL="),
   178  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   179  		)
   180  	} else {
   181  		cp = ts.SpawnCmdWithOpts(
   182  			"/bin/bash",
   183  			e2e.OptAppendEnv("PROMPT_COMMAND="),
   184  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   185  		)
   186  		cp.SendLine(fmt.Sprintf("source %s\n", filepath.Join(targetPath, "bin", "shell.sh")))
   187  	}
   188  
   189  	errorLevel := "echo $?"
   190  	if runtime.GOOS == "windows" {
   191  		errorLevel = `echo %ERRORLEVEL%`
   192  	}
   193  
   194  	cp.SendLine("python3 --version")
   195  	cp.Expect("Python 3")
   196  	cp.SendLine(errorLevel)
   197  	cp.Expect("0")
   198  
   199  	cp.SendLine("pip3 --version")
   200  	cp.Expect("pip")
   201  	cp.SendLine(errorLevel)
   202  	cp.Expect("0")
   203  
   204  	if runtime.GOOS == "darwin" {
   205  		// This is kept as a regression test, pyvenv used to have a relocation problem on MacOS
   206  		cp.SendLine("pyvenv -h")
   207  		cp.SendLine("echo $?")
   208  		cp.Expect("0")
   209  	}
   210  
   211  	cp.SendLine("python3 -m pytest --version")
   212  	cp.Expect("pytest")
   213  
   214  	cp.SendLine("exit")
   215  	cp.ExpectExitCode(0)
   216  
   217  	suite.AssertConfig(ts, targetID.String())
   218  }
   219  
   220  func (suite *DeployIntegrationTestSuite) TestDeployInstall() {
   221  	suite.OnlyRunForTags(tagsuite.Deploy)
   222  	if !e2e.RunningOnCI() {
   223  		suite.T().Skipf("Skipping DeployIntegrationTestSuite when not running on CI, as it modifies bashrc/registry")
   224  	}
   225  
   226  	ts := e2e.New(suite.T(), false)
   227  	defer ts.Close()
   228  
   229  	targetDir, err := fileutils.ResolveUniquePath(filepath.Join(ts.Dirs.Work, "target"))
   230  	suite.Require().NoError(err)
   231  	if fileutils.TargetExists(targetDir) {
   232  		isEmpty, err := fileutils.IsEmptyDir(targetDir)
   233  		suite.Require().NoError(err)
   234  		suite.True(isEmpty, "Target dir should be empty before we start")
   235  	}
   236  
   237  	suite.InstallAndAssert(ts, targetDir)
   238  
   239  	isEmpty, err := fileutils.IsEmptyDir(targetDir)
   240  	suite.Require().NoError(err)
   241  	suite.False(isEmpty, "Target dir should have artifacts written to it")
   242  }
   243  
   244  func (suite *DeployIntegrationTestSuite) InstallAndAssert(ts *e2e.Session, targetPath string) {
   245  	cp := ts.SpawnWithOpts(
   246  		e2e.OptArgs("deploy", "install", "ActiveState-CLI/Python3", "--path", targetPath),
   247  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   248  	)
   249  
   250  	cp.Expect("Installing Runtime")
   251  	cp.Expect("Installing", e2e.RuntimeSourcingTimeoutOpt)
   252  	cp.Expect("Installation completed", e2e.RuntimeSourcingTimeoutOpt)
   253  	cp.ExpectExitCode(0)
   254  }
   255  
   256  func (suite *DeployIntegrationTestSuite) TestDeployConfigure() {
   257  	suite.OnlyRunForTags(tagsuite.Deploy)
   258  	if !e2e.RunningOnCI() {
   259  		suite.T().Skipf("Skipping TestDeployConfigure when not running on CI, as it modifies bashrc/registry")
   260  	}
   261  	ts := e2e.New(suite.T(), false)
   262  	defer ts.Close()
   263  
   264  	ts.SetupRCFile()
   265  	suite.T().Setenv("ACTIVESTATE_HOME", ts.Dirs.HomeDir)
   266  
   267  	targetID, err := uuid.NewUUID()
   268  	suite.Require().NoError(err)
   269  	targetPath, err := fileutils.ResolveUniquePath(filepath.Join(ts.Dirs.Work, targetID.String()))
   270  	suite.Require().NoError(err)
   271  
   272  	// Install step is required
   273  	cp := ts.SpawnWithOpts(
   274  		e2e.OptArgs("deploy", "configure", "ActiveState-CLI/Python3", "--path", targetPath),
   275  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   276  	)
   277  	cp.Expect("need to run the install step")
   278  	cp.ExpectExitCode(1)
   279  	ts.IgnoreLogErrors()
   280  	suite.InstallAndAssert(ts, targetPath)
   281  
   282  	if runtime.GOOS != "windows" {
   283  		cp = ts.SpawnWithOpts(
   284  			e2e.OptArgs("deploy", "configure", "ActiveState-CLI/Python3", "--path", targetPath),
   285  			e2e.OptAppendEnv("SHELL=bash"),
   286  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   287  		)
   288  	} else {
   289  		cp = ts.SpawnWithOpts(
   290  			e2e.OptArgs("deploy", "configure", "ActiveState-CLI/Python3", "--path", targetPath),
   291  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   292  		)
   293  	}
   294  
   295  	cp.Expect("Configuring shell", e2e.RuntimeSourcingTimeoutOpt)
   296  	cp.ExpectExitCode(0)
   297  	suite.AssertConfig(ts, targetID.String())
   298  
   299  	if runtime.GOOS == "windows" {
   300  		cp = ts.SpawnWithOpts(
   301  			e2e.OptArgs("deploy", "configure", "ActiveState-CLI/Python3", "--path", targetPath, "--user"),
   302  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   303  		)
   304  		cp.Expect("Configuring shell", e2e.RuntimeSourcingTimeoutOpt)
   305  		cp.ExpectExitCode(0)
   306  
   307  		out, err := exec.Command("reg", "query", `HKCU\Environment`, "/v", "Path").Output()
   308  		suite.Require().NoError(err)
   309  		suite.Contains(string(out), targetID.String(), "Windows user PATH should contain our target dir")
   310  	}
   311  }
   312  
   313  func (suite *DeployIntegrationTestSuite) AssertConfig(ts *e2e.Session, targetID string) {
   314  	if runtime.GOOS != "windows" {
   315  		// Test config file
   316  		cfg, err := config.New()
   317  		suite.Require().NoError(err)
   318  
   319  		subshell := subshell.New(cfg)
   320  		rcFile, err := subshell.RcFile()
   321  		suite.Require().NoError(err)
   322  
   323  		bashContents := fileutils.ReadFileUnsafe(rcFile)
   324  		suite.Contains(string(bashContents), constants.RCAppendDeployStartLine, "config file should contain our RC Append Start line")
   325  		suite.Contains(string(bashContents), constants.RCAppendDeployStopLine, "config file should contain our RC Append Stop line")
   326  		suite.Contains(string(bashContents), targetID, "config file should contain our target dir")
   327  	} else {
   328  		// Test registry
   329  		out, err := exec.Command("reg", "query", `HKLM\SYSTEM\ControlSet001\Control\Session Manager\Environment`, "/v", "Path").Output()
   330  		suite.Require().NoError(err)
   331  		suite.Contains(string(out), targetID, "bashrc should contain our target dir")
   332  	}
   333  }
   334  
   335  func (suite *DeployIntegrationTestSuite) TestDeploySymlink() {
   336  	suite.OnlyRunForTags(tagsuite.Deploy)
   337  	if runtime.GOOS != "windows" && !e2e.RunningOnCI() {
   338  		suite.T().Skipf("Skipping TestDeploySymlink when not running on CI, as it modifies PATH")
   339  	}
   340  
   341  	ts := e2e.New(suite.T(), false, "SHELL=")
   342  	defer ts.Close()
   343  
   344  	targetID, err := uuid.NewUUID()
   345  	suite.Require().NoError(err)
   346  	targetPath, err := fileutils.ResolveUniquePath(filepath.Join(ts.Dirs.Work, targetID.String()))
   347  	suite.Require().NoError(err)
   348  
   349  	// Install step is required
   350  	cp := ts.SpawnWithOpts(
   351  		e2e.OptArgs("deploy", "symlink", "ActiveState-CLI/Python3", "--path", targetPath),
   352  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   353  	)
   354  	cp.Expect("need to run the install step")
   355  	cp.ExpectExitCode(1)
   356  	ts.IgnoreLogErrors()
   357  	suite.InstallAndAssert(ts, targetPath)
   358  
   359  	if runtime.GOOS != "darwin" {
   360  		cp = ts.SpawnWithOpts(
   361  			e2e.OptArgs("deploy", "symlink", "ActiveState-CLI/Python3", "--path", targetPath),
   362  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   363  		)
   364  	} else {
   365  		cp = ts.SpawnWithOpts(
   366  			e2e.OptArgs("deploy", "symlink", "ActiveState-CLI/Python3", "--path", targetPath, "--force"),
   367  			e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   368  		)
   369  	}
   370  
   371  	if runtime.GOOS != "windows" {
   372  		cp.Expect("Symlinking executables")
   373  	} else {
   374  		cp.Expect("Skipped")
   375  	}
   376  	cp.ExpectExitCode(0)
   377  
   378  	suite.checkSymlink("python3", ts.Dirs.Bin, targetID.String())
   379  }
   380  
   381  func (suite *DeployIntegrationTestSuite) TestDeployReport() {
   382  	suite.OnlyRunForTags(tagsuite.Deploy)
   383  	ts := e2e.New(suite.T(), false)
   384  	defer ts.Close()
   385  
   386  	targetID, err := uuid.NewUUID()
   387  	suite.Require().NoError(err)
   388  	targetPath, err := fileutils.ResolveUniquePath(filepath.Join(ts.Dirs.Work, targetID.String()))
   389  	suite.Require().NoError(err)
   390  
   391  	// Install step is required
   392  	cp := ts.SpawnWithOpts(
   393  		e2e.OptArgs("deploy", "report", "ActiveState-CLI/Python3", "--path", targetPath),
   394  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   395  	)
   396  	cp.Expect("need to run the install step")
   397  	cp.ExpectExitCode(1)
   398  	ts.IgnoreLogErrors()
   399  	suite.InstallAndAssert(ts, targetPath)
   400  
   401  	cp = ts.SpawnWithOpts(
   402  		e2e.OptArgs("deploy", "report", "ActiveState-CLI/Python3", "--path", targetPath),
   403  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   404  	)
   405  	cp.Expect("Deployment Information")
   406  	cp.Expect(targetID.String()) // expect bin dir
   407  	if runtime.GOOS == "windows" {
   408  		cp.Expect("log out")
   409  	} else {
   410  		cp.Expect("restart")
   411  	}
   412  	cp.ExpectExitCode(0)
   413  }
   414  
   415  func (suite *DeployIntegrationTestSuite) TestDeployTwice() {
   416  	suite.OnlyRunForTags(tagsuite.Deploy)
   417  	if runtime.GOOS == "darwin" || !e2e.RunningOnCI() {
   418  		suite.T().Skipf("Skipping TestDeployTwice when not running on CI or on MacOS, as it modifies PATH")
   419  	}
   420  
   421  	ts := e2e.New(suite.T(), false)
   422  	defer ts.Close()
   423  
   424  	targetPath, err := fileutils.ResolveUniquePath(filepath.Join(ts.Dirs.Work, "target"))
   425  	suite.Require().NoError(err)
   426  
   427  	suite.InstallAndAssert(ts, targetPath)
   428  
   429  	pathDir := fileutils.TempDirUnsafe()
   430  	defer os.RemoveAll(pathDir)
   431  	cp := ts.SpawnWithOpts(
   432  		e2e.OptArgs("deploy", "symlink", "ActiveState-CLI/Python3", "--path", targetPath),
   433  		e2e.OptAppendEnv(fmt.Sprintf("PATH=%s", pathDir)), // Avoid conflicts
   434  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   435  	)
   436  	cp.ExpectExitCode(0)
   437  
   438  	// we do not symlink on windows anymore
   439  	if runtime.GOOS != "windows" {
   440  		suite.True(fileutils.FileExists(filepath.Join(targetPath, "bin", "python3"+symlinkExt)), "Python3 symlink should have been written")
   441  	}
   442  
   443  	// Running deploy a second time should not cause any errors (cache is properly picked up)
   444  	cpx := ts.SpawnWithOpts(
   445  		e2e.OptArgs("deploy", "symlink", "ActiveState-CLI/Python3", "--path", targetPath),
   446  		e2e.OptAppendEnv(fmt.Sprintf("PATH=%s", pathDir)), // Avoid conflicts
   447  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   448  	)
   449  	cpx.ExpectExitCode(0)
   450  }
   451  
   452  func (suite *DeployIntegrationTestSuite) TestDeployUninstall() {
   453  	suite.OnlyRunForTags(tagsuite.Deploy)
   454  	if !e2e.RunningOnCI() {
   455  		suite.T().Skipf("Skipping TestDeployUninstall when not running on CI, as it modifies bashrc/registry")
   456  	}
   457  
   458  	ts := e2e.New(suite.T(), false)
   459  	defer ts.Close()
   460  
   461  	targetDir := filepath.Join(ts.Dirs.Work, "target")
   462  	if fileutils.TargetExists(targetDir) {
   463  		isEmpty, err := fileutils.IsEmptyDir(targetDir)
   464  		suite.Require().NoError(err)
   465  		suite.True(isEmpty, "Target dir should be empty before we start")
   466  	}
   467  
   468  	suite.InstallAndAssert(ts, targetDir)
   469  
   470  	// Uninstall deployed runtime.
   471  	cp := ts.SpawnWithOpts(
   472  		e2e.OptArgs("deploy", "uninstall", "--path", filepath.Join(ts.Dirs.Work, "target")),
   473  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   474  	)
   475  	cp.Expect("Uninstall Deployed Runtime")
   476  	cp.Expect("Successful")
   477  	cp.ExpectExitCode(0)
   478  	suite.False(fileutils.TargetExists(filepath.Join(ts.Dirs.Work, "target")), "Deploy dir was not deleted")
   479  	suite.True(fileutils.IsDir(ts.Dirs.Work), "Work dir was unexpectedly deleted")
   480  
   481  	// Trying to uninstall again should fail
   482  	cp = ts.SpawnWithOpts(
   483  		e2e.OptArgs("deploy", "uninstall", "--path", filepath.Join(ts.Dirs.Work, "target")),
   484  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   485  	)
   486  	cp.Expect("no deployed runtime")
   487  	cp.ExpectExitCode(1)
   488  	ts.IgnoreLogErrors()
   489  	suite.True(fileutils.IsDir(ts.Dirs.Work), "Work dir was unexpectedly deleted")
   490  
   491  	// Trying to uninstall in a non-deployment directory should fail.
   492  	cp = ts.SpawnWithOpts(
   493  		e2e.OptArgs("deploy", "uninstall"),
   494  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   495  	)
   496  	cp.Expect("no deployed runtime")
   497  	cp.ExpectExitCode(1)
   498  	suite.True(fileutils.IsDir(ts.Dirs.Work), "Work dir was unexpectedly deleted")
   499  
   500  	// Trying to uninstall in a non-deployment directory should not delete that directory.
   501  	cp = ts.SpawnWithOpts(
   502  		e2e.OptArgs("deploy", "uninstall", "--path", ts.Dirs.Work),
   503  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   504  	)
   505  	cp.Expect("no deployed runtime")
   506  	cp.ExpectExitCode(1)
   507  	suite.True(fileutils.IsDir(ts.Dirs.Work), "Work dir was unexpectedly deleted")
   508  }
   509  
   510  func TestDeployIntegrationTestSuite(t *testing.T) {
   511  	suite.Run(t, new(DeployIntegrationTestSuite))
   512  }