diff --git a/cmd/tsk/tsk.go b/cmd/tsk/tsk.go index 5167756..8894fd4 100644 --- a/cmd/tsk/tsk.go +++ b/cmd/tsk/tsk.go @@ -30,6 +30,7 @@ type Options struct { pure bool taskFile string tasks []string + time bool which bool } @@ -50,6 +51,7 @@ func main() { flag.BoolVar(&opts.prefix, "prefix", false, "prefix task output with the task name") flag.BoolVarP(&opts.pure, "pure", "", false, "don't inherit the parent env") flag.StringVarP(&opts.taskFile, "file", "f", "", "taskfile to use") + flag.BoolVar(&opts.time, "time", false, "show task duration after completion") flag.BoolVar(&opts.which, "which", false, "print the path to the found tasks.toml, or an error") flag.BoolVarP(&help, "help", "h", false, "") flag.Parse() @@ -94,6 +96,7 @@ func main() { Stderr: os.Stderr, Config: cfg, Prefix: opts.prefix, + Time: opts.time, } if opts.listTasks { diff --git a/internal/task/task.go b/internal/task/task.go index 33ec385..e933477 100644 --- a/internal/task/task.go +++ b/internal/task/task.go @@ -11,6 +11,7 @@ import ( "regexp" "strings" "sync" + "time" output "github.com/notnmeyer/tsk/internal/outputformat" @@ -48,6 +49,7 @@ type Executor struct { Stderr io.Writer Config *Config Prefix bool + Time bool colorIndex int taskColors map[string]string } @@ -131,6 +133,8 @@ func (exec *Executor) RunTasks(config *Config, tasks *[]string) error { taskConfig.Dir = config.TaskFileDir } + taskStart := time.Now() + if len(taskConfig.Deps) > 0 { for _, depGroup := range taskConfig.Deps { var wg sync.WaitGroup @@ -162,6 +166,7 @@ func (exec *Executor) RunTasks(config *Config, tasks *[]string) error { Stdin: exec.Stdin, Config: exec.Config, Prefix: exec.Prefix, + Time: exec.Time, } // if a task contains cmds, run them @@ -184,6 +189,10 @@ func (exec *Executor) RunTasks(config *Config, tasks *[]string) error { os.Exit(1) } } + + if exec.Time && exec.Stderr != nil { + fmt.Fprintf(exec.Stderr, "::%s:: duration %s\n", task, formatDuration(time.Since(taskStart))) + } } return nil } @@ -314,6 +323,18 @@ func (exec *Executor) VerifyTasks(tasks []string) error { return nil } +func formatDuration(d time.Duration) string { + if d < time.Second { + return fmt.Sprintf("%dms", d.Milliseconds()) + } + if d < time.Minute { + return fmt.Sprintf("%.2fs", d.Seconds()) + } + m := int(d.Minutes()) + s := d.Seconds() - float64(m*60) + return fmt.Sprintf("%dm%.2fs", m, s) +} + func filterTasks(tasks *map[string]Task, regex *regexp.Regexp) map[string]Task { filtered := make(map[string]Task) for k, v := range *tasks {