Forge
csharpdeeb25a2
1using CascadeIDE.Contracts;
2
3namespace CascadeIDE.Features.Build.Application;
4
5/// <summary>
6/// Сборка решения с потоковым выводом в канал и сливом в произвольный <see cref="Action{T}"/>.
7/// </summary>
8[ApplicationOrchestrator]
9public static class DotnetSolutionChunkedBuildOrchestrator
10{
11 /// <summary>
12 /// Запускает <c>dotnet build</c> для <paramref name="solutionPath"/> с записью лога по чанкам.
13 /// </summary>
14 /// <returns>При ошибке CLR — код выхода <c>null</c>, сборка считается неуспешной.</returns>
15 public static async Task<(int? ExitCode, bool? BuildSucceeded)> RunSolutionBuildStreamingAsync(
16 string solutionPath,
17 IDotnetCommandRunner runner,
18 Action<string> appendChunk,
19 CancellationToken cancellationToken)
20 {
21 var workDir = Path.GetDirectoryName(solutionPath) ?? "";
22 int? lastExitCode = null;
23 bool? lastBuildSucceeded = null;
24
25 try
26 {
27 var channel = BuildLogIngestion.CreateBuildLogChannel();
28
29 var drainTask = BuildLogIngestion.DrainToAppendAsync(
30 channel.Reader,
31 appendChunk,
32 maxBatchChars: 8192,
33 cancellationToken: cancellationToken);
34
35 var runTask = runner.RunWithChunkWriterAsync(
36 ["build", solutionPath],
37 workDir,
38 channel.Writer,
39 cancellationToken);
40
41 await Task.WhenAll(drainTask, runTask).ConfigureAwait(false);
42 var (success, exitCode) = await runTask.ConfigureAwait(false);
43 lastExitCode = exitCode;
44 lastBuildSucceeded = success;
45
46 appendChunk("\r\n");
47 if (!success && exitCode != 0)
48 appendChunk($"\r\nКод выхода: {exitCode}");
49 }
50 catch (Exception ex)
51 {
52 appendChunk("Ошибка: " + ex.Message + "\r\n");
53 lastBuildSucceeded = false;
54 }
55
56 return (lastExitCode, lastBuildSucceeded);
57 }
58}
59
View only · write via MCP/CIDE