texts fixes, search bar fixes, global menu fixes.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
|
||||
namespace StellaOps.PacksRegistry.Tests;
|
||||
|
||||
[Collection(PacksRegistryStartupEnvironmentCollection.Name)]
|
||||
public sealed class PacksRegistryStartupContractTests
|
||||
{
|
||||
[Fact]
|
||||
public void Startup_FailsWithoutPostgresConnectionString_InProduction()
|
||||
{
|
||||
using var environment = PacksRegistryStartupEnvironmentScope.ProductionPostgresWithoutConnection();
|
||||
using var factory = new WebApplicationFactory<Program>();
|
||||
|
||||
var exception = Assert.ThrowsAny<Exception>(() =>
|
||||
{
|
||||
using var client = factory.CreateClient();
|
||||
});
|
||||
|
||||
Assert.Contains(
|
||||
"PacksRegistry requires PostgreSQL connection settings in non-development mode.",
|
||||
exception.ToString(),
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Startup_RejectsRustFsObjectStoreDriver()
|
||||
{
|
||||
using var environment = PacksRegistryStartupEnvironmentScope.ProductionWithObjectStoreDriver("rustfs");
|
||||
using var factory = new WebApplicationFactory<Program>();
|
||||
|
||||
var exception = Assert.ThrowsAny<Exception>(() =>
|
||||
{
|
||||
using var client = factory.CreateClient();
|
||||
});
|
||||
|
||||
Assert.Contains(
|
||||
"RustFS object store is configured for PacksRegistry, but no RustFS adapter is implemented.",
|
||||
exception.ToString(),
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Startup_RejectsUnsupportedObjectStoreDriver()
|
||||
{
|
||||
using var environment = PacksRegistryStartupEnvironmentScope.ProductionWithObjectStoreDriver("unknown-store");
|
||||
using var factory = new WebApplicationFactory<Program>();
|
||||
|
||||
var exception = Assert.ThrowsAny<Exception>(() =>
|
||||
{
|
||||
using var client = factory.CreateClient();
|
||||
});
|
||||
|
||||
Assert.Contains(
|
||||
"Unsupported object store driver 'unknown-store' for PacksRegistry. Allowed values: seed-fs.",
|
||||
exception.ToString(),
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Startup_AllowsSeedFsObjectStoreDriver()
|
||||
{
|
||||
using var environment = PacksRegistryStartupEnvironmentScope.TestingInMemorySeedFs();
|
||||
using var factory = new WebApplicationFactory<Program>();
|
||||
|
||||
using var client = factory.CreateClient();
|
||||
var response = await client.GetAsync("/healthz", TestContext.Current.CancellationToken);
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
namespace StellaOps.PacksRegistry.Tests;
|
||||
|
||||
[CollectionDefinition(Name, DisableParallelization = true)]
|
||||
public sealed class PacksRegistryStartupEnvironmentCollection
|
||||
{
|
||||
public const string Name = "PacksRegistryStartupEnvironment";
|
||||
}
|
||||
|
||||
internal sealed class PacksRegistryStartupEnvironmentScope : IDisposable
|
||||
{
|
||||
private static readonly string[] ManagedKeys =
|
||||
[
|
||||
"DOTNET_ENVIRONMENT",
|
||||
"ASPNETCORE_ENVIRONMENT",
|
||||
"STORAGE__DRIVER",
|
||||
"PACKSREGISTRY__STORAGE__DRIVER",
|
||||
"STORAGE__OBJECTSTORE__DRIVER",
|
||||
"PACKSREGISTRY__STORAGE__OBJECTSTORE__DRIVER",
|
||||
"STORAGE__POSTGRES__CONNECTIONSTRING",
|
||||
"PACKSREGISTRY__STORAGE__POSTGRES__CONNECTIONSTRING",
|
||||
"CONNECTIONSTRINGS__PACKSREGISTRY",
|
||||
"CONNECTIONSTRINGS__DEFAULT"
|
||||
];
|
||||
|
||||
private readonly Dictionary<string, string?> _originalValues = new(StringComparer.Ordinal);
|
||||
|
||||
private PacksRegistryStartupEnvironmentScope()
|
||||
{
|
||||
foreach (var key in ManagedKeys)
|
||||
{
|
||||
_originalValues[key] = Environment.GetEnvironmentVariable(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static PacksRegistryStartupEnvironmentScope ProductionPostgresWithoutConnection()
|
||||
{
|
||||
var scope = new PacksRegistryStartupEnvironmentScope();
|
||||
scope.Set("DOTNET_ENVIRONMENT", "Production");
|
||||
scope.Set("ASPNETCORE_ENVIRONMENT", "Production");
|
||||
scope.Set("STORAGE__DRIVER", "postgres");
|
||||
scope.Set("PACKSREGISTRY__STORAGE__DRIVER", "postgres");
|
||||
scope.Set("PACKSREGISTRY__STORAGE__OBJECTSTORE__DRIVER", "seed-fs");
|
||||
scope.Set("STORAGE__OBJECTSTORE__DRIVER", "seed-fs");
|
||||
scope.Set("STORAGE__POSTGRES__CONNECTIONSTRING", null);
|
||||
scope.Set("PACKSREGISTRY__STORAGE__POSTGRES__CONNECTIONSTRING", null);
|
||||
scope.Set("CONNECTIONSTRINGS__PACKSREGISTRY", null);
|
||||
scope.Set("CONNECTIONSTRINGS__DEFAULT", null);
|
||||
return scope;
|
||||
}
|
||||
|
||||
public static PacksRegistryStartupEnvironmentScope ProductionWithObjectStoreDriver(string objectStoreDriver)
|
||||
{
|
||||
var scope = new PacksRegistryStartupEnvironmentScope();
|
||||
scope.Set("DOTNET_ENVIRONMENT", "Production");
|
||||
scope.Set("ASPNETCORE_ENVIRONMENT", "Production");
|
||||
scope.Set("STORAGE__DRIVER", "postgres");
|
||||
scope.Set("PACKSREGISTRY__STORAGE__DRIVER", "postgres");
|
||||
scope.Set("PACKSREGISTRY__STORAGE__OBJECTSTORE__DRIVER", objectStoreDriver);
|
||||
scope.Set("STORAGE__OBJECTSTORE__DRIVER", objectStoreDriver);
|
||||
var connectionString = "Host=localhost;Database=stellaops_packs;Username=stellaops;Password=stellaops";
|
||||
scope.Set("STORAGE__POSTGRES__CONNECTIONSTRING", connectionString);
|
||||
scope.Set("PACKSREGISTRY__STORAGE__POSTGRES__CONNECTIONSTRING", connectionString);
|
||||
scope.Set("CONNECTIONSTRINGS__PACKSREGISTRY", connectionString);
|
||||
scope.Set("CONNECTIONSTRINGS__DEFAULT", connectionString);
|
||||
return scope;
|
||||
}
|
||||
|
||||
public static PacksRegistryStartupEnvironmentScope TestingInMemorySeedFs()
|
||||
{
|
||||
var scope = new PacksRegistryStartupEnvironmentScope();
|
||||
scope.Set("DOTNET_ENVIRONMENT", "Testing");
|
||||
scope.Set("ASPNETCORE_ENVIRONMENT", "Testing");
|
||||
scope.Set("STORAGE__DRIVER", "inmemory");
|
||||
scope.Set("PACKSREGISTRY__STORAGE__DRIVER", "inmemory");
|
||||
scope.Set("PACKSREGISTRY__STORAGE__OBJECTSTORE__DRIVER", "seed-fs");
|
||||
scope.Set("STORAGE__OBJECTSTORE__DRIVER", "seed-fs");
|
||||
scope.Set("STORAGE__POSTGRES__CONNECTIONSTRING", null);
|
||||
scope.Set("PACKSREGISTRY__STORAGE__POSTGRES__CONNECTIONSTRING", null);
|
||||
scope.Set("CONNECTIONSTRINGS__PACKSREGISTRY", null);
|
||||
scope.Set("CONNECTIONSTRINGS__DEFAULT", null);
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var entry in _originalValues)
|
||||
{
|
||||
Environment.SetEnvironmentVariable(entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void Set(string key, string? value)
|
||||
{
|
||||
Environment.SetEnvironmentVariable(key, value);
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,4 @@ Source of truth: `docs-archived/implplan/2025-12-29-csproj-audit/SPRINT_20251229
|
||||
| AUDIT-0432-T | DONE | Revalidated 2026-01-07; test coverage audit for StellaOps.PacksRegistry.Tests. |
|
||||
| AUDIT-0432-A | DONE | Waived (test project; revalidated 2026-01-07). |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
| SPRINT-20260305-002 | DONE | Added `PacksRegistryStartupContractTests` covering postgres missing-connection fail-fast and seed-fs/rustfs object-store contract enforcement. |
|
||||
|
||||
@@ -73,8 +73,6 @@ else
|
||||
}
|
||||
|
||||
ValidateObjectStoreContract(
|
||||
builder.Configuration,
|
||||
builder.Environment.IsDevelopment(),
|
||||
"PacksRegistry",
|
||||
objectStoreDriver);
|
||||
|
||||
@@ -925,38 +923,21 @@ static string ResolveObjectStoreDriver(IConfiguration configuration, string serv
|
||||
}
|
||||
|
||||
static void ValidateObjectStoreContract(
|
||||
IConfiguration configuration,
|
||||
bool isDevelopment,
|
||||
string serviceName,
|
||||
string objectStoreDriver)
|
||||
{
|
||||
if (!string.Equals(objectStoreDriver, "rustfs", StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals(objectStoreDriver, "seed-fs", StringComparison.OrdinalIgnoreCase))
|
||||
if (!string.Equals(objectStoreDriver, "seed-fs", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (string.Equals(objectStoreDriver, "rustfs", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"RustFS object store is configured for {serviceName}, but no RustFS adapter is implemented. " +
|
||||
"Use seed-fs.");
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
$"Unsupported object store driver '{objectStoreDriver}' for {serviceName}. " +
|
||||
"Allowed values: rustfs, seed-fs.");
|
||||
}
|
||||
|
||||
if (!string.Equals(objectStoreDriver, "rustfs", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isDevelopment)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"RustFS object store is configured for {serviceName}, but the RustFS adapter is not implemented yet. " +
|
||||
"Use seed-fs until RustFS adapter support lands.");
|
||||
}
|
||||
|
||||
var rustFsBaseUrl = FirstNonEmpty(
|
||||
configuration[$"{serviceName}:Storage:ObjectStore:RustFs:BaseUrl"],
|
||||
configuration["Storage:ObjectStore:RustFs:BaseUrl"]);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rustFsBaseUrl))
|
||||
{
|
||||
return;
|
||||
"Allowed values: seed-fs.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,3 +10,4 @@ Source of truth: `docs-archived/implplan/2025-12-29-csproj-audit/SPRINT_20251229
|
||||
| AUDIT-0433-A | TODO | Revalidated 2026-01-07 (open findings). |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
| SPRINT-312-003 | DONE | Postgres-first storage driver migration with seed-fs payload contract wired in Program startup (pack/provenance/attestation payload channel). |
|
||||
| SPRINT-20260305-002 | DONE | Finalized startup contract: seed-fs is the only accepted object-store driver; rustfs/unknown drivers fail fast with deterministic error messages. |
|
||||
|
||||
Reference in New Issue
Block a user