Status: Accepted Date: 2026-04-13
Context: The runner needs to clone repositories, create worktrees, and potentially run other git operations. These operations can take minutes (large repos) and must not block the tokio async runtime.
Decision: Use tokio::process::Command to shell out to the git binary for all git operations.
Alternatives considered:
- git2 (libgit2 bindings) — provides a native Rust API, but
libgit2operations are synchronous and would block the tokio runtime. Usingspawn_blockingfor every call adds complexity and limits concurrency. Also, libgit2's clone progress reporting is less straightforward than parsinggit clone --progressstderr. - gitoxide (gix) — native Rust git implementation, partially async. Promising but not yet feature-complete for all operations needed (worktrees, some clone edge cases). May be reconsidered in the future.
Consequences:
- Fully async —
tokio::process::Commandspawns a child process, no runtime blocking - Progress reporting by parsing
git clone --progressstderr line by line viaAsyncBufReadExt - Timeout enforcement via
tokio::time::timeoutwrapping the process - Requires
gitbinary on the system (present in all target environments) - Trade-off: shelling out is less type-safe than a library API. Error handling relies on exit codes and stderr parsing.
- SSRF validation is applied to URLs before passing them to
git, not relying on git's own URL handling