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:
parent
15ef1fa1c2
commit
e40d2eec9e
@ -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
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
38
help.go
38
help.go
@ -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
|
||||||
|
for i := range tasks {
|
||||||
|
task := tasks[i]
|
||||||
|
j := i
|
||||||
|
g.Go(func() error {
|
||||||
// Get the fingerprinting method to use
|
// Get the fingerprinting method to use
|
||||||
method := e.Taskfile.Method
|
method := e.Taskfile.Method
|
||||||
if t.Method != "" {
|
if task.Method != "" {
|
||||||
method = t.Method
|
method = task.Method
|
||||||
}
|
}
|
||||||
upToDate, err := fingerprint.IsTaskUpToDate(context.Background(), t,
|
upToDate, err := fingerprint.IsTaskUpToDate(context.Background(), task,
|
||||||
fingerprint.WithMethod(method),
|
fingerprint.WithMethod(method),
|
||||||
fingerprint.WithTempDir(e.TempDir),
|
fingerprint.WithTempDir(e.TempDir),
|
||||||
fingerprint.WithDry(e.Dry),
|
fingerprint.WithDry(e.Dry),
|
||||||
fingerprint.WithLogger(e.Logger),
|
fingerprint.WithLogger(e.Logger),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
o.Tasks[i] = editors.Task{
|
o.Tasks[j] = editors.Task{
|
||||||
Name: t.Name(),
|
Name: task.Name(),
|
||||||
Desc: t.Desc,
|
Desc: task.Desc,
|
||||||
Summary: t.Summary,
|
Summary: task.Summary,
|
||||||
UpToDate: upToDate,
|
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()
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
Taskfile struct {
|
||||||
Tasks []Task `json:"tasks"`
|
Tasks []Task `json:"tasks"`
|
||||||
|
Location string `json:"location"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Task describes a single task
|
// Task describes a single task
|
||||||
type Task struct {
|
Task struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Desc string `json:"desc"`
|
Desc string `json:"desc"`
|
||||||
Summary string `json:"summary"`
|
Summary string `json:"summary"`
|
||||||
UpToDate bool `json:"up_to_date"`
|
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
18
taskfile/location.go
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
45
taskfile/tasks.go
Normal 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())
|
||||||
|
}
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user