Skip to content

Implement session management and enhance command execution handling#18

Merged
8bitAlex merged 9 commits intomainfrom
preview
Mar 19, 2026
Merged

Implement session management and enhance command execution handling#18
8bitAlex merged 9 commits intomainfrom
preview

Conversation

@8bitAlex
Copy link
Copy Markdown
Owner

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

  • Introduced a session store (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]
  • Added a shell-aware variable expander (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

  • Updated the README.md to clearly explain shell variable propagation, exit code propagation, and the new variable precedence order. Also clarified that Set task values persist in ~/.raid/vars. (README.md [1] [2] [3]
  • Enhanced the example in profile.raid.yml to demonstrate variable export and propagation between tasks. (profile.raid.yml profile.raid.ymlL13-R32)

Error Handling Improvements

  • Standardized error handling by removing direct use of 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]
  • Improved task runner error aggregation by using errors.Join for clearer multi-error reporting. (src/internal/lib/task_runner.go src/internal/lib/task_runner.goL82-R100)

Miscellaneous

Copilot AI review requested due to automatic review settings March 19, 2026 20:41
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 19, 2026

Codecov Report

❌ Patch coverage is 88.54167% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.88%. Comparing base (0c8ecff) to head (f07f299).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/cmd/raid.go 0.00% 9 Missing ⚠️
src/internal/lib/lib.go 94.87% 1 Missing and 1 partial ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +204 to +209
for k, v := range after {
baseVal, inBase := commandSession.baseline[k]
if !inBase || baseVal != v {
commandSession.vars[k] = v
}
}
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread src/internal/lib/task_runner.go Outdated
Comment on lines +75 to +87
errs = append(errs, e)
}
return fmt.Errorf("some tasks failed to execute: %v", errs)
return errors.Join(errs...)
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +333 to +363
// 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
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread src/internal/lib/lib.go
Comment on lines +150 to +155
if v, ok := os.LookupEnv(key); ok {
return v
}
// Unknown — pass through as a shell variable reference.
return "$" + key
})
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread src/internal/lib/task_runner.go Outdated
Comment on lines +167 to +169
// 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)
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
// 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)

Copilot uses AI. Check for mistakes.
@8bitAlex 8bitAlex merged commit f3944d6 into main Mar 19, 2026
7 checks passed
@8bitAlex 8bitAlex deleted the preview branch March 19, 2026 21:26
@8bitAlex 8bitAlex restored the preview branch March 20, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants