Skip to content

Task runner#5

Merged
8bitAlex merged 43 commits into
mainfrom
task-runner
Mar 14, 2026
Merged

Task runner#5
8bitAlex merged 43 commits into
mainfrom
task-runner

Conversation

@8bitAlex
Copy link
Copy Markdown
Owner

@8bitAlex 8bitAlex commented Mar 13, 2026


Title: Task runner, custom commands, and cross-platform support


Summary

This PR is a major feature addition and hardening pass. It introduces a full task runner with 12 task types, user-defined CLI commands that register as first-class raid subcommands, and cross-platform compatibility fixes for Linux, macOS, and Windows.

Task Runner

Adds a composable task execution engine with the following task types:

  • Shell — run a command string in a configurable shell
  • Script — execute a script file directly or with a runner
  • HTTP — download a file from a URL
  • Wait — poll an HTTP or TCP endpoint until it responds
  • Template — render a file with environment variable substitution
  • Git — run git operations (pull, fetch, checkout, reset)
  • Prompt — prompt the user for input and set an env var
  • Confirm — ask the user for yes/no confirmation
  • Print — print a colored or plain message
  • Group — execute a named group of tasks sequentially
  • Parallel — execute a named group of tasks concurrently
  • Retry — retry a named group of tasks on failure

All task types support an optional condition guard (platform, file exists, command exit code) and concurrent flag. Shell tasks accept an optional path field for working directory, defaulting to ~ for profile-context tasks and the repo directory for repo-context tasks.

Custom Commands

Profiles and repos can now define named commands under a commands: key. Each command registers as a top-level raid <name> subcommand at startup. Profile commands take priority over repo commands on name conflicts.

commands:
  - name: build
    usage: Build all services
    tasks:
      - type: Shell
        cmd: make build
    out:
      stdout: true
      stderr: true
      file: build.log

Cross-Platform Fixes

  • Shell resolution uses names from PATH (bash, sh, zsh) instead of hardcoded Unix paths (/bin/bash etc.) — works on Windows via Git Bash
  • PowerShell invocation now includes the required -Command flag
  • path.Dir  filepath.Dir in directory creation (Windows path separator correctness)
  • os.MkdirAll permissions cleaned up (os.ModeDir|0755  0755)
  • Path construction uses filepath.Join throughout instead of manual string concatenation

Test Coverage

Full test suite added across all new and existing packages — task runner, commands, profiles, repos, environments, config, sys, and utils. Tests use cross-platform shell commands (exit 0/1, echo done >) instead of Unix-specific builtins (touch, true, false).

Copilot AI review requested due to automatic review settings March 13, 2026 22:47
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 13, 2026

Codecov Report

❌ Patch coverage is 81.75766% with 137 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.62%. Comparing base (5feb4a1) to head (ad9488b).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/internal/lib/lib.go 63.88% 24 Missing and 15 partials ⚠️
src/cmd/env/env.go 0.00% 19 Missing ⚠️
src/cmd/raid.go 30.76% 16 Missing and 2 partials ⚠️
src/internal/lib/task_runner.go 95.04% 11 Missing and 6 partials ⚠️
src/raid/raid.go 0.00% 8 Missing ⚠️
src/cmd/profile/add.go 0.00% 6 Missing ⚠️
src/internal/sys/system.go 88.00% 6 Missing ⚠️
src/internal/lib/config.go 68.75% 3 Missing and 2 partials ⚠️
src/internal/lib/repo.go 87.87% 2 Missing and 2 partials ⚠️
src/internal/utils/common.go 76.47% 2 Missing and 2 partials ⚠️
... and 4 more
Additional details and impacted files
@@            Coverage Diff             @@
##            main       #5       +/-   ##
==========================================
+ Coverage   0.00%   75.62%   +75.62%     
==========================================
  Files          1       23       +22     
  Lines          2     1116     +1114     
==========================================
+ Hits           0      844      +844     
- Misses         2      235      +233     
- Partials       0       37       +37     

☔ 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 introduces a task execution engine and custom command system to Raid, expanding profile/repo configuration (schemas + merging) and hardening cross-platform path/env handling across the CLI and core libraries.

Changes:

  • Added a multi-type task runner (Shell/Script/HTTP/Wait/Template/Git/Prompt/Confirm/Print/Group/Parallel/Retry) with conditions and concurrency support.
  • Added profile/repo-defined custom commands that register as first-class raid <name> subcommands, plus command output routing options.
  • Updated schemas, docs, and introduced broad unit test coverage across lib/sys/utils/cmd packages.

Reviewed changes

Copilot reviewed 39 out of 40 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/raid/raid.go Exposes new lib APIs (commands) and loads repo .env files during initialization.
src/internal/utils/common.go Adds shared helpers (error merge, YAML→JSON conversion).
src/internal/utils/common_test.go Tests for new utils helpers.
src/internal/utils/cobra_ext_test.go Tests for cobra positional-arg utility behavior.
src/internal/utils/Common.go Removes prior MergeErr implementation (file rename/restructure).
src/internal/sys/system.go Adds cross-platform helpers (platform detection, path expansion, token splitting, file utilities).
src/internal/sys/system_test.go Adds tests for sys helpers (platform/home/path expansion/file creation).
src/internal/lib/task.go Introduces task/condition models and task-type enum.
src/internal/lib/task_test.go Unit tests for task helpers (IsZero/ToLower/Expand).
src/internal/lib/task_runner.go Implements task execution engine and executors for each task type.
src/internal/lib/task_runner_test.go Primary coverage for task runner behavior across task types.
src/internal/lib/task_runner_extra_test.go Additional branch/error-path coverage for task runner.
src/internal/lib/repo.go Adds repo install/commands support, repo config parsing, repo schema validation.
src/internal/lib/repo_test.go Tests repo parsing/validation/clone/build merge behavior.
src/internal/lib/profile.go Expands profile model (install/groups/commands) and routes schema validation via shared helper.
src/internal/lib/profile_test.go Tests profile parsing (YAML/JSON, multi-doc), registration, and validation flows.
src/internal/lib/lib.go Adds shared schema validation helper and integrates install tasks + repo command merging.
src/internal/lib/lib_test.go Adds foundational tests for Load/ForceLoad/install/schema validation and command merging.
src/internal/lib/env.go Adds env task execution, .env writing/loading, and path handling improvements.
src/internal/lib/env_test.go Tests env switching, .env write/load behavior, and env task execution.
src/internal/lib/config.go Improves config path construction using filepath.Join.
src/internal/lib/config_test.go Adds tests around config initialization/persistence.
src/internal/lib/command.go Implements custom command execution + output routing and command merge strategy.
src/internal/lib/command_test.go Tests command discovery/execution and output routing behavior.
src/cmd/raid.go Pre-initializes to dynamically register custom commands; adds config-flag pre-scan.
src/cmd/raid_test.go Tests --config/-c pre-scan behavior.
src/cmd/profile/remove.go Removes no-op trailing fmt.Print().
src/cmd/profile/list.go Removes no-op trailing fmt.Print().
src/cmd/profile/add.go Removes no-op trailing fmt.Print().
src/cmd/install/install.go Simplifies threads flag backing variable.
src/cmd/env/list.go Removes no-op trailing fmt.Print().
src/cmd/env/env.go Improves control flow and error handling when switching/executing environments.
schemas/raid-repo.schema.json Extends repo schema with install + commands.
schemas/raid-profile.schema.json Extends profile schema with install + groups + commands.
schemas/raid-defs.schema.json Adds definitions for new task types, conditions, install, and commands.
go.mod Reorders/updates module requirements list (adds godotenv entry in main require block).
docs/examples/hello.sh Adds shebang + updated message for script example.
docs/examples/example.raid.yaml Updates example to demonstrate new fields (shell/literal/runner/concurrent/install).
README.md Major documentation refresh covering tasks, commands, config examples, and best practices.
.gitignore Ignores AI assistant-related files/directories.

Comment thread src/internal/lib/task_runner.go Outdated
Comment thread src/internal/lib/lib.go
Comment thread docs/examples/example.raid.yaml
Comment thread src/cmd/raid.go
Comment thread src/internal/utils/common.go
Comment thread src/internal/lib/task_runner_test.go
Comment thread src/internal/sys/system.go Outdated
Comment thread src/raid/raid.go
Comment thread README.md Outdated
Comment thread src/internal/lib/task.go Outdated
@8bitAlex 8bitAlex requested a review from Copilot March 13, 2026 23:25
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 introduces a first-class task runner and user-defined commands to the Raid CLI, while also hardening config/schema validation and improving cross-platform behavior (Linux/macOS/Windows).

Changes:

  • Added a composable task execution engine (multiple task types + conditions + concurrency) and wiring for running tasks from profiles/repos.
  • Added profile/repo-defined custom commands that register as raid <name> subcommands at startup.
  • Improved cross-platform path/shell handling, embedded JSON schema validation, and expanded automated test coverage/CI coverage reporting.

Reviewed changes

Copilot reviewed 43 out of 44 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/raid/raid.go Exposes commands + env loading during init
src/internal/utils/common.go Adds shared MergeErr/YAMLToJSON helpers
src/internal/utils/common_test.go Tests common utils helpers
src/internal/utils/cobra_ext_test.go Tests MatchOne cobra args helper
src/internal/utils/Common.go Removes old MergeErr implementation
src/internal/sys/system.go Cross-platform path, platform, file helpers
src/internal/sys/system_test.go Tests sys utilities (paths, platform, files)
src/internal/lib/task.go Adds Task/Condition types and expansion
src/internal/lib/task_test.go Tests Task helpers/expansion
src/internal/lib/task_runner.go Implements task runner + task executors
src/internal/lib/task_runner_test.go Large task runner test suite
src/internal/lib/task_runner_extra_test.go Extra error-path coverage for runner
src/internal/lib/schemas/raid-defs.schema.json Adds task/command/install/group schema defs
src/internal/lib/schemas/raid-profile.schema.json Updates embedded profile schema
src/internal/lib/schemas/raid-repo.schema.json Updates embedded repo schema
src/internal/lib/repo.go Repo parsing/validation + merges install/commands
src/internal/lib/repo_test.go Tests repo extraction/validation/clone/build
src/internal/lib/profile.go Profile validation/extraction + schema pipeline
src/internal/lib/profile_test.go Tests profile CRUD/extraction/validation
src/internal/lib/command.go Implements custom command execution + output
src/internal/lib/command_test.go Tests command resolution/output behaviors
src/internal/lib/env.go Adds env task execution + .env load support
src/internal/lib/env_test.go Tests env execution and .env handling
src/internal/lib/config.go Robust config path creation + filepath usage
src/internal/lib/config_test.go Tests config init and viper persistence
src/internal/lib/lib.go Embeds schemas + load/install orchestration
src/internal/lib/lib_test.go Broad tests for lib load/install/schema validation
src/cmd/raid.go Pre-init + dynamic subcommand registration
src/cmd/raid_test.go Tests config flag pre-scan logic
src/cmd/profile/add.go Removes stray prints; uses validation/unmarshal
src/cmd/profile/list.go Removes stray prints
src/cmd/profile/remove.go Removes stray prints
src/cmd/install/install.go Simplifies threads flag var
src/cmd/env/env.go Improves env command flow + error handling
src/cmd/env/list.go Removes stray prints
schemas/raid-defs.schema.json Updates repo-root schema defs
schemas/raid-profile.schema.json Updates repo-root profile schema
schemas/raid-repo.schema.json Updates repo-root repo schema
docs/examples/hello.sh Adds shebang + updated message
docs/examples/example.raid.yaml Updates example tasks + install section
README.md Major docs refresh: tasks/commands/examples
go.mod Reorders requirements (no semantic change)
.gitignore Ignores assistant-related files
.github/workflows/codecov.yml Ensures Go setup + atomic coverage across ./...

Comment thread src/internal/lib/lib.go Outdated
Comment thread src/internal/lib/lib.go
… to Groups

- validateFile now detects top-level JSON arrays and validates each element
  individually, matching extractProfilesFromJSON which supports both single-
  object and array-of-objects profile files
- ForceLoad now applies withDefaultDir to profile.Groups so Shell tasks
  inside Group/Parallel/Retry tasks use the home dir as default working
  directory, consistent with Commands tasks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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 introduces a task runner and profile-defined custom commands that register as first-class raid <name> subcommands, while hardening cross-platform path/shell behavior and adding broad test coverage and schema validation updates.

Changes:

  • Add a task execution engine (Shell/Script/HTTP/Wait/Template/Git/Prompt/Confirm/Print/Group/Parallel/Retry) with conditions, concurrency, and default working-dir handling.
  • Add profile/repo commands: support and register them dynamically in the Cobra CLI at startup.
  • Improve cross-platform filesystem/path handling, embed JSON schemas for validation, and add extensive tests + docs/schema updates.

Reviewed changes

Copilot reviewed 43 out of 44 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/raid/raid.go Exposes new command APIs from internal/lib and loads .env files during initialization.
src/internal/utils/common.go Adds shared helpers (MergeErr, YAMLToJSON) in a consistently named file.
src/internal/utils/common_test.go Adds unit tests for MergeErr and YAMLToJSON.
src/internal/utils/cobra_ext_test.go Adds tests for MatchOne positional-arg combiner behavior.
src/internal/utils/Common.go Removes legacy MergeErr implementation (replaced by common.go).
src/internal/sys/system.go Adds platform detection, safer path expansion, file creation, existence checks, and input splitting.
src/internal/sys/system_test.go Adds tests for new sys helpers (platform, path expansion, file ops, splitting).
src/internal/lib/task.go Introduces Task, TaskType, and Condition models plus env-expansion helpers.
src/internal/lib/task_test.go Adds unit tests for task zero-ness and expansion behavior.
src/internal/lib/task_runner.go Implements task execution dispatch, concurrency, conditions, and task type executors.
src/internal/lib/task_runner_test.go Adds a comprehensive task-runner test suite (shell/script/http/wait/template/group/etc.).
src/internal/lib/task_runner_extra_test.go Adds extra branch/error-path coverage for task runner helpers.
src/internal/lib/schemas/raid-defs.schema.json Adds/updates embedded schema definitions for tasks/environments/install/commands.
src/internal/lib/schemas/raid-profile.schema.json Adds embedded profile schema updates (install/groups/commands).
src/internal/lib/schemas/raid-repo.schema.json Adds embedded repo schema updates (install/commands).
src/internal/lib/repo.go Extends repo model (branch/install/commands), adds repo schema validation + parsing, and branch-aware clone.
src/internal/lib/repo_test.go Adds coverage for repo extraction/validation/build/clone behaviors.
src/internal/lib/profile.go Updates profile model to include install/groups/commands and switches to embedded-schema validation.
src/internal/lib/profile_test.go Adds tests for profile CRUD + extraction + schema validation paths.
src/internal/lib/lib.go Embeds schemas, adds multi-doc YAML + JSON-array validation, merges repo commands, and runs install tasks.
src/internal/lib/lib_test.go Adds tests for load/forceload/schema validation/install flows and command merging.
src/internal/lib/env.go Adds env execution (write .env, run env tasks) and .env loading across repos.
src/internal/lib/env_test.go Adds tests for env selection, .env writing/loading, and env task execution.
src/internal/lib/config.go Improves config-file creation with filepath joins + proper error propagation.
src/internal/lib/config_test.go Adds tests for config initialization and persistence via viper.
src/internal/lib/command.go Implements custom command execution with optional output routing/suppression.
src/internal/lib/command_test.go Adds tests for command lookup/execution and output routing behavior.
src/cmd/raid.go Pre-initializes Raid before Cobra arg parsing to register dynamic subcommands; adds config pre-scan.
src/cmd/raid_test.go Tests pre-scan config flag handling (applyConfigFlag).
src/cmd/profile/remove.go Removes stray no-op fmt.Print() call.
src/cmd/profile/list.go Removes stray no-op fmt.Print() call.
src/cmd/profile/add.go Removes stray no-op fmt.Print() call.
src/cmd/install/install.go Simplifies maxThreads var declaration.
src/cmd/env/list.go Removes stray no-op fmt.Print() call.
src/cmd/env/env.go Refactors env command flow to return early on errors and handle ForceLoad errors.
schemas/raid-defs.schema.json Updates top-level (non-embedded) schema docs to match new task/command/install features.
schemas/raid-profile.schema.json Updates top-level profile schema to include install/groups/commands.
schemas/raid-repo.schema.json Updates top-level repo schema to include install/commands.
go.mod Reorders/normalizes module requirements (no functional change).
docs/examples/hello.sh Adds shebang and updates sample output.
docs/examples/example.raid.yaml Updates example to include more task fields and install tasks.
README.md Major documentation refresh covering tasks, commands, install/groups, and configuration guidance.
.gitignore Ignores AI assistant files.
.github/workflows/codecov.yml Ensures Go setup and uses atomic covermode + ./... for coverage.

Comment thread src/cmd/raid.go
Comment thread src/internal/lib/lib.go
Comment thread src/internal/lib/task_runner_test.go Outdated
@8bitAlex
Copy link
Copy Markdown
Owner Author

@claude

@claude
Copy link
Copy Markdown

claude Bot commented Mar 14, 2026

Claude finished @8bitAlex's task in 2m 15s —— View job


PR Review: Task Runner, Custom Commands & Cross-Platform Support

This is a substantial PR with well-structured code. Here are my findings, organized by severity.


Critical Bugs

1. Race condition on global output writers (src/internal/lib/task_runner.go:21-24, command.go:56-67)

commandStdout and commandStderr are package-level globals. runCommand temporarily swaps them and restores via defer. If a custom command with Out configured triggers concurrent tasks (via ExecuteTasks with task.Concurrent=true), goroutines share the same globals and will race when reading/writing them. This is a data race that won't be caught by tests unless -race is used.

Suggested fix: pass stdout/stderr io.Writer parameters down the call stack rather than mutating globals. Fix this →

2. Empty YAML passes schema validation (src/internal/lib/lib.go:217-238)

validateFile iterates a YAML decoder, breaking on io.EOF. For an empty file, it breaks immediately without validating anything and returns nil. An empty config silently passes schema validation even when the schema requires fields like name.

// Current: loop exits on first EOF, never validated → returns nil
for {
    var raw any
    if err := dec.Decode(&raw); err != nil {
        if err == io.EOF { break }  // ← returns nil for empty file
        return err
    }
    // ... validate raw
}

Fix this →


Important Issues

3. Write() panics instead of propagating errors (src/internal/lib/config.go:61)

func Write() {
    if err := viper.WriteConfig(); err != nil {
        panic(err)  // ← should return error
    }
}

Set() calls Write() silently and can't surface this failure. panic is inappropriate for an I/O error like a full disk or lost permissions. Fix this →

4. clone() bypasses output routing (src/internal/lib/repo.go:107-108)

func clone(path string, url string, branch string) error {
    cmd.Stdout = os.Stdout  // ← bypasses commandStdout
    cmd.Stderr = os.Stderr  // ← bypasses commandStderr
    return cmd.Run()
}

Git clone output can't be suppressed or captured by a command's out configuration. Should use commandStdout/commandStderr (or ideally, the writer parameters from fix #1).

5. setEnvVariablesForRepos prints to os.Stdout directly (src/internal/lib/env.go:86)

fmt.Printf("Setting up environment for repo: %s\n", repo.Name)

Should use fmt.Fprintf(commandStdout, ...) for consistent output routing.

6. applyConfigFlag doesn't handle -c=value shorthand form (src/cmd/raid.go:76-78)

The function handles --config=value but not -c=value. This is a subtle CLI behavior gap since cobra supports both forms. Fix this →

7. ForceLoad doesn't apply withDefaultDir to install tasks for repos (src/internal/lib/lib.go:70-79)

Repo install tasks get withDefaultDir applied in Install() (lib.go:138), but ForceLoad only applies it to command tasks. If install tasks are ever run outside of Install(), they'll execute from the caller's CWD. This is an easy source of future bugs.


Minor Issues

8. SplitInput doesn't handle single quotes (src/internal/sys/system.go:77)

The TODO comment acknowledges this. Worth noting: execShell passes the entire cmd string to the shell's -c flag as one argument, so SplitInput is not used for shell commands (which is correct). Double-check whether SplitInput is used anywhere that single-quoted paths could appear.

9. execGroup/execParallel/execRetry require non-nil context.Profile.Groups (task_runner.go:345,465,504)

All three return a generic "no groups defined in the active profile" error if context is nil. The nil-context check was added to ExecuteEnv, but Group/Parallel/Retry will still panic if context is nil and somehow reached (would only happen via test code). Low risk in practice, but worth a guard.

10. validateFile handles JSON arrays for profiles but not YAML arrays (src/internal/lib/lib.go:246-265)

The JSON path detects a top-level array and validates each element. The YAML path validates each document in a multi-doc stream. But a YAML file containing a list (- name: ...) would be treated as a single document and fail schema validation if the schema doesn't allow arrays at root. Verify the schema covers this case.


What's Done Well

  • The embedded schema approach (//go:embed schemas/*.json) is a clean solution to the CWD-relative schema path problem that the original ValidateSchema had.
  • mergeCommands with profile-priority semantics is simple and correct.
  • The withDefaultDir helper is a clean way to apply directory defaults without mutating the original task slice.
  • applyConfigFlag pre-scan approach cleanly solves the chicken-and-egg problem of needing config before cobra parses args.
  • The getShell function correctly prefers pwsh over powershell on non-Windows platforms.
  • Test coverage at 84.8% patch coverage for a PR this size is solid.

8bitAlex and others added 7 commits March 13, 2026 19:38
test -n is a POSIX shell built-in unavailable in cmd.exe on Windows,
causing the test to fail in the windows-latest CI matrix.
exit 0 is universally available in both cmd and POSIX shells.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
An empty YAML file produced zero decode iterations, so validateFile
returned nil even when the schema required fields like 'name'. Track
the document count and return an error when the stream contains no
documents.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously applyConfigFlag missed the -c=value shorthand form and would
continue scanning positional args after a -- end-of-flags marker, risking
picking up the wrong config path or treating positional args as flags.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
config.Write() panicked on viper.WriteConfig failure, which crashes
the process instead of letting callers handle the error. Changed Write()
and Set() to return error, and propagated through SetProfile, AddProfile,
AddProfiles, RemoveProfile, and SetEnv.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A Condition task's Cmd ran with inherited stdout/stderr, polluting
the terminal output with the condition check's output. Condition
evaluation is a boolean probe — its output is noise to the user.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
os.Create fails when the parent directory does not exist. Added
MkdirAll before creating the output file, matching the behaviour
of the HTTP download task. Updated the test to use a path whose
parent is a regular file so MkdirAll itself fails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
checkHTTP returned nil for any HTTP response including 4xx/5xx,
causing execWait to consider a server that is returning errors as
ready and stop waiting prematurely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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 introduces a full task runner and custom command system to Raid, expanding the CLI’s orchestration capabilities and hardening cross-platform behavior (Linux/macOS/Windows).

Changes:

  • Added a multi-type task execution engine (shell/script/http/wait/template/git/prompt/confirm/print/group/parallel/retry) with conditions and concurrency support.
  • Added profile/repo-defined custom commands that register as first-class raid <name> subcommands at startup.
  • Updated JSON schema validation to use embedded schemas and expanded schema definitions; added extensive test coverage and some cross-platform path fixes.

Reviewed changes

Copilot reviewed 44 out of 45 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/internal/lib/task_runner.go Implements the task runner, task dispatch, concurrency handling, and condition evaluation.
src/internal/lib/task.go Adds Task/Condition models and task type normalization/expansion.
src/internal/lib/command.go Adds custom command execution with configurable output routing.
src/cmd/raid.go Pre-initializes Raid to dynamically register custom commands as cobra subcommands.
src/internal/lib/lib.go Embeds schemas and centralizes schema validation; merges repo commands and applies default working directories.
schemas/raid-.schema.json + src/internal/lib/schemas/raid-.schema.json Expands schema definitions for tasks, commands, groups, repo/profile installs.
src/internal/sys/system.go Adds platform detection, safer path expansion, and more portable file creation helpers.
Tests (multiple *_test.go) Adds broad coverage for tasks, commands, env/profile/repo/config behavior.
README.md Updates documentation to describe tasks, commands, install/env flows, and configuration format.

Comment thread schemas/raid-defs.schema.json Outdated
Comment thread src/internal/lib/schemas/raid-defs.schema.json Outdated
Comment thread src/internal/lib/task_runner.go
Comment thread src/internal/lib/task_runner.go
Comment thread src/internal/lib/task_runner.go
Comment thread src/raid/raid.go
Comment thread src/cmd/raid.go
8bitAlex and others added 6 commits March 13, 2026 20:11
getShell() accepts "pwsh" and "ps" as aliases for PowerShell, but
neither schema listed them, causing schema validation to reject
otherwise-valid configs. Both the root schema and the embedded
runtime copy are updated together.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
An empty Cmd would silently invoke the shell with no arguments and
exit 0, masking misconfigurations. Return a clear error instead,
consistent with the required-field checks in HTTP/Wait/Template tasks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both tasks read from os.Stdin and can be marked concurrent:true.
Without synchronization, concurrent Prompt/Confirm tasks interleave
reads, hang, or consume each other's input. A package-level stdinMu
mutex ensures stdin is held exclusively for the duration of each
prompt, making concurrent execution effectively sequential for
user input.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without context, a fatal during initialization only shows the raw
error string with no indication of which stage failed. Adding
"init config:" and "load profile:" prefixes makes CLI failures
easier to diagnose.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Commands whose names match reserved subcommands were silently skipped,
giving no indication in help output or logs. Now emits a warning to
stderr so users know why their command is missing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Install() accessed context.Profile unconditionally. If called before
Initialize() sets the context, this panics. Added a nil guard
consistent with the pattern used in ExecuteEnv and GetCommands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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 introduces a task execution engine and custom command support to Raid, alongside cross-platform filesystem/shell improvements and expanded schema-driven configuration validation.

Changes:

  • Add a multi-type task runner (shell/script/http/wait/template/git/prompt/confirm/print/group/parallel/retry) plus task grouping and retries.
  • Add user-defined commands: that register as top-level raid <name> subcommands and support configurable output handling.
  • Harden cross-platform path handling, embed JSON schemas for validation, and add broad test coverage + updated docs/CI.

Reviewed changes

Copilot reviewed 44 out of 45 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/internal/lib/task_runner.go Implements task dispatch/execution, concurrency behavior, output routing, and group/parallel/retry logic.
src/internal/lib/task.go Defines Task/Condition models and expansion helpers.
src/cmd/raid.go Pre-initializes Raid to register dynamic subcommands and implements --config/-c pre-scan.
src/internal/lib/command.go Adds custom command execution and output configuration (stdout/stderr/file).
src/internal/lib/lib.go Adds embedded-schema validation and multi-doc YAML / JSON-array validation logic.
src/internal/sys/system.go Cross-platform path utilities and safer file existence checks; directory/file creation changes.
src/internal/lib/profile.go / repo.go / env.go Extends profile/repo/env models for install/groups/commands/tasks and integrates schema validation.
schemas/* + src/internal/lib/schemas/* Updates/extends JSON schemas for tasks, commands, install, and groups.
*_test.go files Adds extensive unit tests across sys/utils/lib/cmd.
README.md Updates documentation for tasks, commands, schemas, and examples.
.github/workflows/codecov.yml Ensures Go is set up and runs coverage with atomic mode.

Comment on lines 163 to 167
func extractProfilesFromYAML(data []byte, path string) ([]Profile, error) {
var profiles []Profile

documents := strings.Split(string(data), YAML_SEP)
documents := strings.Split(string(data), yamlSep)

Comment on lines +36 to 43
// CreateFile opens or creates the file at filePath for reading and writing, creating parent directories as needed.
func CreateFile(filePath string) (*os.File, error) {
pathEx := ExpandPath(filePath)
if FileExists(pathEx) {
return os.Open(pathEx)
if err := os.MkdirAll(filepath.Dir(pathEx), 0755); err != nil {
return nil, fmt.Errorf("failed to create directories for '%s': %w", filePath, err)
}

os.MkdirAll(path.Dir(pathEx), os.ModeDir|0755)
return os.Create(pathEx)
return os.OpenFile(pathEx, os.O_RDWR|os.O_CREATE, 0644)
}
Comment on lines +387 to +390
info, statErr := os.Stat(dir)
if statErr != nil || !info.IsDir() {
return fmt.Errorf("path is not a directory: %s", dir)
}
Comment thread src/cmd/raid.go
Comment on lines +86 to +87
if (arg == "--config" || arg == "-c") && i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
*raid.ConfigPath = args[i+1]
@8bitAlex 8bitAlex merged commit 2641081 into main Mar 14, 2026
15 checks passed
@8bitAlex 8bitAlex deleted the task-runner branch March 14, 2026 03:22
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