1
0
mirror of https://github.com/go-task/task.git synced 2025-02-03 13:22:11 +02:00

feat: add task location data to json output (#1056)

* feat: add task location data to json output

* feat: add root taskfile location to --json output
This commit is contained in:
Pete Davison 2023-03-17 12:34:06 +00:00 committed by GitHub
parent 15ef1fa1c2
commit e40d2eec9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 169 additions and 44 deletions

View File

@ -2,6 +2,10 @@
## Unreleased ## Unreleased
- Added task location data to the `--json` flag output ([#1056](https://github.com/go-task/task/pull/1056) by @pd93)
## Unreleased
- Change the name of the file generated by `task --init` from `Taskfile.yaml` - Change the name of the file generated by `task --init` from `Taskfile.yaml`
to `Taskfile.yml` to `Taskfile.yml`
([#1062](https://github.com/go-task/task/pull/1062) by @misitebao). ([#1062](https://github.com/go-task/task/pull/1062) by @misitebao).
@ -9,6 +13,7 @@
(`{{splitArgs "foo bar 'foo bar baz'"}}`) to ensure string is splitted as (`{{splitArgs "foo bar 'foo bar baz'"}}`) to ensure string is splitted as
arguments not whitespaces arguments not whitespaces
([#1040](https://github.com/go-task/task/issues/1040), [#1059](https://github.com/go-task/task/pull/1059) by @dhanusaputra). ([#1040](https://github.com/go-task/task/issues/1040), [#1059](https://github.com/go-task/task/pull/1059) by @dhanusaputra).
- Added task location data to the `--json` flag output ([#1056](https://github.com/go-task/task/pull/1056) by @pd93)
## v3.22.0 - 2023-03-10 ## v3.22.0 - 2023-03-10

View File

@ -34,6 +34,7 @@ variable
| `-I` | `--interval` | `string` | `5s` | Sets a different watch interval when using `--watch`, the default being 5 seconds. This string should be a valid [Go Duration](https://pkg.go.dev/time#ParseDuration). | | `-I` | `--interval` | `string` | `5s` | Sets a different watch interval when using `--watch`, the default being 5 seconds. This string should be a valid [Go Duration](https://pkg.go.dev/time#ParseDuration). |
| `-l` | `--list` | `bool` | `false` | Lists tasks with description of current Taskfile. | | `-l` | `--list` | `bool` | `false` | Lists tasks with description of current Taskfile. |
| `-a` | `--list-all` | `bool` | `false` | Lists tasks with or without a description. | | `-a` | `--list-all` | `bool` | `false` | Lists tasks with or without a description. |
| | `--json` | `bool` | `false` | See [JSON Output](#json-output) |
| `-o` | `--output` | `string` | Default set in the Taskfile or `intervealed` | Sets output style: [`interleaved`/`group`/`prefixed`]. | | `-o` | `--output` | `string` | Default set in the Taskfile or `intervealed` | Sets output style: [`interleaved`/`group`/`prefixed`]. |
| | `--output-group-begin` | `string` | | Message template to print before a task's grouped output. | | | `--output-group-begin` | `string` | | Message template to print before a task's grouped output. |
| | `--output-group-end` | `string` | | Message template to print after a task's grouped output. | | | `--output-group-end` | `string` | | Message template to print after a task's grouped output. |
@ -47,6 +48,30 @@ variable
| | `--version` | `bool` | `false` | Show Task version. | | | `--version` | `bool` | `false` | Show Task version. |
| `-w` | `--watch` | `bool` | `false` | Enables watch of the given task. | | `-w` | `--watch` | `bool` | `false` | Enables watch of the given task. |
## JSON Output
When using the `--json` flag in combination with either the `--list` or `--list-all` flags, the output will be a JSON object with the following structure:
```jsonc
{
"tasks": [
{
"name": "",
"desc": "",
"summary": "",
"up_to_date": false,
"location": {
"line": 54,
"column": 3,
"taskfile": "/path/to/Taskfile.yml"
}
},
// ...
],
"location": "/path/to/Taskfile.yml"
}
```
## Special Variables ## Special Variables
There are some special variables that is available on the templating system: There are some special variables that is available on the templating system:

64
help.go
View File

@ -11,6 +11,8 @@ import (
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"golang.org/x/sync/errgroup"
"github.com/go-task/task/v3/internal/editors" "github.com/go-task/task/v3/internal/editors"
"github.com/go-task/task/v3/internal/fingerprint" "github.com/go-task/task/v3/internal/fingerprint"
"github.com/go-task/task/v3/internal/logger" "github.com/go-task/task/v3/internal/logger"
@ -144,31 +146,43 @@ func (e *Executor) ListTaskNames(allTasks bool) {
} }
} }
func (e *Executor) ToEditorOutput(tasks []*taskfile.Task) (*editors.Output, error) { func (e *Executor) ToEditorOutput(tasks []*taskfile.Task) (*editors.Taskfile, error) {
o := &editors.Output{ o := &editors.Taskfile{
Tasks: make([]editors.Task, len(tasks)), Tasks: make([]editors.Task, len(tasks)),
Location: e.Taskfile.Location,
} }
for i, t := range tasks { var g errgroup.Group
// Get the fingerprinting method to use for i := range tasks {
method := e.Taskfile.Method task := tasks[i]
if t.Method != "" { j := i
method = t.Method g.Go(func() error {
} // Get the fingerprinting method to use
upToDate, err := fingerprint.IsTaskUpToDate(context.Background(), t, method := e.Taskfile.Method
fingerprint.WithMethod(method), if task.Method != "" {
fingerprint.WithTempDir(e.TempDir), method = task.Method
fingerprint.WithDry(e.Dry), }
fingerprint.WithLogger(e.Logger), upToDate, err := fingerprint.IsTaskUpToDate(context.Background(), task,
) fingerprint.WithMethod(method),
if err != nil { fingerprint.WithTempDir(e.TempDir),
return nil, err fingerprint.WithDry(e.Dry),
} fingerprint.WithLogger(e.Logger),
o.Tasks[i] = editors.Task{ )
Name: t.Name(), if err != nil {
Desc: t.Desc, return err
Summary: t.Summary, }
UpToDate: upToDate, o.Tasks[j] = editors.Task{
} Name: task.Name(),
Desc: task.Desc,
Summary: task.Summary,
UpToDate: upToDate,
Location: &editors.Location{
Line: task.Location.Line,
Column: task.Location.Column,
Taskfile: task.Location.Taskfile,
},
}
return nil
})
} }
return o, nil return o, g.Wait()
} }

View File

@ -1,14 +1,23 @@
package editors package editors
// Output wraps task list output for use in editor integrations (e.g. VSCode, etc) type (
type Output struct { // Taskfile wraps task list output for use in editor integrations (e.g. VSCode, etc)
Tasks []Task `json:"tasks"` Taskfile struct {
} Tasks []Task `json:"tasks"`
Location string `json:"location"`
// Task describes a single task }
type Task struct { // Task describes a single task
Name string `json:"name"` Task struct {
Desc string `json:"desc"` Name string `json:"name"`
Summary string `json:"summary"` Desc string `json:"desc"`
UpToDate bool `json:"up_to_date"` Summary string `json:"summary"`
} UpToDate bool `json:"up_to_date"`
Location *Location `json:"location"`
}
// Location describes a task's location in a taskfile
Location struct {
Line int `json:"line"`
Column int `json:"column"`
Taskfile string `json:"taskfile"`
}
)

18
taskfile/location.go Normal file
View File

@ -0,0 +1,18 @@
package taskfile
type Location struct {
Line int
Column int
Taskfile string
}
func (l *Location) DeepCopy() *Location {
if l == nil {
return nil
}
return &Location{
Line: l.Line,
Column: l.Column,
Taskfile: l.Taskfile,
}
}

View File

@ -65,7 +65,9 @@ func Merge(t1, t2 *Taskfile, includedTaskfile *IncludedTaskfile, namespaces ...s
} }
// Add the task to the merged taskfile // Add the task to the merged taskfile
t1.Tasks[taskNameWithNamespace(k, namespaces...)] = task taskNameWithNamespace := taskNameWithNamespace(k, namespaces...)
task.Task = taskNameWithNamespace
t1.Tasks[taskNameWithNamespace] = task
} }
return nil return nil

View File

@ -176,12 +176,18 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, string, error) {
} }
} }
for name, task := range t.Tasks { // Set the location of the Taskfile
t.Location = path
for _, task := range t.Tasks {
// If the task is not defined, create a new one
if task == nil { if task == nil {
task = &taskfile.Task{} task = &taskfile.Task{}
t.Tasks[name] = task
} }
task.Task = name // Set the location of the taskfile for each task
if task.Location.Taskfile == "" {
task.Location.Taskfile = path
}
} }
return t, readerNode.Dir, nil return t, readerNode.Dir, nil

View File

@ -6,9 +6,6 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
// Tasks represents a group of tasks
type Tasks map[string]*Task
// Task represents a task // Task represents a task
type Task struct { type Task struct {
Task string Task string
@ -39,6 +36,7 @@ type Task struct {
IncludedTaskfileVars *Vars IncludedTaskfileVars *Vars
IncludedTaskfile *IncludedTaskfile IncludedTaskfile *IncludedTaskfile
Platforms []*Platform Platforms []*Platform
Location *Location
} }
func (t *Task) Name() string { func (t *Task) Name() string {
@ -162,6 +160,7 @@ func (t *Task) DeepCopy() *Task {
IncludedTaskfileVars: t.IncludedTaskfileVars.DeepCopy(), IncludedTaskfileVars: t.IncludedTaskfileVars.DeepCopy(),
IncludedTaskfile: t.IncludedTaskfile.DeepCopy(), IncludedTaskfile: t.IncludedTaskfile.DeepCopy(),
Platforms: deepCopySlice(t.Platforms), Platforms: deepCopySlice(t.Platforms),
Location: t.Location.DeepCopy(),
} }
return c return c
} }

View File

@ -15,6 +15,7 @@ var (
// Taskfile represents a Taskfile.yml // Taskfile represents a Taskfile.yml
type Taskfile struct { type Taskfile struct {
Location string
Version *semver.Version Version *semver.Version
Expansions int Expansions int
Output Output Output Output

45
taskfile/tasks.go Normal file
View File

@ -0,0 +1,45 @@
package taskfile
import (
"fmt"
"gopkg.in/yaml.v3"
)
// Tasks represents a group of tasks
type Tasks map[string]*Task
func (t *Tasks) UnmarshalYAML(node *yaml.Node) error {
switch node.Kind {
case yaml.MappingNode:
tasks := map[string]*Task{}
if err := node.Decode(tasks); err != nil {
return err
}
for name := range tasks {
// Set the task's name
if tasks[name] == nil {
tasks[name] = &Task{
Task: name,
}
}
tasks[name].Task = name
// Set the task's location
for _, keys := range node.Content {
if keys.Value == name {
tasks[name].Location = &Location{
Line: keys.Line,
Column: keys.Column,
}
}
}
}
*t = Tasks(tasks)
return nil
}
return fmt.Errorf("yaml: line %d: cannot unmarshal %s into tasks", node.Line, node.ShortTag())
}

View File

@ -66,6 +66,7 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
IncludeVars: origTask.IncludeVars, IncludeVars: origTask.IncludeVars,
IncludedTaskfileVars: origTask.IncludedTaskfileVars, IncludedTaskfileVars: origTask.IncludedTaskfileVars,
Platforms: origTask.Platforms, Platforms: origTask.Platforms,
Location: origTask.Location,
} }
new.Dir, err = execext.Expand(new.Dir) new.Dir, err = execext.Expand(new.Dir)
if err != nil { if err != nil {