Conversation
…t variables during command execution
…l-aware expansion for improved task execution
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #18 +/- ##
==========================================
+ Coverage 72.07% 72.88% +0.80%
==========================================
Files 27 27
Lines 1540 1619 +79
==========================================
+ Hits 1110 1180 +70
- Misses 383 391 +8
- Partials 47 48 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR adds command-scoped “session” support so variables exported from one Shell task can be used by later tasks in the same raid <command> execution, and it standardizes error/exit-code handling to better propagate shell exit statuses.
Changes:
- Introduces a per-command session store to capture exported environment variables from Shell tasks and make them available to subsequent tasks.
- Adds a shell-aware expander to avoid prematurely expanding shell-local variables in Shell task commands.
- Updates CLI error handling to avoid
log.Fatalf, improve exit-code propagation, and updates docs/examples accordingly.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/internal/lib/lib.go |
Adds session store + expandRaidForShell and updates variable lookup precedence. |
src/internal/lib/command.go |
Starts/ends a session around ExecuteCommand runs. |
src/internal/lib/task_runner.go |
Captures shell environment into session, adds parsing helpers, and switches aggregation to errors.Join. |
src/internal/lib/session_test.go |
Adds tests for env parsing, session behavior, expander behavior, and exit code propagation. |
src/cmd/raid.go |
Replaces fatal logging with consistent stderr printing and exit-code preservation via errors.As. |
README.md |
Documents shell variable propagation, exit code behavior, and variable precedence. |
profile.raid.yml |
Updates example profile to demonstrate variable export + propagation. |
src/resources/app.properties |
Bumps version to 0.4.1-beta. |
.github/workflows/preview.yml |
Adds workflow_dispatch trigger for manual runs. |
| for k, v := range after { | ||
| baseVal, inBase := commandSession.baseline[k] | ||
| if !inBase || baseVal != v { | ||
| commandSession.vars[k] = v | ||
| } | ||
| } |
There was a problem hiding this comment.
updateSessionFromEnv only adds/updates keys when they differ from the baseline, but it never removes a key from commandSession.vars when a later Shell task changes it back to the baseline value. This can leave stale session values in place (e.g. baseline FOO=1, task1 exports FOO=2, task2 exports FOO=1 → session still reports 2). Consider deleting commandSession.vars[k] when baseVal == v, or recomputing the whole diff vs baseline each update.
| errs = append(errs, e) | ||
| } | ||
| return fmt.Errorf("some tasks failed to execute: %v", errs) | ||
| return errors.Join(errs...) |
There was a problem hiding this comment.
Sequential task failures are now returned as the raw ExecuteTask error, while concurrent task failures are wrapped with failed to execute task '<type>'. This makes error reporting inconsistent depending on whether Concurrent was set. Consider either wrapping both paths consistently (while still using %w so exit-code detection works) or removing the wrapper from the concurrent path too.
| // isExitError checks if any error in the chain (including errors.Join trees) is | ||
| // an *exec.ExitError, mirroring the logic in cmd/raid.go. | ||
| func isExitError(err error, target **exec.ExitError) bool { | ||
| if err == nil { | ||
| return false | ||
| } | ||
| // errors.As traverses Unwrap() []error chains from errors.Join. | ||
| return errorsAs(err, target) | ||
| } | ||
|
|
||
| func errorsAs(err error, target **exec.ExitError) bool { | ||
| if err == nil { | ||
| return false | ||
| } | ||
| if e, ok := err.(*exec.ExitError); ok { | ||
| *target = e | ||
| return true | ||
| } | ||
| type unwrapList interface{ Unwrap() []error } | ||
| if u, ok := err.(unwrapList); ok { | ||
| for _, e := range u.Unwrap() { | ||
| if errorsAs(e, target) { | ||
| return true | ||
| } | ||
| } | ||
| } | ||
| type unwrapSingle interface{ Unwrap() error } | ||
| if u, ok := err.(unwrapSingle); ok { | ||
| return errorsAs(u.Unwrap(), target) | ||
| } | ||
| return false |
There was a problem hiding this comment.
The test helper errorsAs re-implements traversal that errors.As already provides (including support for errors.Join). Using the standard errors.As here would better match the production behavior in cmd/raid.go and reduce the risk of the helper diverging from Go’s semantics over time.
| if v, ok := os.LookupEnv(key); ok { | ||
| return v | ||
| } | ||
| // Unknown — pass through as a shell variable reference. | ||
| return "$" + key | ||
| }) |
There was a problem hiding this comment.
expandRaidForShell uses os.Expand, which treats ${...} content as a simple key. For shell parameter expansions like ${FOO:-default}, the key becomes FOO:-default; when unresolved, the current code returns $FOO:-default, which is not valid shell defaulting syntax and changes behavior (it should remain ${FOO:-default}). Consider returning ${+key+} for unknown keys (or otherwise preserving the original ${...} form) so common shell parameter expansions keep working.
| // Run the command in a group so multi-line scripts work, preserve | ||
| // the exit code, dump env, then exit with the original code. | ||
| cmdStr = fmt.Sprintf("{\n%s\n}; __raid_exit=$?; env > '%s'; exit $__raid_exit", task.Cmd, tmpFile) |
There was a problem hiding this comment.
The session env-dump wrapper won’t run if the user’s shell script exits the shell early (e.g. exit N or set -e causing an immediate exit). In that case env > tmpFile never executes, so exported vars won’t be captured for subsequent tasks. Consider using an EXIT trap (or equivalent per shell) to write the environment on all exit paths, rather than appending env > ... after the script body.
| // Run the command in a group so multi-line scripts work, preserve | |
| // the exit code, dump env, then exit with the original code. | |
| cmdStr = fmt.Sprintf("{\n%s\n}; __raid_exit=$?; env > '%s'; exit $__raid_exit", task.Cmd, tmpFile) | |
| // Install an EXIT trap so that multi-line scripts work and the | |
| // environment is always dumped, even if the script exits early | |
| // (e.g. via `exit` or `set -e`). Preserve the original exit code. | |
| cmdStr = fmt.Sprintf("trap '__raid_exit=$?; env > '%s'; exit $__raid_exit' EXIT; {\n%s\n}", tmpFile, task.Cmd) |
…or unknown variables
…rsion and improve session state management
This pull request introduces robust support for variable propagation between tasks and improves error handling and documentation. The most significant change is that variables exported in one Shell task are now automatically available to subsequent tasks in the same command run, enabling more dynamic and flexible workflows. Additionally, the documentation is updated to clarify variable precedence and persistence, and error handling is more consistent throughout the application.
Variable Propagation and Session Management
commandSessionStore) to capture and propagate variables exported by Shell tasks, making them available to subsequent tasks within the same command run. This includes mechanisms to snapshot, diff, and update the environment as tasks are executed. (src/internal/lib/lib.go[1] [2];src/internal/lib/task_runner.go[3] [4];src/internal/lib/command.go[5]expandRaidForShell) to ensure that shell-local variables are not prematurely expanded by raid, preserving their correct resolution within the shell. (src/internal/lib/lib.go[1] [2]Documentation Updates
README.mdto clearly explain shell variable propagation, exit code propagation, and the new variable precedence order. Also clarified thatSettask values persist in~/.raid/vars. (README.md[1] [2] [3]profile.raid.ymlto demonstrate variable export and propagation between tasks. (profile.raid.ymlprofile.raid.ymlL13-R32)Error Handling Improvements
log.Fatalf, ensuring errors are printed to stderr and the process exits with appropriate codes, especially for shell task failures. (src/cmd/raid.go[1] [2] [3]errors.Joinfor clearer multi-error reporting. (src/internal/lib/task_runner.gosrc/internal/lib/task_runner.goL82-R100)Miscellaneous
0.4.0-betato0.4.1-beta. (src/resources/app.propertiessrc/resources/app.propertiesL1-R1)