mirror of
https://github.com/MAKS-IT-COM/maksit-certs-ui.git
synced 2026-05-16 04:48:12 +02:00
(bugfix): fluent migrator version info table and columns name s consolidation with the rest of the database tables
This commit is contained in:
parent
bd54f6e6c3
commit
4fc9cfdcea
14
CHANGELOG.md
14
CHANGELOG.md
@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [3.3.19] - 2026-04-26
|
||||
|
||||
### Changed
|
||||
|
||||
- **FluentMigrator / PostgreSQL:** Version metadata table is **`public.version_info`** with snake_case columns **`version`**, **`applied_on`**, **`description`** and unique index **`uc_version`**, configured via **`CertsFluentMigratorVersionTableMetaData`** and **`WithVersionTable`** on the runner (aligned with the rest of the schema naming).
|
||||
|
||||
### Removed
|
||||
|
||||
- **Startup migrations:** Removed legacy compatibility paths: **`VersionInfo` → `version_info` rename**, PascalCase → snake_case column repair on the version table, and the **EF-era baseline** that created or seeded **`version_info`** when **`users`** already existed (and **`RunMigrationsService.BaselineVersion`**).
|
||||
|
||||
### Upgrade notes
|
||||
|
||||
- **Breaking:** **Recreate the Certs engine database** (or use a new empty database). The app no longer upgrades in place from **`VersionInfo`**, mixed column casing, or pre–FluentMigrator-baseline layouts; **`MigrateUp`** expects a clean or fully FluentMigrator-managed schema.
|
||||
|
||||
## [3.3.18] - 2026-04-26
|
||||
|
||||
### Changed
|
||||
|
||||
@ -31,6 +31,7 @@ public static class ServiceCollectionExtensions {
|
||||
.ConfigureRunner(rb => rb
|
||||
.AddPostgres()
|
||||
.WithGlobalConnectionString(certsEngineConfiguration.ConnectionString)
|
||||
.WithVersionTable(new CertsFluentMigratorVersionTableMetaData())
|
||||
.ScanIn(typeof(BaselineCertsSchema).Assembly).For.All())
|
||||
.AddLogging(lb => lb.AddFluentMigratorConsole());
|
||||
services.AddScoped<IRunMigrationsService, RunMigrationsService>();
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
using FluentMigrator.Runner.VersionTableInfo;
|
||||
|
||||
namespace MaksIT.CertsUI.Engine.Infrastructure;
|
||||
|
||||
/// <summary>FluentMigrator version table: snake_case <c>public.version_info</c> (table and columns) for PostgreSQL consistency.</summary>
|
||||
public sealed class CertsFluentMigratorVersionTableMetaData : IVersionTableMetaData {
|
||||
|
||||
public const string Table = "version_info";
|
||||
|
||||
public const string VersionColumn = "version";
|
||||
|
||||
public const string AppliedOnColumn = "applied_on";
|
||||
|
||||
public const string DescriptionColumn = "description";
|
||||
|
||||
public const string UniqueIndex = "uc_version";
|
||||
|
||||
public bool OwnsSchema => true;
|
||||
|
||||
public string SchemaName => "public";
|
||||
|
||||
public string TableName => Table;
|
||||
|
||||
public string ColumnName => VersionColumn;
|
||||
|
||||
public string DescriptionColumnName => DescriptionColumn;
|
||||
|
||||
public string UniqueIndexName => UniqueIndex;
|
||||
|
||||
public string AppliedOnColumnName => AppliedOnColumn;
|
||||
|
||||
public bool CreateWithPrimaryKey => false;
|
||||
}
|
||||
@ -8,7 +8,7 @@ using Npgsql;
|
||||
namespace MaksIT.CertsUI.Engine.Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
/// FluentMigrator runner for the Certs database: optionally creates the database, baselines legacy EF-created schemas, migrates up,
|
||||
/// FluentMigrator runner for the Certs database: optionally creates the database, migrates up,
|
||||
/// then idempotent coordination-table repair. Forward <c>Up()</c> migrations should be additive (new tables/columns); avoid dropping
|
||||
/// renamed or legacy columns in <c>Up()</c> — use expand/contract and ops-driven cleanup.
|
||||
/// </summary>
|
||||
@ -18,8 +18,6 @@ public sealed class RunMigrationsService(
|
||||
ICertsEngineConfiguration config
|
||||
) : IRunMigrationsService {
|
||||
|
||||
public static long BaselineVersion => BaselineCertsSchema.Version;
|
||||
|
||||
public async Task RunAsync(CancellationToken cancellationToken = default) {
|
||||
if (string.IsNullOrWhiteSpace(config.ConnectionString))
|
||||
throw new InvalidOperationException(
|
||||
@ -36,7 +34,6 @@ public sealed class RunMigrationsService(
|
||||
logger.LogInformation("FluentMigrator discovered {MigrationCount} migration type(s) in {Assembly}.", migrationTypeCount, typeof(BaselineCertsSchema).Assembly.GetName().Name);
|
||||
|
||||
await EnsureDatabaseExistsAsync(cancellationToken).ConfigureAwait(false);
|
||||
await BaselineExistingEfDatabaseAsync(cancellationToken).ConfigureAwait(false);
|
||||
await Task.Run(() => migrationRunner.MigrateUp(), cancellationToken).ConfigureAwait(false);
|
||||
await CoordinationTableProvisioner.EnsureAsync(config.ConnectionString, cancellationToken).ConfigureAwait(false);
|
||||
await VerifyCoreSchemaAsync(cancellationToken).ConfigureAwait(false);
|
||||
@ -54,7 +51,7 @@ public sealed class RunMigrationsService(
|
||||
EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'app_runtime_leases')
|
||||
AND (
|
||||
EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'users')
|
||||
OR EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'VersionInfo')
|
||||
OR EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'version_info')
|
||||
);
|
||||
""",
|
||||
conn);
|
||||
@ -64,7 +61,7 @@ public sealed class RunMigrationsService(
|
||||
return;
|
||||
|
||||
throw new InvalidOperationException(
|
||||
"After migrations and coordination DDL, schema \"public\" is missing \"app_runtime_leases\" and/or core tables (\"users\" / \"VersionInfo\"). " +
|
||||
"After migrations and coordination DDL, schema \"public\" is missing \"app_runtime_leases\" and/or core tables (\"users\" / \"version_info\"). " +
|
||||
"Confirm Database= in the connection string, role CREATE privileges, and that FluentMigrator committed (non-empty connection string).");
|
||||
}
|
||||
|
||||
@ -103,42 +100,4 @@ public sealed class RunMigrationsService(
|
||||
database);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the database already has Certs tables from legacy EF Core migrations, mark the FluentMigrator baseline as applied.
|
||||
/// </summary>
|
||||
private async Task BaselineExistingEfDatabaseAsync(CancellationToken cancellationToken) {
|
||||
await using var conn = new NpgsqlConnection(config.ConnectionString);
|
||||
await conn.OpenAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await using (var cmd = new NpgsqlCommand(
|
||||
"SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'users' LIMIT 1",
|
||||
conn)) {
|
||||
await using var reader = await cmd.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
|
||||
return;
|
||||
}
|
||||
|
||||
logger.LogInformation("Existing Certs schema detected; baselining FluentMigrator VersionInfo if needed.");
|
||||
|
||||
await using (var cmd = new NpgsqlCommand(@"
|
||||
CREATE TABLE IF NOT EXISTS ""VersionInfo"" (
|
||||
""Version"" bigint NOT NULL PRIMARY KEY,
|
||||
""AppliedOn"" timestamp NULL,
|
||||
""Description"" varchar(1024) NULL
|
||||
)", conn)) {
|
||||
await cmd.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await using (var cmd = new NpgsqlCommand(
|
||||
@"INSERT INTO ""VersionInfo"" (""Version"", ""AppliedOn"", ""Description"")
|
||||
VALUES (@v, @appliedOn, @desc)
|
||||
ON CONFLICT (""Version"") DO NOTHING",
|
||||
conn)) {
|
||||
cmd.Parameters.AddWithValue("v", BaselineCertsSchema.Version);
|
||||
cmd.Parameters.AddWithValue("appliedOn", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("desc", "BaselineCertsSchema (existing DB from EF Core)");
|
||||
await cmd.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>3.3.18</Version>
|
||||
<Version>3.3.19</Version>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user