up
Some checks failed
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
This commit is contained in:
@@ -185,6 +185,8 @@ public sealed class MigrationRunner : IMigrationRunner
|
||||
await using var connection = new NpgsqlConnection(_connectionString);
|
||||
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await EnsureSchemaAsync(connection, cancellationToken).ConfigureAwait(false);
|
||||
await SetSearchPathAsync(connection, cancellationToken).ConfigureAwait(false);
|
||||
// Coordination: advisory lock to avoid concurrent runners
|
||||
var lockKey = ComputeLockKey(SchemaName);
|
||||
var lockAcquired = await TryAcquireLockAsync(connection, lockKey, cancellationToken).ConfigureAwait(false);
|
||||
@@ -197,7 +199,6 @@ public sealed class MigrationRunner : IMigrationRunner
|
||||
|
||||
try
|
||||
{
|
||||
await EnsureSchemaAsync(connection, cancellationToken).ConfigureAwait(false);
|
||||
await EnsureMigrationsTableAsync(connection, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var applied = await GetAppliedMigrationsAsync(connection, cancellationToken).ConfigureAwait(false);
|
||||
@@ -317,12 +318,27 @@ public sealed class MigrationRunner : IMigrationRunner
|
||||
|
||||
private async Task EnsureSchemaAsync(NpgsqlConnection connection, CancellationToken cancellationToken)
|
||||
{
|
||||
var schemaName = QuoteIdentifier(SchemaName);
|
||||
|
||||
await using var command = new NpgsqlCommand(
|
||||
$"CREATE SCHEMA IF NOT EXISTS {SchemaName};",
|
||||
$"CREATE SCHEMA IF NOT EXISTS {schemaName};",
|
||||
connection);
|
||||
await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task SetSearchPathAsync(NpgsqlConnection connection, CancellationToken cancellationToken)
|
||||
{
|
||||
var quotedSchema = QuoteIdentifier(SchemaName);
|
||||
await using var command = new NpgsqlCommand($"SET search_path TO {quotedSchema}, public;", connection);
|
||||
await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static string QuoteIdentifier(string identifier)
|
||||
{
|
||||
var escaped = identifier.Replace("\"", "\"\"", StringComparison.Ordinal);
|
||||
return $"\"{escaped}\"";
|
||||
}
|
||||
|
||||
private async Task EnsureMigrationsTableAsync(NpgsqlConnection connection, CancellationToken cancellationToken)
|
||||
{
|
||||
await using var command = new NpgsqlCommand(
|
||||
|
||||
@@ -92,7 +92,12 @@ public sealed class PostgresFixture : IAsyncDisposable
|
||||
moduleName,
|
||||
_logger);
|
||||
|
||||
await runner.RunAsync(migrationsPath, cancellationToken).ConfigureAwait(false);
|
||||
var result = await runner.RunAsync(
|
||||
migrationsPath,
|
||||
options: null,
|
||||
cancellationToken: cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
EnsureSuccess(result, moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -114,7 +119,12 @@ public sealed class PostgresFixture : IAsyncDisposable
|
||||
moduleName,
|
||||
_logger);
|
||||
|
||||
await runner.RunFromAssemblyAsync(assembly, resourcePrefix, cancellationToken).ConfigureAwait(false);
|
||||
var result = await runner.RunFromAssemblyAsync(
|
||||
assembly,
|
||||
resourcePrefix,
|
||||
options: null,
|
||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
EnsureSuccess(result, moduleName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -203,6 +213,20 @@ public sealed class PostgresFixture : IAsyncDisposable
|
||||
_logger.LogWarning(ex, "Failed to drop test schema: {Schema}", _schemaName);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureSuccess(MigrationResult result, string moduleName)
|
||||
{
|
||||
if (result.Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var details = result.ChecksumErrors.Count > 0
|
||||
? $"{result.ErrorMessage ?? "Migration failure"} | checksum errors: {string.Join("; ", result.ChecksumErrors)}"
|
||||
: result.ErrorMessage ?? "Migration failure";
|
||||
|
||||
throw new InvalidOperationException($"Failed to run migrations for {moduleName}: {details}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user