Skip to content

Commit

Permalink
fix: inconsistent current directory resolution depending on include o…
Browse files Browse the repository at this point in the history
…rder (go-task#1757)
  • Loading branch information
pbitty authored Oct 6, 2024
1 parent c5eea29 commit a72e70b
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 2 deletions.
102 changes: 102 additions & 0 deletions task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import (
"context"
"fmt"
"io"
"io/fs"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
"testing"
"time"

"github.com/Masterminds/semver/v3"
"github.com/stretchr/testify/assert"
Expand All @@ -21,6 +25,7 @@ import (
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/experiments"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/taskfile/ast"
)

Expand Down Expand Up @@ -1086,6 +1091,88 @@ func TestIncludesEmptyMain(t *testing.T) {
tt.Run(t)
}

func TestIncludesHttp(t *testing.T) {
enableExperimentForTest(t, &experiments.RemoteTaskfiles, "1")

dir, err := filepath.Abs("testdata/includes_http")
require.NoError(t, err)

srv := httptest.NewServer(http.FileServer(http.Dir(dir)))
defer srv.Close()

t.Cleanup(func() {
// This test fills the .task/remote directory with cache entries because the include URL
// is different on every test due to the dynamic nature of the TCP port in srv.URL
if err := os.RemoveAll(filepath.Join(dir, ".task")); err != nil {
t.Logf("error cleaning up: %s", err)
}
})

taskfiles, err := fs.Glob(os.DirFS(dir), "root-taskfile-*.yml")
require.NoError(t, err)

remotes := []struct {
name string
root string
}{
{
name: "local",
root: ".",
},
{
name: "http-remote",
root: srv.URL,
},
}

for _, taskfile := range taskfiles {
t.Run(taskfile, func(t *testing.T) {
for _, remote := range remotes {
t.Run(remote.name, func(t *testing.T) {
t.Setenv("INCLUDE_ROOT", remote.root)
entrypoint := filepath.Join(dir, taskfile)

var buff SyncBuffer
e := task.Executor{
Entrypoint: entrypoint,
Dir: dir,
Stdout: &buff,
Stderr: &buff,
Insecure: true,
Download: true,
AssumeYes: true,
Logger: &logger.Logger{Stdout: &buff, Stderr: &buff, Verbose: true},
Timeout: time.Minute,
}
require.NoError(t, e.Setup())
defer func() { t.Log("output:", buff.buf.String()) }()

tcs := []struct {
name, dir string
}{
{
name: "second-with-dir-1:third-with-dir-1:default",
dir: filepath.Join(dir, "dir-1"),
},
{
name: "second-with-dir-1:third-with-dir-2:default",
dir: filepath.Join(dir, "dir-2"),
},
}

for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
task, err := e.CompiledTask(&ast.Call{Task: tc.name})
require.NoError(t, err)
assert.Equal(t, tc.dir, task.Dir)
})
}
})
}
})
}
}

func TestIncludesDependencies(t *testing.T) {
tt := fileContentTest{
Dir: "testdata/includes_deps",
Expand Down Expand Up @@ -2616,3 +2703,18 @@ func TestReference(t *testing.T) {
})
}
}

// enableExperimentForTest enables the experiment behind pointer e for the duration of test t and sub-tests,
// with the experiment being restored to its previous state when tests complete.
//
// Typically experiments are controlled via TASK_X_ env vars, but we cannot use those in tests
// because the experiment settings are parsed during experiments.init(), before any tests run.
func enableExperimentForTest(t *testing.T, e *experiments.Experiment, val string) {
prev := *e
*e = experiments.Experiment{
Name: prev.Name,
Enabled: true,
Value: val,
}
t.Cleanup(func() { *e = prev })
}
8 changes: 6 additions & 2 deletions taskfile/node_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,12 @@ func (node *HTTPNode) ResolveDir(dir string) (string, error) {

// NOTE: Uses the directory of the entrypoint (Taskfile), not the current working directory
// This means that files are included relative to one another
entrypointDir := filepath.Dir(node.Dir())
return filepathext.SmartJoin(entrypointDir, path), nil
parent := node.Dir()
if node.Parent() != nil {
parent = node.Parent().Dir()
}

return filepathext.SmartJoin(parent, path), nil
}

func (node *HTTPNode) FilenameAndLastDir() (string, string) {
Expand Down
9 changes: 9 additions & 0 deletions testdata/includes_http/child-taskfile2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: '3'

includes:
third-with-dir-1:
taskfile: "{{.INCLUDE_ROOT}}/child-taskfile3.yml"
dir: ./dir-1
third-with-dir-2:
taskfile: "{{.INCLUDE_ROOT}}/child-taskfile3.yml"
dir: ./dir-2
4 changes: 4 additions & 0 deletions testdata/includes_http/child-taskfile3.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
version: '3'

tasks:
default: "true"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: '3'

includes:
second-no-dir:
taskfile: "{{.INCLUDE_ROOT}}/child-taskfile2.yml"
second-with-dir-1:
taskfile: "{{.INCLUDE_ROOT}}/child-taskfile2.yml"
dir: ./dir-1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: '3'

includes:
second-with-dir-1:
taskfile: "{{.INCLUDE_ROOT}}/child-taskfile2.yml"
dir: ./dir-1
second-no-dir:
taskfile: "{{.INCLUDE_ROOT}}/child-taskfile2.yml"

0 comments on commit a72e70b

Please sign in to comment.