diff options
| author | crupest <crupest@outlook.com> | 2022-11-26 17:21:33 +0800 | 
|---|---|---|
| committer | crupest <crupest@outlook.com> | 2022-11-26 17:21:33 +0800 | 
| commit | 80bb178ab3234fb7b883c6489ff3c5e2631e208e (patch) | |
| tree | 588d8efd20f1e427a9c72ce8fadd8a5dcb0b4879 /docker | |
| parent | 63e43d1a9b880c92d73b7ec97b596c38d3e758e2 (diff) | |
| download | crupest-80bb178ab3234fb7b883c6489ff3c5e2631e208e.tar.gz crupest-80bb178ab3234fb7b883c6489ff3c5e2631e208e.tar.bz2 crupest-80bb178ab3234fb7b883c6489ff3c5e2631e208e.zip | |
Add crupest-api.
Diffstat (limited to 'docker')
| -rw-r--r-- | docker/auto-backup/AutoBackup/.dockerignore | 2 | ||||
| -rw-r--r-- | docker/crupest-api/CrupestApi/.dockerignore | 2 | ||||
| -rw-r--r-- | docker/crupest-api/CrupestApi/.gitignore | 2 | ||||
| -rw-r--r-- | docker/crupest-api/CrupestApi/Config/TodosConfiguration.cs | 15 | ||||
| -rw-r--r-- | docker/crupest-api/CrupestApi/CrupestApi.csproj | 8 | ||||
| -rw-r--r-- | docker/crupest-api/CrupestApi/Program.cs | 160 | ||||
| -rw-r--r-- | docker/crupest-api/CrupestApi/Properties/launchSettings.json | 13 | ||||
| -rw-r--r-- | docker/crupest-api/CrupestApi/appsettings.json | 8 | ||||
| -rw-r--r-- | docker/crupest-api/Dockerfile | 13 | 
9 files changed, 223 insertions, 0 deletions
| diff --git a/docker/auto-backup/AutoBackup/.dockerignore b/docker/auto-backup/AutoBackup/.dockerignore new file mode 100644 index 0000000..7de5508 --- /dev/null +++ b/docker/auto-backup/AutoBackup/.dockerignore @@ -0,0 +1,2 @@ +obj +bin diff --git a/docker/crupest-api/CrupestApi/.dockerignore b/docker/crupest-api/CrupestApi/.dockerignore new file mode 100644 index 0000000..7de5508 --- /dev/null +++ b/docker/crupest-api/CrupestApi/.dockerignore @@ -0,0 +1,2 @@ +obj +bin diff --git a/docker/crupest-api/CrupestApi/.gitignore b/docker/crupest-api/CrupestApi/.gitignore new file mode 100644 index 0000000..7de5508 --- /dev/null +++ b/docker/crupest-api/CrupestApi/.gitignore @@ -0,0 +1,2 @@ +obj +bin diff --git a/docker/crupest-api/CrupestApi/Config/TodosConfiguration.cs b/docker/crupest-api/CrupestApi/Config/TodosConfiguration.cs new file mode 100644 index 0000000..68f893a --- /dev/null +++ b/docker/crupest-api/CrupestApi/Config/TodosConfiguration.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace CrupestApi.Config +{ +    public class TodoConfiguration +    { +        [Required] +        public string Username { get; set; } = default!; +        [Required] +        public int ProjectNumber { get; set; } = default!; +        [Required] +        public string Token { get; set; } = default!; +        public int? Count { get; set; } +    } +}
\ No newline at end of file diff --git a/docker/crupest-api/CrupestApi/CrupestApi.csproj b/docker/crupest-api/CrupestApi/CrupestApi.csproj new file mode 100644 index 0000000..4348979 --- /dev/null +++ b/docker/crupest-api/CrupestApi/CrupestApi.csproj @@ -0,0 +1,8 @@ +<Project Sdk="Microsoft.NET.Sdk.Web">
 +
 +  <PropertyGroup>
 +    <TargetFramework>net7.0</TargetFramework>
 +    <Nullable>enable</Nullable>
 +  </PropertyGroup>
 +
 +</Project>
 diff --git a/docker/crupest-api/CrupestApi/Program.cs b/docker/crupest-api/CrupestApi/Program.cs new file mode 100644 index 0000000..c62bf4d --- /dev/null +++ b/docker/crupest-api/CrupestApi/Program.cs @@ -0,0 +1,160 @@ +using System;
 +using System.Collections.Generic;
 +using System.Text;
 +using System.Text.Json;
 +using System.Net.Http;
 +using System.Net.Http.Headers;
 +using System.Net.Mime;
 +using Microsoft.AspNetCore.Builder;
 +using Microsoft.AspNetCore.Mvc;
 +using Microsoft.Extensions.Configuration;
 +using Microsoft.Extensions.Logging;
 +using Microsoft.Extensions.Logging.Console;
 +using Microsoft.AspNetCore.Http;
 +using CrupestApi.Config;
 +
 +public class TodoItem
 +{
 +    public string Status { get; set; } = default!;
 +    public string Title { get; set; } = default!;
 +}
 +
 +internal class Program
 +{
 +    private static void Main(string[] args)
 +    {
 +        using var httpClient = new HttpClient();
 +
 +        var builder = WebApplication.CreateBuilder(args);
 +
 +        string configFilePath = Environment.GetEnvironmentVariable("CRUPEST_API_CONFIG_FILE") ?? "/config.json";
 +
 +        builder.Configuration.AddJsonFile(configFilePath, optional: false, reloadOnChange: true);
 +
 +        string? logFilePath = Environment.GetEnvironmentVariable("CRUPEST_API_LOG_FILE");
 +        if (logFilePath is not null)
 +        {
 +            // TODO: Log to file.
 +            builder.Logging.AddSimpleConsole(logger =>
 +            {
 +                logger.ColorBehavior = LoggerColorBehavior.Disabled;
 +            });
 +        }
 +
 +        var app = builder.Build();
 +
 +        app.MapGet("/api/todos", async ([FromServices] IConfiguration configuration, [FromServices] ILoggerFactory loggerFactory) =>
 +        {
 +            var logger = loggerFactory.CreateLogger("CrupestApi.Todos");
 +
 +            static string CreateGraphQLQuery(TodoConfiguration todoConfiguration)
 +            {
 +                return $$"""
 +{
 +    user(login: "{{todoConfiguration.Username}}") {
 +        projectV2(number: {{todoConfiguration.ProjectNumber}}) {
 +          items(last: {{todoConfiguration.Count ?? 20}}) {
 +            nodes {
 +              __typename
 +              content {
 +                __typename
 +                ... on Issue {
 +                  title
 +                  closed
 +                }
 +                ... on PullRequest {
 +                  title
 +                  closed
 +                }
 +                ... on DraftIssue {
 +                  title
 +                }
 +              }
 +            }
 +          }
 +        }
 +      }
 +    }
 +""";
 +            }
 +
 +            var todoConfiguration = configuration.GetSection("Todos").Get<TodoConfiguration>();
 +            if (todoConfiguration is null)
 +            {
 +                throw new Exception("Fail to get todos configuration.");
 +            }
 +
 +            using var requestContent = new StringContent(JsonSerializer.Serialize(new
 +            {
 +                query = CreateGraphQLQuery(todoConfiguration)
 +            }));
 +            requestContent.Headers.ContentType = new MediaTypeHeaderValue(MediaTypeNames.Application.Json, Encoding.UTF8.WebName);
 +
 +            using var request = new HttpRequestMessage(HttpMethod.Post, "https://api.github.com/graphql");
 +            request.Content = requestContent;
 +            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", todoConfiguration.Token);
 +
 +            using var response = await httpClient.SendAsync(request);
 +            var responseBody = await response.Content.ReadAsStringAsync();
 +            logger.LogInformation(response.StatusCode.ToString());
 +            logger.LogInformation(responseBody);
 +
 +
 +            if (response.IsSuccessStatusCode)
 +            {
 +                using var responseJson = JsonSerializer.Deserialize<JsonDocument>(responseBody);
 +                if (responseJson is null)
 +                {
 +                    throw new Exception("Fail to deserialize response body.");
 +                }
 +
 +                var nodes = responseJson.RootElement.GetProperty("data").GetProperty("user").GetProperty("projectV2").GetProperty("items").GetProperty("nodes").EnumerateArray();
 +
 +                var result = new List<TodoItem>();
 +
 +                foreach (var node in nodes)
 +                {
 +                    var content = node.GetProperty("content");
 +                    var title = content.GetProperty("title").GetString();
 +                    if (title is null)
 +                    {
 +                        throw new Exception("Fail to get title.");
 +                    }
 +                    JsonElement closedElement;
 +                    bool closed;
 +                    if (content.TryGetProperty("closed", out closedElement))
 +                    {
 +                        closed = closedElement.GetBoolean();
 +                    }
 +                    else
 +                    {
 +                        closed = false;
 +                    }
 +
 +                    result.Add(new TodoItem
 +                    {
 +                        Title = title,
 +                        Status = closed ? "Done" : "Todo"
 +                    });
 +                }
 +
 +                return Results.Json(result, new JsonSerializerOptions
 +                {
 +                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
 +                }, statusCode: 200);
 +            }
 +            else
 +            {
 +                const string message = "Fail to get todos from GitHub.";
 +                logger.LogError(message);
 +
 +                return Results.Json(new
 +                {
 +                    message
 +                }, statusCode: StatusCodes.Status503ServiceUnavailable);
 +            }
 +        });
 +
 +        app.Run();
 +    }
 +}
\ No newline at end of file diff --git a/docker/crupest-api/CrupestApi/Properties/launchSettings.json b/docker/crupest-api/CrupestApi/Properties/launchSettings.json new file mode 100644 index 0000000..01f2a12 --- /dev/null +++ b/docker/crupest-api/CrupestApi/Properties/launchSettings.json @@ -0,0 +1,13 @@ +{
 +  "$schema": "https://json.schemastore.org/launchsettings.json",
 +  "profiles": {
 +    "dev": {
 +      "commandName": "Project",
 +      "dotnetRunMessages": true,
 +      "applicationUrl": "http://localhost:5188",
 +      "environmentVariables": {
 +        "ASPNETCORE_ENVIRONMENT": "Development"
 +      }
 +    }
 +  }
 +}
\ No newline at end of file diff --git a/docker/crupest-api/CrupestApi/appsettings.json b/docker/crupest-api/CrupestApi/appsettings.json new file mode 100644 index 0000000..53753bd --- /dev/null +++ b/docker/crupest-api/CrupestApi/appsettings.json @@ -0,0 +1,8 @@ +{
 +  "Logging": {
 +    "LogLevel": {
 +      "Default": "Information"
 +    }
 +  },
 +  "AllowedHosts": "*"
 +}
\ No newline at end of file diff --git a/docker/crupest-api/Dockerfile b/docker/crupest-api/Dockerfile new file mode 100644 index 0000000..ba7d75b --- /dev/null +++ b/docker/crupest-api/Dockerfile @@ -0,0 +1,13 @@ +FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine AS build +COPY CrupestApi /CrupestApi +WORKDIR /CrupestApi +RUN dotnet publish CrupestApi.csproj --configuration Release --output ./publish/ -r linux-x64 --self-contained false + +FROM mcr.microsoft.com/dotnet/aspnet:7.0-alpine +ENV ASPNETCORE_URLS=http://0.0.0.0:5000 +ENV ASPNETCORE_FORWARDEDHEADERS_ENABLED=true +COPY --from=build /CrupestApi/publish /CrupestApi +WORKDIR /CrupestApi +VOLUME [ "/config.json" ] +EXPOSE 5000 +ENTRYPOINT ["dotnet", "CrupestApi.dll"] | 
