diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index f315fe6..c1a2b54 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -8,6 +8,10 @@ on: pull_request: branches: [ "master" ] +permissions: + contents: read + actions: write + jobs: build: @@ -18,7 +22,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: download JSON submodule run: git submodule update --init ./src/Helldivers-2-Models/json - name: Restore dependencies @@ -36,3 +40,22 @@ jobs: retention-days: 5 name: openapi-schemas path: docs/openapi/ + + docker-build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./src/Helldivers-2-API/Dockerfile + push: false + tags: helldivers-api:test + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index e66e0b6..14ad50e 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -31,7 +31,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Generate OpenAPI JSON files run: dotnet build -c Debug - name: Copy README diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index 1a5af52..f56d754 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -23,7 +23,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.0.x' + dotnet-version: '10.0.x' - name: Download JSON submodule run: git submodule update --init ./src/Helldivers-2-Models/json diff --git a/Directory.Build.props b/Directory.Build.props index bf255bb..bc2f4d4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ enable enable - net9.0 + net10.0 true diff --git a/src/Helldivers-2-API/Dockerfile b/src/Helldivers-2-API/Dockerfile index 2cad5bd..e53d752 100644 --- a/src/Helldivers-2-API/Dockerfile +++ b/src/Helldivers-2-API/Dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-alpine-extra AS base +FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine-extra AS base USER $APP_UID WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build -RUN apk add --upgrade --no-cache build-base clang zlib-dev +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine-aot AS build +RUN apk add --no-cache build-base clang lld llvm zlib-dev libstdc++ ARG BUILD_CONFIGURATION=Release ARG BUILD_RUNTIME=linux-musl-x64 ARG OPENAPI=false @@ -35,7 +35,9 @@ RUN dotnet build "Helldivers-2-API.csproj" --no-restore -r $BUILD_RUNTIME -c $BU FROM build AS publish ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "Helldivers-2-API.csproj" /p:Version="$VERSION" --no-restore --self-contained -r $BUILD_RUNTIME -c $BUILD_CONFIGURATION -o /app/publish +ARG BUILD_RUNTIME=linux-musl-x64 +ARG VERSION=0.0.0 +RUN dotnet publish "Helldivers-2-API.csproj" /p:Version="$VERSION" --self-contained -r $BUILD_RUNTIME -c $BUILD_CONFIGURATION -o /app/publish FROM base AS final WORKDIR /app diff --git a/src/Helldivers-2-API/Helldivers-2-API.csproj b/src/Helldivers-2-API/Helldivers-2-API.csproj index 57bcee3..e691df0 100644 --- a/src/Helldivers-2-API/Helldivers-2-API.csproj +++ b/src/Helldivers-2-API/Helldivers-2-API.csproj @@ -4,8 +4,8 @@ true Helldivers.API Linux - true true + true @@ -23,8 +23,9 @@ - - + + + @@ -36,12 +37,12 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/Helldivers-2-API/OpenApi/TypeMappers/EnumStringTypeMapper.cs b/src/Helldivers-2-API/OpenApi/TypeMappers/EnumStringTypeMapper.cs index ad77a62..3869268 100644 --- a/src/Helldivers-2-API/OpenApi/TypeMappers/EnumStringTypeMapper.cs +++ b/src/Helldivers-2-API/OpenApi/TypeMappers/EnumStringTypeMapper.cs @@ -1,4 +1,5 @@ -using NJsonSchema; +#if DEBUG +using NJsonSchema; using NJsonSchema.Generation.TypeMappers; using System.Collections.ObjectModel; @@ -34,3 +35,4 @@ public void GenerateSchema(JsonSchema schema, TypeMapperContext context) schema.ExtensionData ??= new Dictionary()!; } } +#endif diff --git a/src/Helldivers-2-API/Program.cs b/src/Helldivers-2-API/Program.cs index 33dd3ac..c87e91d 100644 --- a/src/Helldivers-2-API/Program.cs +++ b/src/Helldivers-2-API/Program.cs @@ -91,8 +91,8 @@ options.ForwardLimit = 999; options.OriginalForHeaderName = "Fly-Client-IP"; options.ForwardedHeaders = ForwardedHeaders.XForwardedFor; - options.KnownNetworks.Add(new IPNetwork(IPAddress.Any, 0)); - options.KnownNetworks.Add(new IPNetwork(IPAddress.IPv6Any, 0)); + options.KnownIPNetworks.Add(new System.Net.IPNetwork(IPAddress.Any, 0)); + options.KnownIPNetworks.Add(new System.Net.IPNetwork(IPAddress.IPv6Any, 0)); }); // This configuration is bound here so that source generators kick in. @@ -219,6 +219,9 @@ // Ensure web applications can access the API by setting CORS headers. app.UseCors(); +// Add various security-related headers. +app.UseSecurityHeaders(); + // Make sure ASP.NET Core uses the correct addresses internally rather than Fly's proxy app.UseForwardedHeaders(); diff --git a/src/Helldivers-2-CI/Helldivers-2-CI.csproj b/src/Helldivers-2-CI/Helldivers-2-CI.csproj index 76bce0f..15a4fea 100644 --- a/src/Helldivers-2-CI/Helldivers-2-CI.csproj +++ b/src/Helldivers-2-CI/Helldivers-2-CI.csproj @@ -2,13 +2,13 @@ Exe - net9.0 + net10.0 Helldivers_2_CI false - + diff --git a/src/Helldivers-2-Core/Helldivers-2-Core.csproj b/src/Helldivers-2-Core/Helldivers-2-Core.csproj index 0d66e02..ece9726 100644 --- a/src/Helldivers-2-Core/Helldivers-2-Core.csproj +++ b/src/Helldivers-2-Core/Helldivers-2-Core.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/Helldivers-2-SourceGen/Helldivers-2-SourceGen.csproj b/src/Helldivers-2-SourceGen/Helldivers-2-SourceGen.csproj index 55e74cf..98e54f2 100644 --- a/src/Helldivers-2-SourceGen/Helldivers-2-SourceGen.csproj +++ b/src/Helldivers-2-SourceGen/Helldivers-2-SourceGen.csproj @@ -18,13 +18,13 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - - + + + diff --git a/src/Helldivers-2-Sync/Helldivers-2-Sync.csproj b/src/Helldivers-2-Sync/Helldivers-2-Sync.csproj index bcb6843..a3ff309 100644 --- a/src/Helldivers-2-Sync/Helldivers-2-Sync.csproj +++ b/src/Helldivers-2-Sync/Helldivers-2-Sync.csproj @@ -6,11 +6,10 @@ - - - - - + + + + diff --git a/src/Helldivers-2-Sync/Hosted/ArrowHeadSyncService.cs b/src/Helldivers-2-Sync/Hosted/ArrowHeadSyncService.cs index 3c9a6e1..9f36ea5 100644 --- a/src/Helldivers-2-Sync/Hosted/ArrowHeadSyncService.cs +++ b/src/Helldivers-2-Sync/Hosted/ArrowHeadSyncService.cs @@ -53,7 +53,6 @@ private static partial void LogFailedToLoadTranslation(ILogger logger, Exception /// protected override async Task ExecuteAsync(CancellationToken cancellationToken) { - var delay = TimeSpan.FromSeconds(configuration.Value.IntervalSeconds); LogRunAtInterval(logger, delay); @@ -113,11 +112,12 @@ private async Task SynchronizeAsync(IServiceProvider services, CancellationToken cancellationToken ); - var spaceStations = await configuration.Value.SpaceStations.ToAsyncEnumerable().ToDictionaryAwaitAsync(ValueTask.FromResult, async key => - await DownloadTranslations( - async language => await api.LoadSpaceStations(season, key, language, cancellationToken), - cancellationToken - ), cancellationToken: cancellationToken); + var spaceStations = await configuration.Value.SpaceStations.ToAsyncEnumerable().ToDictionaryAsync( + static (key, _) => ValueTask.FromResult(key), async (key, stoppingToken) => + await DownloadTranslations( + async language => await api.LoadSpaceStations(season, key, language, stoppingToken), + stoppingToken + ), cancellationToken: cancellationToken); await storage.UpdateStores( rawWarId, @@ -152,7 +152,7 @@ private async Task>> DownloadTranslations(Fun return new KeyValuePair?>(language, null); } }) - .SelectAwait(async task => await task) + .Select(async (task, stoppingToken) => await task.WaitAsync(stoppingToken)) .Where(pair => pair.Value is not null) .ToDictionaryAsync(pair => pair.Key, pair => pair.Value.GetValueOrDefault(), cancellationToken: cancellationToken);