Previously the gitlab output wrapped each command individually, causing
two visible bugs in real GitLab pipelines:
- every section displayed a duration of 00:00, because start and end
markers were emitted microseconds apart for instant commands
- the `task: [NAME] CMD` announcement lines were rendered outside the
sections, because Logger.Errf bypassed the cmd-level wrapper
Fix by wrapping output at the task level via a new optional
[output.TaskWrapper] interface that GitLab implements. Task-scoped
writers are threaded via ctx so nested `task:` invocations produce
properly nested sections (GitLab supports this natively), and deps
running in parallel each get their own buffer with mutex-protected
flushes into the parent's buffer.
- `internal/output/output.go`: add TaskWrapper interface
- `internal/output/gitlab.go`: logic moved from WrapWriter to WrapTask;
WrapWriter becomes passthrough; sync.Mutex around the buffer for
concurrent flushes from parallel sub-task sections
- `task_output.go` (new): ctx plumbing + helpers kept out of task.go
- `task.go`: 7 lines of surgical edits — name the lambda's error
return, wrap before the cmd loop, defer the closer with the final
error, and swap the cmd announcement to `printCmdAnnouncement` which
writes into the task-scoped stderr
Move the prompt for required variables AFTER the if condition check.
This avoids asking the user for input when the task won't run anyway.
The order in RunTask() is now:
1. FastCompiledTask
2. Check required vars early (non-interactive mode only)
3. CompiledTask (resolve dynamic vars)
4. Check if condition → exit early if false
5. Prompt for missing vars (only if task will run)
6. Validate required vars
Previously if a task was run as a dependency of another task,
the error message simply reported something like:
exit status 1
It is desirable instead to name the root task and all child tasks in the tree
to the failing task.
After this PR, the error message will read:
task: Failed to run task "root": task: Failed to run task "failing-task": exit status 1
* refactor: executor functional options
* refactor: minor tidy up of list code
* fix: WithVersionCheck missing from call to NewExecutor
* feat: docstrings for structs with functional options
* refactor: prefix the functional options with the name of the struct they belong to
* feat: update minimum version to 1.22
* refactor: use int range iterator
* refactor: loop variables
* refactor: replace slicesext.FirstNonZero with cmp.Or
* refactor: use slices.Concat instead of append
* fix: unused param
* fix: linting