Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Given a version number `MAJOR.MINOR.PATCH`, we increment the:
### Fixed

- Fix Terragrunt integration not skipping hidden directories and not honoring `.tmskip` file.
- Fix `terramate [run, script run]` not computing the relative command path correctly relative
to the stack directory.

## v0.13.0

Expand Down
3 changes: 2 additions & 1 deletion cloudsync/terraform_planfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ func runTerraformShow(e *engine.Engine, run engine.StackCloudRun, flags ...strin
cmdName = "terraform"
}

cmdPath, err := runpkg.LookPath(cmdName, run.Env)
stackdir := run.Stack.Dir.HostPath(e.Config().HostDir())
cmdPath, err := runpkg.LookPath(cmdName, stackdir, run.Env)
if err != nil {
return "", errors.E(clitest.ErrCloudTerraformPlanFile, "looking up executable for %s: %w", cmdName, err)
}
Expand Down
57 changes: 57 additions & 0 deletions e2etests/core/run_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,60 @@ func TestRunLookPathFromStackEnviron(t *testing.T) {
Stdout: "Hello from myscript\n",
})
}

func TestRunWithRelativePathFromStackDir(t *testing.T) {
t.Parallel()

s := sandbox.NoGit(t, true)
s.Env = os.Environ()
s.BuildTree([]string{
`f:bin/helper.sh:#!/bin/bash
echo "okay"
`,
`s:stack`,
`s:stack/nested`,
`run:/:chmod +x ./bin/helper.sh`,
})

cli := NewCLI(t, s.RootDir())
AssertRunResult(t, cli.Run("run", "--quiet", "--eval", `${tm_join("/", [terramate.stack.path.to_root, "bin", "helper.sh"])}`),
RunExpected{
Stdout: nljoin("okay", "okay"),
},
)
}

func TestScriptRunWithRelativePathFromStackDir(t *testing.T) {
t.Parallel()

s := sandbox.NoGit(t, true)
s.Env = os.Environ()
s.BuildTree([]string{
`f:bin/helper.sh:#!/bin/bash
echo "okay"
`,
`run:/:chmod +x ./bin/helper.sh`,
`s:stack`,
`s:stack/nested`,
`f:script.tm:` + Doc(
Terramate(
Config(
Experiments("scripts"),
),
),
Block("script",
Labels("test"),
Block("job",
Expr("command", `["${tm_join("/", [terramate.stack.path.to_root, "bin", "helper.sh"])}"]`),
),
),
).String(),
})

cli := NewCLI(t, s.RootDir())
AssertRunResult(t, cli.Run("script", "run", "--quiet", "--", "test"),
RunExpected{
Stdout: nljoin("okay", "okay"),
},
)
}
5 changes: 3 additions & 2 deletions engine/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,8 @@ func (e *Engine) RunAll(
Str("cmd", cmdStr).
Logger()

cmdPath, err := runutil.LookPath(task.Cmd[0], environ)
stackdir := run.Stack.HostDir(e.Config())
cmdPath, err := runutil.LookPath(task.Cmd[0], stackdir, environ)
if err != nil {
opts.Hooks.After(e, cloudRun, RunResult{ExitCode: -1}, errors.E(ErrRunCommandNotExecuted, err))
errs.Append(errors.E(err, "running `%s` in stack %s", cmdStr, run.Stack.Dir))
Expand All @@ -453,7 +454,7 @@ func (e *Engine) RunAll(
}

cmd := exec.Command(cmdPath, task.Cmd[1:]...)
cmd.Dir = run.Stack.HostDir(e.Config())
cmd.Dir = stackdir
cmd.Env = environ

stdin := opts.Stdin
Expand Down
5 changes: 4 additions & 1 deletion run/lookpath_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ const ErrNotFound errors.Kind = "executable file not found in $PATH"
// In older versions of Go, LookPath could return a path relative to the current directory.
// As of Go 1.19, LookPath will instead return that path along with an error satisfying
// errors.Is(err, ErrDot). See the package documentation for more details.
func LookPath(file string, environ []string) (string, error) {
func LookPath(file string, cwd string, environ []string) (string, error) {
// NOTE(rsc): I wish we could use the Plan 9 behavior here
// (only bypass the path if file begins with / or ./ or ../)
// but that would not match all the Unix shells.

if strings.Contains(file, "/") {
if !filepath.IsAbs(file) {
file = filepath.Join(cwd, file)
}
err := findExecutable(file)
if err == nil {
return file, nil
Expand Down
5 changes: 4 additions & 1 deletion run/lookpath_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func findExecutable(file string, exts []string) (string, error) {
// In older versions of Go, LookPath could return a path relative to the current directory.
// As of Go 1.19, LookPath will instead return that path along with an error satisfying
// errors.Is(err, ErrDot). See the package documentation for more details.
func LookPath(file string, environ []string) (string, error) {
func LookPath(file string, cwd string, environ []string) (string, error) {
var exts []string
x, _ := Getenv(`PATHEXT`, environ)
if x != "" {
Expand All @@ -92,6 +92,9 @@ func LookPath(file string, environ []string) (string, error) {
}

if strings.ContainsAny(file, `:\/`) {
if !filepath.IsAbs(file) {
file = filepath.Join(cwd, file)
}
f, err := findExecutable(file, exts)
if err == nil {
return f, nil
Expand Down
2 changes: 1 addition & 1 deletion test/sandbox/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ func buildTree(t testing.TB, root *config.Root, environ []string, layout []strin
))
case "run:":
cmdParts := strings.Split(param2, " ")
path, err := run.LookPath(cmdParts[0], environ)
path, err := run.LookPath(cmdParts[0], rootdir, environ)
assert.NoError(t, err)
cmd := exec.Command(path, cmdParts[1:]...)
cmd.Dir = filepath.Join(rootdir, param1)
Expand Down
Loading