fix: remote git taskfile cloning and directory includes (#2602)

This commit is contained in:
Valentin Maerten
2026-01-14 19:43:39 +01:00
committed by GitHub
parent 4e963f8714
commit ba38344ca6
2 changed files with 22 additions and 16 deletions

View File

@@ -15,6 +15,7 @@ import (
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/internal/fsext"
)
// An GitNode is a node that reads a Taskfile from a remote location via Git.
@@ -104,13 +105,13 @@ func (node *GitNode) buildURL() string {
// Get the base URL
baseURL := node.url.String()
ref := node.ref
if ref == "" {
ref = "HEAD"
}
// Always use git:: prefix for git URLs (following Terraform's pattern)
// This forces go-getter to use git protocol
return fmt.Sprintf("git::%s?ref=%s&depth=1", baseURL, ref)
if node.ref != "" {
return fmt.Sprintf("git::%s?ref=%s&depth=1", baseURL, node.ref)
}
// When no ref is specified, omit it entirely to let git clone the default branch
return fmt.Sprintf("git::%s?depth=1", baseURL)
}
// getOrCloneRepo returns the path to a cached git repository.
@@ -164,11 +165,16 @@ func (node *GitNode) ReadContext(ctx context.Context) ([]byte, error) {
}
// Build path to Taskfile in the cached repo
taskfilePath := node.path
if taskfilePath == "" {
taskfilePath = "Taskfile.yml"
// If node.path is empty, search in repo root; otherwise search in the specified path
// fsext.SearchPath handles both files and directories (searching for DefaultTaskfiles)
searchPath := repoDir
if node.path != "" {
searchPath = filepath.Join(repoDir, node.path)
}
filePath, err := fsext.SearchPath(searchPath, DefaultTaskfiles)
if err != nil {
return nil, err
}
filePath := filepath.Join(repoDir, taskfilePath)
// Read file from cached repo
b, err := os.ReadFile(filePath)
@@ -230,7 +236,7 @@ func (node *GitNode) repoCacheKey() string {
ref := node.ref
if ref == "" {
ref = "HEAD"
ref = "_default_" // Placeholder for the remote's default branch
}
return filepath.Join(node.url.Host, repoPath, ref)

View File

@@ -127,9 +127,9 @@ func TestGitNode_buildURL(t *testing.T) {
expectedURL: "git::https://github.com/foo/bar.git?ref=v1.0.0&depth=1",
},
{
name: "HTTPS without ref (uses remote HEAD)",
name: "HTTPS without ref (uses remote default branch)",
entrypoint: "https://github.com/foo/bar.git//Taskfile.yml",
expectedURL: "git::https://github.com/foo/bar.git?ref=HEAD&depth=1",
expectedURL: "git::https://github.com/foo/bar.git?depth=1",
},
{
name: "SSH with directory path",
@@ -198,20 +198,20 @@ func TestRepoCacheKey_DifferentRepos(t *testing.T) {
assert.NotEqual(t, key1, key2, "Different repos should generate different cache keys")
}
func TestRepoCacheKey_NoRefVsHead(t *testing.T) {
func TestRepoCacheKey_NoRefVsExplicitRef(t *testing.T) {
t.Parallel()
// No ref (defaults to HEAD) vs explicit HEAD should have SAME cache key
// No ref (uses default branch) vs explicit ref should have DIFFERENT cache keys
node1, err := NewGitNode("https://github.com/foo/bar.git//file.yml", "", false)
require.NoError(t, err)
node2, err := NewGitNode("https://github.com/foo/bar.git//file.yml?ref=HEAD", "", false)
node2, err := NewGitNode("https://github.com/foo/bar.git//file.yml?ref=main", "", false)
require.NoError(t, err)
key1 := node1.repoCacheKey()
key2 := node2.repoCacheKey()
assert.Equal(t, key1, key2, "No ref and explicit HEAD should generate same cache key")
assert.NotEqual(t, key1, key2, "No ref and explicit ref should generate different cache keys")
}
func TestRepoCacheKey_SSHvsHTTPS(t *testing.T) {