Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Several improvements #442

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG TARGETARCH
WORKDIR /app

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

COPY src/Directory.Build.props src/Directory.Build.props
COPY src/Directory.Packages.props src/Directory.Packages.props
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
COPY src/UnityNuGet.Server.Tests/*.csproj src/UnityNuGet.Server.Tests
RUN dotnet restore src -a $TARGETARCH

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

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:9.0
Expand Down
9 changes: 5 additions & 4 deletions examples/docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ services:
build: ../..
environment:
- Registry:RootHttpUrl=http://localhost:5000/ # Server Url to build the absolute path to the package.
- Registry:Filter= # Filter in regex format so that only the indicated packages are processed.
- Registry:UnityScope=org.custom # Packages prefix, default is "org.nuget" but it can be modified to be able to have several containers with different prefixes and to be able to add several scope registries.
- Registry:MinimumUnityVersion=2020.1 # Minimum version of Unity required to install packages, default is "2019.1".
- Registry:PackageNameNuGetPostFix= (Custom NuGet) # Suffix of the package title, useful in case of having several containers and several scope registries, default is " (NuGet)".
- Registry:RegistryFilePath=custom_registry.json # Path to the file (relative or absolute) where the packages registry file will be stored, default is "registry.json".
- Registry:RootPersistentFolder=custom_unity_packages # Path to the folder (relative or absolute) where the packages cache will be stored, default is "unity_packages".
- Registry:RegistryFilePath=/data/registry.json # Path to the file (relative or absolute) where the packages registry file will be stored, default is "registry.json".
- Registry:RootPersistentFolder=/data/unity_packages # Path to the folder (relative or absolute) where the packages cache will be stored, default is "unity_packages".
- Registry:UpdateInterval=00:01:00 # Packages update interval, default is "00:10:00" (10 minutes).
- Logging:LogLevel:Default=Information
ports:
- 5000:8080
volumes:
- ./registry.json:/app/custom_registry.json # Override the package registry to be able to add or remove packages.
- ./unity_packages:/app/custom_unity_packages # Map the folder with the packages cache.
- ./registry.json:/data/registry.json # Override the package registry to be able to add or remove packages.
- ./unity_packages:/data/unity_packages # Map the folder with the packages cache.
- ./NuGet.Config:/root/.nuget/NuGet/NuGet.Config # Override Nuget.config file with repository information. This file can be used to configure a custom NuGet repository: https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file
4 changes: 4 additions & 0 deletions examples/docker/registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
"listed": true,
"version": "4.4.0"
},
"System.Linq.Async": {
"listed": true,
"version": "4.0.0"
},
"System.Memory": {
"listed": true,
"version": "4.5.0"
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.22.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0" />
Expand Down
201 changes: 201 additions & 0 deletions src/UnityNuGet.Server.Tests/ApiControllerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
using System;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;
using UnityNuGet.Npm;

namespace UnityNuGet.Server.Tests
{
public class ApiControllerTests
{
private readonly UnityNuGetWebApplicationFactory _webApplicationFactory;

public ApiControllerTests()
{
_webApplicationFactory = new UnityNuGetWebApplicationFactory();
}

[OneTimeTearDown]
public void OneTimeTearDown()
{
_webApplicationFactory.Dispose();
}

[Test]
public async Task Home_Success()
{
using HttpClient client = _webApplicationFactory.CreateDefaultClient();

HttpResponseMessage response = await client.GetAsync("/");

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.Found));
Assert.That(response.Headers.Location, Is.EqualTo(new Uri("/-/all", UriKind.Relative)));

string responseContent = await response.Content.ReadAsStringAsync();

Assert.That(responseContent, Is.Empty);
}

[Test]
public async Task GetAll_Success()
{
using HttpClient httpClient = _webApplicationFactory.CreateDefaultClient();

await WaitForInitialization(_webApplicationFactory.Services);

HttpResponseMessage response = await httpClient.GetAsync("/-/all");

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));

string responseContent = await response.Content.ReadAsStringAsync();

NpmPackageListAllResponse npmPackageListAllResponse = JsonSerializer.Deserialize(responseContent, UnityNugetJsonSerializerContext.Default.NpmPackageListAllResponse)!;

Assert.That(npmPackageListAllResponse.Packages, Has.Count.EqualTo(1));

Assert.Multiple(() =>
{
string packageName = $"org.nuget.{UnityNuGetWebApplicationFactory.PackageName.ToLowerInvariant()}";

Assert.That(npmPackageListAllResponse.Packages.ContainsKey(packageName), Is.True);
Assert.That(npmPackageListAllResponse.Packages[packageName].Name, Is.EqualTo(packageName));
Assert.That(npmPackageListAllResponse.Packages[packageName].Description, Is.Not.Null);
Assert.That(npmPackageListAllResponse.Packages[packageName].Author, Is.Not.Null);
});
}

[Test]
public async Task GetPackage_NotFound()
{
using HttpClient httpClient = _webApplicationFactory.CreateDefaultClient();

await WaitForInitialization(_webApplicationFactory.Services);

HttpResponseMessage response = await httpClient.GetAsync($"/InvalidPackageName");

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));

string responseContent = await response.Content.ReadAsStringAsync();

NpmError npmError = JsonSerializer.Deserialize(responseContent, UnityNugetJsonSerializerContext.Default.NpmError)!;

Assert.That(npmError.Error, Is.EqualTo("not_found"));
}

[Test]
public async Task GetPackage_Success()
{
using HttpClient httpClient = _webApplicationFactory.CreateDefaultClient();

await WaitForInitialization(_webApplicationFactory.Services);

string packageName = $"org.nuget.{UnityNuGetWebApplicationFactory.PackageName.ToLowerInvariant()}";

HttpResponseMessage response = await httpClient.GetAsync($"/{packageName}");

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));

string responseContent = await response.Content.ReadAsStringAsync();

NpmPackage npmPackage = JsonSerializer.Deserialize(responseContent, UnityNugetJsonSerializerContext.Default.NpmPackage)!;

Assert.Multiple(() =>
{
Assert.That(npmPackage.Id, Is.EqualTo(packageName));
Assert.That(npmPackage.Revision, Is.Not.Null);
Assert.That(npmPackage.Name, Is.EqualTo(packageName));
Assert.That(npmPackage.License, Is.Not.Null);
Assert.That(npmPackage.Description, Is.Not.Null);
});
}

[Test]
[TestCase("org.nuget.newtonsoft.json", "InvalidFile")]
[TestCase("InvalidId", "org.nuget.newtonsoft.json-11.0.1.tgz")]
[TestCase("org.nuget.newtonsoft.json", "org.nuget.newtonsoft.json_11.0.1.tgz")]
[TestCase("org.nuget.newtonsoft.json", "org.nuget.newtonsoft.json-11.0.1.InvalidExtension")]
public async Task DownloadPackage_NotFound(string id, string file)
{
using HttpClient httpClient = _webApplicationFactory.CreateDefaultClient();

await WaitForInitialization(_webApplicationFactory.Services);

HttpResponseMessage response = await httpClient.GetAsync($"/{id}/-/{file}");

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));

string responseContent = await response.Content.ReadAsStringAsync();

NpmError npmError = JsonSerializer.Deserialize(responseContent, UnityNugetJsonSerializerContext.Default.NpmError)!;

Assert.That(npmError.Error, Is.EqualTo("not_found"));
}

[Test]
public async Task DownloadPackage_Head_Success()
{
using HttpClient httpClient = _webApplicationFactory.CreateDefaultClient();

await WaitForInitialization(_webApplicationFactory.Services);

string packageName = $"org.nuget.{UnityNuGetWebApplicationFactory.PackageName.ToLowerInvariant()}";

HttpRequestMessage httpRequestMessage = new()
{
RequestUri = new Uri($"/{packageName}/-/{packageName}-11.0.1.tgz", UriKind.Relative),
Method = HttpMethod.Head
};

HttpResponseMessage response = await httpClient.SendAsync(httpRequestMessage);

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));

byte[] responseContent = await response.Content.ReadAsByteArrayAsync();

Assert.Multiple(() =>
{
Assert.That(responseContent, Is.Empty);

Assert.That(response.Content.Headers.ContentType!.MediaType, Is.EqualTo("application/octet-stream"));
Assert.That(response.Content.Headers.ContentLength, Is.GreaterThan(0));
});
}

[Test]
public async Task DownloadPackage_Get_Success()
{
using HttpClient httpClient = _webApplicationFactory.CreateDefaultClient();

await WaitForInitialization(_webApplicationFactory.Services);

string packageName = $"org.nuget.{UnityNuGetWebApplicationFactory.PackageName.ToLowerInvariant()}";

HttpResponseMessage response = await httpClient.GetAsync($"/{packageName}/-/{packageName}-11.0.1.tgz");

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));

byte[] responseContent = await response.Content.ReadAsByteArrayAsync();

Assert.Multiple(() =>
{
Assert.That(responseContent, Is.Not.Empty);

Assert.That(response.Content.Headers.ContentType!.MediaType, Is.EqualTo("application/octet-stream"));
Assert.That(response.Content.Headers.ContentLength, Is.GreaterThan(0));
});
}

private static async Task WaitForInitialization(IServiceProvider serviceProvider)
{
RegistryCacheSingleton registryCacheSingleton = serviceProvider.GetRequiredService<RegistryCacheSingleton>();

while (registryCacheSingleton.Instance == null)
{
await Task.Delay(25);
}
}
}
}
24 changes: 24 additions & 0 deletions src/UnityNuGet.Server.Tests/UnityNuGet.Server.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<IsPackable>false</IsPackable>
<IsPublishable>false</IsPublishable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="nunit" />
<PackageReference Include="NUnit.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NUnit3TestAdapter" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\UnityNuGet.Server\UnityNuGet.Server.csproj" />
</ItemGroup>

</Project>
34 changes: 34 additions & 0 deletions src/UnityNuGet.Server.Tests/UnityNuGetWebApplicationFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace UnityNuGet.Server.Tests
{
internal class UnityNuGetWebApplicationFactory : WebApplicationFactory<Program>
{
public const string PackageName = "Newtonsoft.Json";

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
base.ConfigureWebHost(builder);

builder.ConfigureAppConfiguration(builder =>
{
builder.AddInMemoryCollection(new Dictionary<string, string?>
{
{ WebHostDefaults.ServerUrlsKey, "http://localhost" }
});
});

builder.ConfigureServices(services =>
{
services.Configure<RegistryOptions>(options =>
{
options.Filter = PackageName;
});
});
}
}
}
Loading
Loading