Skip to content

Commit

Permalink
Target .NET 8 (xoofx#282)
Browse files Browse the repository at this point in the history
* Target .NET 8

* Update NUnit
  • Loading branch information
bdovaz authored Dec 5, 2023
1 parent e5f6e85 commit dbff383
Show file tree
Hide file tree
Showing 32 changed files with 1,929 additions and 1,873 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Install .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: '7.0.x'
dotnet-version: '8.0.x'

- name: Build & test (Release)
run: dotnet test src -c Release
Expand Down
40 changes: 20 additions & 20 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:7.0 AS build
ARG TARGETARCH
WORKDIR /app

RUN mkdir -p src/UnityNuGet && mkdir -p src/UnityNuGet.Server && mkdir -p src/UnityNuGet.Tests

COPY src/*.sln src
COPY src/UnityNuGet/*.csproj src/UnityNuGet
COPY src/UnityNuGet.Server/*.csproj src/UnityNuGet.Server
COPY src/UnityNuGet.Tests/*.csproj src/UnityNuGet.Tests
RUN dotnet restore src -a $TARGETARCH

COPY . ./
RUN dotnet publish src -a $TARGETARCH -c Release -o /app/src/out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /app
COPY --from=build /app/src/out .
ENTRYPOINT ["dotnet", "UnityNuGet.Server.dll"]
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG TARGETARCH
WORKDIR /app

RUN mkdir -p src/UnityNuGet && mkdir -p src/UnityNuGet.Server && mkdir -p src/UnityNuGet.Tests

COPY src/*.sln src
COPY src/UnityNuGet/*.csproj src/UnityNuGet
COPY src/UnityNuGet.Server/*.csproj src/UnityNuGet.Server
COPY src/UnityNuGet.Tests/*.csproj src/UnityNuGet.Tests
RUN dotnet restore src -a $TARGETARCH

COPY . ./
RUN dotnet publish src -a $TARGETARCH -c Release -o /app/src/out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app/src/out .
ENTRYPOINT ["dotnet", "UnityNuGet.Server.dll"]
8 changes: 8 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project>

<PropertyGroup>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

</Project>
24 changes: 24 additions & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="8.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
<PackageVersion Include="NuGet.PackageManagement" Version="6.8.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageVersion Include="NUglify" Version="1.21.0" />
<PackageVersion Include="nunit" Version="3.14.0" />
<PackageVersion Include="NUnit.Analyzers" Version="3.10.0" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageVersion Include="Scriban" Version="5.9.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
</ItemGroup>
</Project>
250 changes: 122 additions & 128 deletions src/UnityNuGet.Server/Controllers/ApiController.cs
Original file line number Diff line number Diff line change
@@ -1,130 +1,124 @@
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using UnityNuGet.Npm;

namespace UnityNuGet.Server.Controllers
{
/// <summary>
/// Main entry to emulate the following NPM endpoints:
///
/// - "-/all": query all packages (return json)
/// - "{packageId}": query a specific package (return json)
/// - "{package_id}/-/{package_file}": download a specific package
/// </summary>
[Route("")]
[ApiController]
public class ApiController : ControllerBase
{
private readonly RegistryCacheSingleton _cacheSingleton;
private readonly RegistryCacheReport _registryCacheReport;

public ApiController(RegistryCacheSingleton cacheSingleton, RegistryCacheReport registryCacheReport)
{
_cacheSingleton = cacheSingleton;
_registryCacheReport = registryCacheReport;
}
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using UnityNuGet.Npm;

namespace UnityNuGet.Server.Controllers
{
/// <summary>
/// Main entry to emulate the following NPM endpoints:
///
/// - "-/all": query all packages (return json)
/// - "{packageId}": query a specific package (return json)
/// - "{package_id}/-/{package_file}": download a specific package
/// </summary>
[Route("")]
[ApiController]
public class ApiController(RegistryCacheSingleton cacheSingleton, RegistryCacheReport registryCacheReport) : ControllerBase
{
private readonly RegistryCacheSingleton _cacheSingleton = cacheSingleton;
private readonly RegistryCacheReport _registryCacheReport = registryCacheReport;

// GET /
[HttpGet("")]
public IActionResult Home()
{
return Ok();
}

// GET -/all
[HttpGet("-/all")]
public JsonResult GetAll()
{
if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);

var result = instance?.All();
return new JsonResult(result);
}

// GET {packageId}
[HttpGet("{id}")]
public JsonResult GetPackage(string id)
{
if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);

var package = instance?.GetPackage(id);
if (package == null)
{
return new JsonResult(NpmError.NotFound);
}

return new JsonResult(package);
}

// GET {package_id}/-/{package_file}
[HttpGet("{id}/-/{file}")]
[HttpHead("{id}/-/{file}")]
public IActionResult DownloadPackage(string id, string file)
{
if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);

var package = instance?.GetPackage(id);
if (package == null)
{
return new JsonResult(NpmError.NotFound);
}

if (!file.StartsWith(id + "-") || !file.EndsWith(".tgz"))
{
return new JsonResult(NpmError.NotFound);
}

var filePath = instance?.GetPackageFilePath(file);
if (string.IsNullOrEmpty(filePath) || !System.IO.File.Exists(filePath))
{
return new JsonResult(NpmError.NotFound);
}

// This method can be called with HEAD request, so in that case we just calculate the content length
if (Request.Method.Equals("HEAD"))
{
Response.ContentType = "application/octet-stream";
Response.ContentLength = new FileInfo(filePath).Length;
return Ok();
}
else
{
return new PhysicalFileResult(filePath, "application/octet-stream") { FileDownloadName = file };
}
}

private bool TryGetInstance(out RegistryCache? cacheInstance, out NpmError? npmError)
{
var instance = _cacheSingleton.Instance;
cacheInstance = instance;

if (instance == null)
{
if (_registryCacheReport.ErrorMessages.Any())
{
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Error initializing the server:");

foreach (var error in _registryCacheReport.ErrorMessages)
{
stringBuilder.AppendLine(error);
}

npmError = new NpmError("not_initialized", stringBuilder.ToString());
}
else
{
npmError = new NpmError("not_initialized", $"The server is initializing ({_registryCacheReport.Progress:F1}% completed). Please retry later...");
}
}
else
{
npmError = null;
}

return instance != null;
}
}
}
[HttpGet("")]
public IActionResult Home()
{
return Ok();
}

// GET -/all
[HttpGet("-/all")]
public JsonResult GetAll()
{
if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);

var result = instance?.All();
return new JsonResult(result);
}

// GET {packageId}
[HttpGet("{id}")]
public JsonResult GetPackage(string id)
{
if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);

var package = instance?.GetPackage(id);
if (package == null)
{
return new JsonResult(NpmError.NotFound);
}

return new JsonResult(package);
}

// GET {package_id}/-/{package_file}
[HttpGet("{id}/-/{file}")]
[HttpHead("{id}/-/{file}")]
public IActionResult DownloadPackage(string id, string file)
{
if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);

var package = instance?.GetPackage(id);
if (package == null)
{
return new JsonResult(NpmError.NotFound);
}

if (!file.StartsWith(id + "-") || !file.EndsWith(".tgz"))
{
return new JsonResult(NpmError.NotFound);
}

var filePath = instance?.GetPackageFilePath(file);
if (string.IsNullOrEmpty(filePath) || !System.IO.File.Exists(filePath))
{
return new JsonResult(NpmError.NotFound);
}

// This method can be called with HEAD request, so in that case we just calculate the content length
if (Request.Method.Equals("HEAD"))
{
Response.ContentType = "application/octet-stream";
Response.ContentLength = new FileInfo(filePath).Length;
return Ok();
}
else
{
return new PhysicalFileResult(filePath, "application/octet-stream") { FileDownloadName = file };
}
}

private bool TryGetInstance(out RegistryCache? cacheInstance, out NpmError? npmError)
{
var instance = _cacheSingleton.Instance;
cacheInstance = instance;

if (instance == null)
{
if (_registryCacheReport.ErrorMessages.Any())
{
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Error initializing the server:");

foreach (var error in _registryCacheReport.ErrorMessages)
{
stringBuilder.AppendLine(error);
}

npmError = new NpmError("not_initialized", stringBuilder.ToString());
}
else
{
npmError = new NpmError("not_initialized", $"The server is initializing ({_registryCacheReport.Progress:F1}% completed). Please retry later...");
}
}
else
{
npmError = null;
}

return instance != null;
}
}
}
Loading

0 comments on commit dbff383

Please sign in to comment.