Execution runtime
After planning, orun switches from compiler behavior to runtime behavior. The runtime reads the immutable plan, orders jobs, persists state, and delegates each step to an executor backend.
Runtime responsibilities
- verify the plan checksum against saved state
- compute topological execution order
- print dry-run or live execution summaries
- persist step and job state when execution is enabled
- delegate each step to the selected executor
Executor backends
Local executor
Runs run: steps through sh -c on the host. It is the simplest backend and the best default for local development.
Docker executor
Ensures the image is available, mounts the workspace at /workspace, and executes inside a container. It uses job.runsOn as the image source.
GitHub Actions executor
Uses the internal GitHub Actions engine to support use: steps, workflow command files, post-step handling, and GitHub Actions environment semantics.
Per-job environment isolation
Each job gets its own temp directory, HOME, RUNNER_TEMP, and file-command directories. This prevents jobs running concurrently from colliding on environment state.
Per-job action isolation
Remote actions are materialized into each job's temp directory before execution. Files are hardlinked from the shared on-disk cache — a zero-cost operation on the same filesystem. If the cache and temp directories are on different filesystems, a full copy is made automatically.
This means:
- The shared action cache is read-only during execution.
- A job cannot corrupt a cached action or affect a sibling job's copy.
- Local actions (workspace-relative paths) are used directly without copying.
Action reference caching
Resolving a mutable ref (e.g., actions/setup-node@v4) to a pinned SHA uses a three-tier cache: an in-memory map shared across jobs in the same process (with singleflight deduplication), an on-disk file under ~/.orun/actions/, and the GitHub REST API as a final fallback. This eliminates redundant API calls under high concurrency.
Phase boundaries
Execution stays linear but explicit:
premainpost
Within each phase, order and declaration order determine the exact step sequence.
Failure behavior
failFastis read from the plan execution block- step-level
retryvalues are honored onFailure: continuelets later steps run after a non-fatal failure- job state is persisted only when execution is enabled
That keeps dry-run side-effect free while still letting execute mode resume safely.