feat(admin): dispatch allowlisted maintenance jobs
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using JobTrackerApi.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace JobTrackerApi.Tests;
|
||||
|
||||
public sealed class MaintenanceJobDispatcherTests
|
||||
{
|
||||
[Fact]
|
||||
public void Job_is_unavailable_without_a_dispatch_token()
|
||||
{
|
||||
var dispatcher = new MaintenanceJobDispatcher(new ConfigurationBuilder().Build(), Mock.Of<IHttpClientFactory>());
|
||||
|
||||
var job = Assert.Single(dispatcher.GetJobs());
|
||||
|
||||
Assert.Equal(MaintenanceJobDispatcher.CvBenchmarkJobId, job.Id);
|
||||
Assert.False(job.Available);
|
||||
Assert.Null(job.RunsUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Dispatch_sends_only_the_registered_workflow_and_job_id()
|
||||
{
|
||||
HttpRequestMessage? captured = null;
|
||||
string? body = null;
|
||||
var handler = new StubHandler(async request =>
|
||||
{
|
||||
captured = request;
|
||||
body = request.Content is null ? null : await request.Content.ReadAsStringAsync();
|
||||
return new HttpResponseMessage(HttpStatusCode.NoContent);
|
||||
});
|
||||
var factory = new Mock<IHttpClientFactory>();
|
||||
factory.Setup(x => x.CreateClient("maintenance-jobs")).Returns(new HttpClient(handler));
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["MaintenanceJobs:GiteaBaseUrl"] = "https://git.example.test/",
|
||||
["MaintenanceJobs:GiteaOwner"] = "owner",
|
||||
["MaintenanceJobs:GiteaRepository"] = "repo",
|
||||
["MaintenanceJobs:GiteaToken"] = "test-token",
|
||||
}).Build();
|
||||
var dispatcher = new MaintenanceJobDispatcher(config, factory.Object);
|
||||
|
||||
await dispatcher.DispatchAsync(MaintenanceJobDispatcher.CvBenchmarkJobId, CancellationToken.None);
|
||||
|
||||
Assert.NotNull(captured);
|
||||
Assert.Equal(HttpMethod.Post, captured!.Method);
|
||||
Assert.Equal("https://git.example.test/api/v1/repos/owner/repo/actions/workflows/maintenance.yml/dispatches", captured.RequestUri!.ToString());
|
||||
Assert.Equal("token", captured.Headers.Authorization!.Scheme);
|
||||
using var json = JsonDocument.Parse(body!);
|
||||
Assert.Equal("main", json.RootElement.GetProperty("ref").GetString());
|
||||
Assert.Equal("cv-benchmark", json.RootElement.GetProperty("inputs").GetProperty("job").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Dispatch_rejects_any_unregistered_job_without_an_http_call()
|
||||
{
|
||||
var factory = new Mock<IHttpClientFactory>();
|
||||
var dispatcher = new MaintenanceJobDispatcher(new ConfigurationBuilder().Build(), factory.Object);
|
||||
|
||||
await Assert.ThrowsAsync<KeyNotFoundException>(() => dispatcher.DispatchAsync("shell", CancellationToken.None));
|
||||
factory.Verify(x => x.CreateClient(It.IsAny<string>()), Times.Never);
|
||||
}
|
||||
|
||||
private sealed class StubHandler(Func<HttpRequestMessage, Task<HttpResponseMessage>> send) : HttpMessageHandler
|
||||
{
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => send(request);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user