CliWrap trialled and rejected — close the gaps in ProcessTasks instead
Maintainer thường phản hồi trong vòng 5 ngày
@ChrisonSimtian đang làm issue này rồi.
Từ ngày 27/7/2026.
Đánh giá
Issue này chưa được đánh giá.
Mô tả
Decision
CliWrap was trialled in Fallout.Migrate and rejected. Process execution stays on the in-house ProcessTasks (src/Fallout.Tooling/ProcessTasks.cs). No new package dependency.
Trialled and reverted in #576, which needed to shell out to dotnet tool uninstall / dotnet tool install from SwitchGlobalToolStep.
What the comparison showed
Both versions were built and run side by side against dotnet tool list --global, a deliberately failing dotnet tool uninstall, and a 1 ms timeout. Identical exit codes, identical stdout, identical stderr, and both return null on timeout. The difference is only in what the calling code costs to write.
| Lines (non-blank) | |
|---|---|
| CliWrap | 18 |
Raw System.Diagnostics.Process, written correctly |
47 |
ProcessTasks (what we shipped) |
31 |
With CliWrap:
using var cancellation = new CancellationTokenSource(commandTimeout);
return await Cli.Wrap("dotnet")
.WithArguments(arguments)
.WithValidation(CommandResultValidation.None)
.ExecuteBufferedAsync(cancellation.Token);
With ProcessTasks:
var argumentLine = arguments.Select(x => x.DoubleQuoteIfNeeded()).JoinSpace();
using var process = ProcessTasks.StartProcess(
"dotnet", argumentLine, timeout: (int)commandTimeout.TotalMilliseconds,
logOutput: false, logInvocation: false);
if (process == null || !process.WaitForExit())
return null;
return new CommandResult(
process.ExitCode,
Join(process.Output, OutputType.Std),
Join(process.Output, OutputType.Err));
What CliWrap actually solves
Worth recording, because these are the traps a hand-rolled runner falls into:
- The pipe-buffer deadlock. The obvious raw implementation is
WaitForExit()thenStandardOutput.ReadToEnd(). That hangs once the child fills the ~64KB pipe buffer while the parent is blocked inWaitForExit. Avoiding it needs event-based reads plus counting two EOF sentinels.ProcessTasksalready handles this, which is the main reason it was a viable replacement. - Cancellation that actually kills.
WaitForExitAsync(token)returns on timeout but leaves the child running. An explicitKill(entireProcessTree: true)is required or a timeout orphans the process. - A single result object carrying exit code plus both streams.
What CliWrap does not solve any more
Its reputation is dated on two points:
- Argument escaping —
ProcessStartInfo.ArgumentListhas handled quoting since .NET Core 2.1. - Async —
WaitForExitAsynchas been in the BCL since .NET 5.
What using ProcessTasks instead costs
Honest list, since these are the gaps a future improvement would close:
- No
CancellationToken. Only anintmillisecond timeout. - Synchronous only. No
WaitForExitAsync, so a step that is otherwise async has to wrap it. - Arguments are one pre-quoted string. No
ArgumentListequivalent, so every caller does its ownDoubleQuoteIfNeeded(). This is the one place the raw BCL is now better than our own layer. - Output is one interleaved collection filtered by
OutputType, rather than separate stdout and stderr. - Logs through Serilog by default. A tool that renders through Spectre must pass
logOutput: false, logInvocation: false. - Asserts instead of returning null when the executable is not on
PATH, so callers need atry/catch. - Pulls
SerilogandNuGet.Packaginginto anything referencingFallout.Tooling. ForFallout.Migratethis swapped one direct dependency for two transitive ones.
Acceptance criteria
-
ProcessTasks(or its successor) accepts aCancellationTokenalongside the millisecond timeout. - An async overload exists, so callers do not have to block a thread.
- An argument-list overload exists that quotes each argument, instead of every caller calling
DoubleQuoteIfNeeded(). - Not finding the executable on
PATHis reportable without atry/catcharound the call. -
docs/dependencies.mdkeeps pointing here as the reason there is no third-party process runner.
Notes
- Related: #310 (FT-5, context-scope tool-path resolvers and process defaults) is the natural home for the resolver half of this.
- Do not re-litigate adding CliWrap without new information. The measured difference is 18 lines against 31, for one call site.
- Ngôn ngữ chính
- C#
- Star
- 169
- Fork
- 21
- Merge trung bình
- 3 ngày 7 giờ
- Pull request đã merge (30 ngày)
- 9
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của Fallout-build/Fallout
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Fallout-build/Fallout#708 ·
Maintainer thường phản hồi trong vòng 5 ngày
-
.\build.ps1 in its current state isn't capable for :add-package commandCó thể đã có người làm @ITaluone đã nhận 33 ngày trước. Đang mởbug needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
Fallout-build/Fallout#670 ·
Maintainer thường phản hồi trong vòng 5 ngày
-
bug needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
Fallout-build/Fallout#669 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 5 ngày
-
CD enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Fallout-build/Fallout#649 ·
Maintainer thường phản hồi trong vòng 5 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Fallout-build/Fallout#630 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 5 ngày
Tất cả issue của Fallout-build/Fallout
Issue tương tự
-
bug misleading tooling trivial
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Docs example projects pinned to a literal library version instead of 3.*Có thể đã có người làm @DaveSkender đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
facioquo/stock-indicators-dotnet#2372 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[辞書] 「ショタ」の追加Đang mở辞書
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
yksr-melt/Meltype#653 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
needs-area
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Azure/typespec-azure#5695 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
svenhb/GRBL-Plotter#483 ·