Files
jobtrackingapp/JobTrackerApi/Services/MaintenanceJobDispatcher.cs
T
cesnimda de85492373
CI and Deploy / test (push) Successful in 6m47s
CI and Deploy / deploy (push) Failing after 25s
feat(ops): automate backups and private CV benchmarks
2026-09-02 00:49:06 +02:00

77 lines
3.2 KiB
C#

using System.Net.Http.Headers;
using System.Net.Http.Json;
namespace JobTrackerApi.Services;
public sealed record MaintenanceJobDefinition(string Id, string Title, string Description, bool Available, string? RunsUrl);
public sealed class MaintenanceJobDispatcher(IConfiguration configuration, IHttpClientFactory httpClientFactory)
{
public const string CvBenchmarkJobId = "cv-benchmark";
public IReadOnlyList<MaintenanceJobDefinition> GetJobs()
{
var settings = ReadSettings();
return
[
new(
CvBenchmarkJobId,
"CV extraction benchmark",
"Runs the private CV corpus benchmark on the production host and publishes its report to Admin/System.",
settings.IsConfigured,
settings.RunsUrl)
];
}
public async Task DispatchAsync(string jobId, CancellationToken cancellationToken)
{
if (!string.Equals(jobId, CvBenchmarkJobId, StringComparison.Ordinal))
{
throw new KeyNotFoundException("Unknown maintenance job.");
}
var settings = ReadSettings();
if (!settings.IsConfigured)
{
throw new InvalidOperationException("Maintenance job dispatch is not configured.");
}
using var request = new HttpRequestMessage(
HttpMethod.Post,
$"{settings.BaseUrl}/api/v1/repos/{Uri.EscapeDataString(settings.Owner)}/{Uri.EscapeDataString(settings.Repository)}/actions/workflows/maintenance.yml/dispatches");
request.Headers.Authorization = new AuthenticationHeaderValue("token", settings.Token);
request.Content = JsonContent.Create(new
{
@ref = "main",
inputs = new Dictionary<string, string> { ["job"] = jobId }
});
using var response = await httpClientFactory.CreateClient("maintenance-jobs")
.SendAsync(request, cancellationToken);
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException(
$"Gitea rejected the maintenance workflow dispatch with HTTP {(int)response.StatusCode}.",
null,
response.StatusCode);
}
}
private Settings ReadSettings()
{
var baseUrl = (configuration["MaintenanceJobs:GiteaBaseUrl"] ?? "https://git.cesnimda.uk").Trim().TrimEnd('/');
var owner = (configuration["MaintenanceJobs:GiteaOwner"] ?? "cesnimda").Trim();
var repository = (configuration["MaintenanceJobs:GiteaRepository"] ?? "jobtrackingapp").Trim();
var token = (configuration["MaintenanceJobs:GiteaToken"] ?? string.Empty).Trim();
var configured = Uri.TryCreate(baseUrl, UriKind.Absolute, out var uri)
&& uri.Scheme == Uri.UriSchemeHttps
&& !string.IsNullOrWhiteSpace(owner)
&& !string.IsNullOrWhiteSpace(repository)
&& !string.IsNullOrWhiteSpace(token);
var runsUrl = configured ? $"{baseUrl}/{owner}/{repository}/actions" : null;
return new Settings(baseUrl, owner, repository, token, configured, runsUrl);
}
private sealed record Settings(string BaseUrl, string Owner, string Repository, string Token, bool IsConfigured, string? RunsUrl);
}