From 481a062a1a7a5c0cef3c706072fc9b4da28fcb49 Mon Sep 17 00:00:00 2001 From: master <> Date: Mon, 9 Mar 2026 07:53:24 +0200 Subject: [PATCH] fix(jobengine): register startup migrations for orchestrator schema Wire AddStartupMigrations so JobEngine converges the orchestrator schema on fresh database or wiped volumes without manual bootstrap scripts. Adds StellaOps.Infrastructure.Postgres.Migrations dependency. Co-Authored-By: Claude Opus 4.6 --- .../ServiceCollectionExtensions.cs | 7 ++++ .../StellaOps.JobEngine.Infrastructure.csproj | 1 + ...obEngineInfrastructureRegistrationTests.cs | 33 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Tests/Infrastructure/JobEngineInfrastructureRegistrationTests.cs diff --git a/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Infrastructure/ServiceCollectionExtensions.cs b/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Infrastructure/ServiceCollectionExtensions.cs index 103afa4a3..27cbec384 100644 --- a/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Infrastructure/ServiceCollectionExtensions.cs +++ b/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Infrastructure/ServiceCollectionExtensions.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Npgsql; +using StellaOps.Infrastructure.Postgres.Migrations; using StellaOps.JobEngine.Core.Backfill; using StellaOps.JobEngine.Core.DeadLetter; using StellaOps.JobEngine.Core.Observability; @@ -54,6 +55,12 @@ public static class ServiceCollectionExtensions } }); + services.AddStartupMigrations( + schemaName: "orchestrator", + moduleName: "JobEngine", + migrationsAssembly: typeof(JobEngineDataSource).Assembly, + connectionStringSelector: options => options.Database.ConnectionString); + // Register data source services.AddSingleton(); diff --git a/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Infrastructure/StellaOps.JobEngine.Infrastructure.csproj b/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Infrastructure/StellaOps.JobEngine.Infrastructure.csproj index 566f68cf5..dab123668 100644 --- a/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Infrastructure/StellaOps.JobEngine.Infrastructure.csproj +++ b/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Infrastructure/StellaOps.JobEngine.Infrastructure.csproj @@ -20,6 +20,7 @@ + diff --git a/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Tests/Infrastructure/JobEngineInfrastructureRegistrationTests.cs b/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Tests/Infrastructure/JobEngineInfrastructureRegistrationTests.cs new file mode 100644 index 000000000..1d5742ba7 --- /dev/null +++ b/src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Tests/Infrastructure/JobEngineInfrastructureRegistrationTests.cs @@ -0,0 +1,33 @@ +using FluentAssertions; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using StellaOps.JobEngine.Infrastructure; +using StellaOps.TestKit; + +namespace StellaOps.JobEngine.Tests.Infrastructure; + +public sealed class JobEngineInfrastructureRegistrationTests +{ + [Trait("Category", TestCategories.Unit)] + [Fact] + public void AddJobEngineInfrastructure_RegistersStartupMigrationHost() + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + ["JobEngine:Database:ConnectionString"] = "Host=postgres;Database=stellaops;Username=postgres;Password=postgres" + }) + .Build(); + + var services = new ServiceCollection(); + services.AddLogging(); + + services.AddJobEngineInfrastructure(configuration); + + services + .Where(descriptor => descriptor.ServiceType == typeof(IHostedService)) + .Should() + .ContainSingle("clean-reset installs need JobEngine startup migrations to create the orchestrator schema before serving traffic"); + } +}