using System.Net.Http.Headers; using System.Reflection; using System.Text.Json.Serialization; using Asp.Versioning; using Microsoft.AspNetCore.Mvc; namespace OliverBooth.Api.Controllers.v1; [ApiController] [Route("v{version:apiVersion}/api/badge")] [Produces("application/json")] [ApiVersion(1)] public sealed class BadgeController : ControllerBase { private readonly IConfiguration _configuration; private readonly IHttpClientFactory _httpClientFactory; private readonly string _version; /// /// Initializes a new instance of the class. /// /// The configuration. /// The HTTP client factory. public BadgeController(IConfiguration configuration, IHttpClientFactory httpClientFactory) { _configuration = configuration; _httpClientFactory = httpClientFactory; var attribute = typeof(Program).Assembly.GetCustomAttribute(); _version = attribute?.InformationalVersion ?? "1.0.0"; } /// /// Returns a JSON object that is compatible with a shields.io custom endpoint. /// /// The repository name. /// The workflow. /// The owner. Defaults to oliverbooth. /// A JSON object. [HttpGet("status/{repo}/{workflow}")] [HttpGet("status/{owner}/{repo}/{workflow}")] [EndpointDescription("Returns a JSON object that is compatible with a shields.io custom endpoint.")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task StatusAsync(string repo, string workflow, string owner = "oliverbooth") { string? githubToken = _configuration.GetSection("GitHub:Token").Value; var url = $"https://api.github.com/repos/{owner}/{repo}/actions/workflows/{workflow}/runs"; Console.WriteLine(url); using HttpClient client = _httpClientFactory.CreateClient(); using var request = new HttpRequestMessage(); request.RequestUri = new Uri(url); request.Headers.Add("Accept", "application/json"); request.Headers.Add("Authorization", $"Bearer {githubToken}"); request.Headers.Add("X-GitHub-Api-Version", "2022-11-28"); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("oliverbooth.dev", _version)); using HttpResponseMessage response = await client.SendAsync(request); Console.WriteLine(await response.Content.ReadAsStringAsync()); var body = await response.Content.ReadFromJsonAsync(); WorkflowRun? run = body?.WorkflowRuns.FirstOrDefault(r => r.Status == WorkflowRunStatus.Completed); if (run is not null) { var color = run.Conclusion switch { WorkflowRunConclusion.Failure => "e05d44", WorkflowRunConclusion.Success => "44cc11", _ => "lightgray" }; var message = run.Conclusion switch { WorkflowRunConclusion.Failure => "failing", WorkflowRunConclusion.Success => "passing", _ => "unknown" }; return Ok(new { color, message }); } return Ok(new { color = "lightgray", message = "unknown" }); } private class WorkflowRunSchema { [JsonPropertyName("workflow_runs"), JsonInclude] public WorkflowRun[] WorkflowRuns { get; set; } = Array.Empty(); } private class WorkflowRun { [JsonPropertyName("conclusion"), JsonInclude] [JsonConverter(typeof(JsonStringEnumConverter))] public WorkflowRunConclusion Conclusion { get; set; } = WorkflowRunConclusion.Unknown; [JsonPropertyName("status"), JsonInclude] [JsonConverter(typeof(JsonStringEnumConverter))] public WorkflowRunStatus Status { get; set; } = WorkflowRunStatus.Unknown; } private enum WorkflowRunStatus { Unknown = -1, Completed } private enum WorkflowRunConclusion { Unknown = -1, Success, Failure } }