Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.

This commit is contained in:
StellaOps Bot
2025-12-26 21:54:17 +02:00
parent 335ff7da16
commit c2b9cd8d1f
3717 changed files with 264714 additions and 48202 deletions

View File

@@ -0,0 +1,27 @@
using System.Reflection;
using StellaOps.Infrastructure.Postgres.Testing;
using StellaOps.PacksRegistry.Persistence.Postgres;
using Xunit;
namespace StellaOps.PacksRegistry.Persistence.Tests;
/// <summary>
/// PostgreSQL integration test fixture for the PacksRegistry module.
/// </summary>
public sealed class PacksRegistryPostgresFixture : PostgresIntegrationFixture, ICollectionFixture<PacksRegistryPostgresFixture>
{
protected override Assembly? GetMigrationAssembly()
=> typeof(PacksRegistryDataSource).Assembly;
protected override string GetModuleName() => "PacksRegistry";
}
/// <summary>
/// Collection definition for PacksRegistry PostgreSQL integration tests.
/// Tests in this collection share a single PostgreSQL container instance.
/// </summary>
[CollectionDefinition(Name)]
public sealed class PacksRegistryPostgresCollection : ICollectionFixture<PacksRegistryPostgresFixture>
{
public const string Name = "PacksRegistryPostgres";
}

View File

@@ -0,0 +1,161 @@
using System.Text;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using MicrosoftOptions = Microsoft.Extensions.Options;
using StellaOps.PacksRegistry.Core.Models;
using StellaOps.PacksRegistry.Persistence.Postgres;
using StellaOps.PacksRegistry.Persistence.Postgres.Repositories;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.PacksRegistry.Persistence.Tests;
[Collection(PacksRegistryPostgresCollection.Name)]
public sealed class PostgresPackRepositoryTests : IAsyncLifetime
{
private readonly PacksRegistryPostgresFixture _fixture;
private readonly PostgresPackRepository _repository;
private readonly string _tenantId = "tenant-" + Guid.NewGuid().ToString("N")[..8];
public PostgresPackRepositoryTests(PacksRegistryPostgresFixture fixture)
{
_fixture = fixture;
var options = fixture.Fixture.CreateOptions();
options.SchemaName = fixture.SchemaName;
var dataSource = new PacksRegistryDataSource(MicrosoftOptions.Options.Create(options), NullLogger<PacksRegistryDataSource>.Instance);
_repository = new PostgresPackRepository(dataSource, NullLogger<PostgresPackRepository>.Instance);
}
public async Task InitializeAsync()
{
await _fixture.TruncateAllTablesAsync();
}
public Task DisposeAsync() => Task.CompletedTask;
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task UpsertAndGet_RoundTripsPackRecord()
{
// Arrange
var packId = "pack-" + Guid.NewGuid().ToString("N");
var record = new PackRecord(
PackId: packId,
Name: "test-pack",
Version: "1.0.0",
TenantId: _tenantId,
Digest: "sha256:abc123",
Signature: "sig123",
ProvenanceUri: "https://example.com/provenance",
ProvenanceDigest: "sha256:prov456",
CreatedAtUtc: DateTimeOffset.UtcNow,
Metadata: new Dictionary<string, string> { ["author"] = "test" });
var content = Encoding.UTF8.GetBytes("pack content here");
var provenance = Encoding.UTF8.GetBytes("provenance data");
// Act
await _repository.UpsertAsync(record, content, provenance);
var fetched = await _repository.GetAsync(packId);
// Assert
fetched.Should().NotBeNull();
fetched!.PackId.Should().Be(packId);
fetched.Name.Should().Be("test-pack");
fetched.Version.Should().Be("1.0.0");
fetched.TenantId.Should().Be(_tenantId);
fetched.Metadata.Should().ContainKey("author");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task GetContentAsync_ReturnsPackContent()
{
// Arrange
var packId = "pack-" + Guid.NewGuid().ToString("N");
var record = CreatePackRecord(packId, "content-test", "1.0.0");
var expectedContent = Encoding.UTF8.GetBytes("this is the pack content");
await _repository.UpsertAsync(record, expectedContent, null);
// Act
var content = await _repository.GetContentAsync(packId);
// Assert
content.Should().NotBeNull();
Encoding.UTF8.GetString(content!).Should().Be("this is the pack content");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task GetProvenanceAsync_ReturnsProvenanceData()
{
// Arrange
var packId = "pack-" + Guid.NewGuid().ToString("N");
var record = CreatePackRecord(packId, "provenance-test", "1.0.0");
var content = Encoding.UTF8.GetBytes("content");
var expectedProvenance = Encoding.UTF8.GetBytes("provenance statement");
await _repository.UpsertAsync(record, content, expectedProvenance);
// Act
var provenance = await _repository.GetProvenanceAsync(packId);
// Assert
provenance.Should().NotBeNull();
Encoding.UTF8.GetString(provenance!).Should().Be("provenance statement");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ListAsync_ReturnsPacksForTenant()
{
// Arrange
var pack1 = CreatePackRecord("pack-1-" + Guid.NewGuid().ToString("N")[..8], "pack-a", "1.0.0");
var pack2 = CreatePackRecord("pack-2-" + Guid.NewGuid().ToString("N")[..8], "pack-b", "2.0.0");
var content = Encoding.UTF8.GetBytes("content");
await _repository.UpsertAsync(pack1, content, null);
await _repository.UpsertAsync(pack2, content, null);
// Act
var packs = await _repository.ListAsync(_tenantId);
// Assert
packs.Should().HaveCount(2);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task UpsertAsync_UpdatesExistingPack()
{
// Arrange
var packId = "pack-" + Guid.NewGuid().ToString("N");
var record1 = CreatePackRecord(packId, "original", "1.0.0");
var record2 = CreatePackRecord(packId, "updated", "2.0.0");
var content = Encoding.UTF8.GetBytes("content");
// Act
await _repository.UpsertAsync(record1, content, null);
await _repository.UpsertAsync(record2, content, null);
var fetched = await _repository.GetAsync(packId);
// Assert
fetched.Should().NotBeNull();
fetched!.Name.Should().Be("updated");
fetched.Version.Should().Be("2.0.0");
}
private PackRecord CreatePackRecord(string packId, string name, string version) =>
new(
PackId: packId,
Name: name,
Version: version,
TenantId: _tenantId,
Digest: "sha256:" + Guid.NewGuid().ToString("N"),
Signature: null,
ProvenanceUri: null,
ProvenanceDigest: null,
CreatedAtUtc: DateTimeOffset.UtcNow,
Metadata: null);
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>preview</LangVersion>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<RootNamespace>StellaOps.PacksRegistry.Persistence.Tests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Options" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\__Libraries\StellaOps.PacksRegistry.Persistence\StellaOps.PacksRegistry.Persistence.csproj" />
<ProjectReference Include="..\..\..\__Tests\__Libraries\StellaOps.Infrastructure.Postgres.Testing\StellaOps.Infrastructure.Postgres.Testing.csproj" />
<ProjectReference Include="..\..\..\__Libraries\StellaOps.TestKit\StellaOps.TestKit.csproj" />
</ItemGroup>
</Project>