Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the taskfile in include required #1902

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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
29 changes: 29 additions & 0 deletions task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,35 @@ func TestIncludesInterpolation(t *testing.T) {
}
}

func TestIncludesInvalidTaskfile(t *testing.T) {
const dir = "testdata/includes_invalid_taskfile"

tests := []struct {
name string
expectedErr string
}{
{"include_empty_taskfile", "taskfile field in the include cannot be empty"},
{"include_empty_value", "taskfile of the include cannot be empty"},
{"include_missing_taskfile", "taskfile field in the include cannot be null"},
{"include_null_taskfile", "taskfile field in the include cannot be null"},
{"include_null_value", "value of the include cannot be null"},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var buff bytes.Buffer
e := task.Executor{
Dir: filepath.Join(dir, test.name),
Stdout: &buff,
Stderr: &buff,
Silent: true,
}
err := e.Setup()
assert.ErrorContains(t, err, test.expectedErr)
})
}
}

func TestIncludedTaskfileVarMerging(t *testing.T) {
const dir = "testdata/included_taskfile_var_merging"
tests := []struct {
Expand Down
21 changes: 17 additions & 4 deletions taskfile/ast/include.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,18 @@ type Includes struct {
func (includes *Includes) UnmarshalYAML(node *yaml.Node) error {
switch node.Kind {
case yaml.MappingNode:
// NOTE(@andreynering): on this style of custom unmarshalling,
// NOTE(@andreynering): on this style of custom unmarshaling,
// even number contains the keys, while odd numbers contains
// the values.
for i := 0; i < len(node.Content); i += 2 {
keyNode := node.Content[i]
valueNode := node.Content[i+1]

// Ensure the include value is not null, as it must be either a string or an include object.
if valueNode.Kind == yaml.ScalarNode && valueNode.Tag == "!!null" {
return errors.NewTaskfileDecodeError(nil, valueNode).WithMessage("value of the include cannot be null")
}

var v Include
if err := valueNode.Decode(&v); err != nil {
return errors.NewTaskfileDecodeError(err, node)
Expand Down Expand Up @@ -67,18 +72,20 @@ func (includes *Includes) Range(f func(k string, v *Include) error) error {

func (include *Include) UnmarshalYAML(node *yaml.Node) error {
switch node.Kind {

case yaml.ScalarNode:
var str string
if err := node.Decode(&str); err != nil {
return errors.NewTaskfileDecodeError(err, node)
}
if str == "" {
return errors.NewTaskfileDecodeError(nil, node).WithMessage("taskfile of the include cannot be empty")
}
include.Taskfile = str
return nil

case yaml.MappingNode:
var includedTaskfile struct {
Taskfile string
Taskfile *string
Dir string
Optional bool
Internal bool
Expand All @@ -89,7 +96,13 @@ func (include *Include) UnmarshalYAML(node *yaml.Node) error {
if err := node.Decode(&includedTaskfile); err != nil {
return errors.NewTaskfileDecodeError(err, node)
}
include.Taskfile = includedTaskfile.Taskfile
if includedTaskfile.Taskfile == nil {
return errors.NewTaskfileDecodeError(nil, node).WithMessage("taskfile field in the include cannot be null")
}
if *includedTaskfile.Taskfile == "" {
return errors.NewTaskfileDecodeError(nil, node).WithMessage("taskfile field in the include cannot be empty")
}
include.Taskfile = *includedTaskfile.Taskfile
include.Dir = includedTaskfile.Dir
include.Optional = includedTaskfile.Optional
include.Internal = includedTaskfile.Internal
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: '3'

includes:
included:
taskfile: ''

tasks:
default:
cmds:
- task: included:default
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: '3'

includes:
included: ''

tasks:
default:
cmds:
- task: included:default
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: '3'

includes:
included:
dir: '.'

tasks:
default:
cmds:
- task: included:default
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: '3'

includes:
included:
taskfile: null

tasks:
default:
cmds:
- task: included:default
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: '3'

includes:
included: null

tasks:
default:
cmds:
- task: included:default
9 changes: 6 additions & 3 deletions website/static/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -614,14 +614,16 @@
"^.*$": {
"anyOf": [
{
"type": "string"
"type": "string",
"minLength": 1
},
{
"type": "object",
"properties": {
"taskfile": {
"description": "The path for the Taskfile or directory to be included. If a directory, Task will look for files named `Taskfile.yml` or `Taskfile.yaml` inside that directory. If a relative path, resolved relative to the directory containing the including Taskfile.",
"type": "string"
"type": "string",
"minLength": 1
},
"dir": {
"description": "The working directory of the included tasks when run.",
Expand Down Expand Up @@ -650,7 +652,8 @@
"description": "A set of variables to apply to the included Taskfile.",
"$ref": "#/definitions/vars"
}
}
},
"required": ["taskfile"]
}
]
}
Expand Down
Loading