Per-list optional VerifyCommand (list_config.verify_command) runs via VerifyCommandRunner in the list's working dir right after a successful merge/continue-merge, before the task is allowed to reach Done. A non-zero exit or timeout leaves the merge in place but keeps the task out of Done and reports StatusVerifyFailed with an output excerpt through MergeResultDto/review_task; no command configured behaves exactly as before. Merges against the same repo are now serialized per working dir so a running verify can't be interrupted by a second merge landing mid-build. Adds the field to the List Settings modal (en/de localized) and covers success/failure/timeout in TaskMergeServiceTests + VerifyCommandRunnerTests.
61 lines
1.9 KiB
C#
61 lines
1.9 KiB
C#
using ClaudeDo.Worker.Lifecycle;
|
|
|
|
namespace ClaudeDo.Worker.Tests.Services;
|
|
|
|
public class VerifyCommandRunnerTests
|
|
{
|
|
private readonly VerifyCommandRunner _runner = new();
|
|
|
|
[Fact]
|
|
public async Task RunAsync_ExitsZero_ReportsSuccessNotTimedOut()
|
|
{
|
|
var result = await _runner.RunAsync(
|
|
Path.GetTempPath(), "exit 0", TimeSpan.FromSeconds(30), CancellationToken.None);
|
|
|
|
Assert.Equal(0, result.ExitCode);
|
|
Assert.False(result.TimedOut);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RunAsync_NonZeroExit_ReportsExitCode()
|
|
{
|
|
var result = await _runner.RunAsync(
|
|
Path.GetTempPath(), "exit 7", TimeSpan.FromSeconds(30), CancellationToken.None);
|
|
|
|
Assert.Equal(7, result.ExitCode);
|
|
Assert.False(result.TimedOut);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RunAsync_CapturesStdoutAndStderr()
|
|
{
|
|
var result = await _runner.RunAsync(
|
|
Path.GetTempPath(), "echo hello-out & echo hello-err 1>&2", TimeSpan.FromSeconds(30), CancellationToken.None);
|
|
|
|
Assert.Contains("hello-out", result.Output);
|
|
Assert.Contains("hello-err", result.Output);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RunAsync_RunsInSpecifiedWorkingDirectory()
|
|
{
|
|
var dir = Path.Combine(Path.GetTempPath(), $"verify_wd_{Guid.NewGuid():N}");
|
|
Directory.CreateDirectory(dir);
|
|
try
|
|
{
|
|
var result = await _runner.RunAsync(dir, "cd", TimeSpan.FromSeconds(30), CancellationToken.None);
|
|
Assert.Contains(new DirectoryInfo(dir).Name, result.Output);
|
|
}
|
|
finally { Directory.Delete(dir, recursive: true); }
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RunAsync_ExceedsTimeout_KillsProcessAndReportsTimedOut()
|
|
{
|
|
var result = await _runner.RunAsync(
|
|
Path.GetTempPath(), "ping -n 60 127.0.0.1", TimeSpan.FromMilliseconds(300), CancellationToken.None);
|
|
|
|
Assert.True(result.TimedOut);
|
|
}
|
|
}
|