mirror of
https://github.com/go-task/task.git
synced 2026-07-01 16:44:34 +00:00
feat: add command-level timeout support
Add a per-command `timeout` option that terminates a command once it exceeds the given duration, preventing commands from hanging indefinitely in a pipeline. Uses Go duration syntax (e.g. 30s, 5m, 1h30m) and applies to both shell commands and task calls. Closes #1569
This commit is contained in:
12
task.go
12
task.go
@@ -376,12 +376,21 @@ func (e *Executor) runCommand(ctx context.Context, t *ast.Task, call *Call, i in
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.Timeout > 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, cmd.Timeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
switch {
|
||||
case cmd.Task != "":
|
||||
reacquire := e.releaseConcurrencyLimit()
|
||||
defer reacquire()
|
||||
|
||||
err := e.RunTask(ctx, &Call{Task: cmd.Task, Vars: cmd.Vars, Silent: cmd.Silent, Indirect: true})
|
||||
if err != nil && ctx.Err() == context.DeadlineExceeded {
|
||||
return fmt.Errorf("task: [%s] command timeout exceeded (%s): %w", t.Name(), cmd.Timeout, err)
|
||||
}
|
||||
var exitCode interp.ExitStatus
|
||||
if errors.As(err, &exitCode) && cmd.IgnoreError {
|
||||
e.Logger.VerboseErrf(logger.Yellow, "task: [%s] task error ignored: %v\n", t.Name(), err)
|
||||
@@ -426,6 +435,9 @@ func (e *Executor) runCommand(ctx context.Context, t *ast.Task, call *Call, i in
|
||||
if closeErr := closer(err); closeErr != nil {
|
||||
e.Logger.Errf(logger.Red, "task: unable to close writer: %v\n", closeErr)
|
||||
}
|
||||
if err != nil && ctx.Err() == context.DeadlineExceeded {
|
||||
return fmt.Errorf("task: [%s] command timeout exceeded (%s): %w", t.Name(), cmd.Timeout, err)
|
||||
}
|
||||
var exitCode interp.ExitStatus
|
||||
if errors.As(err, &exitCode) && cmd.IgnoreError {
|
||||
e.Logger.VerboseErrf(logger.Yellow, "task: [%s] command error ignored: %v\n", t.Name(), err)
|
||||
|
||||
Reference in New Issue
Block a user