Skip to content

Commit

Permalink
Bug #553: Baseline creates orphan version_id in ScriptsRun
Browse files Browse the repository at this point in the history
When running in baseline mode, no SQL is actually run, so there was not inserted any entry
into the Version table. However, this should be inserted in baseline mode, as this makes sense
business-wise, to register the baseline as a version of the database (even with no changes)

Fixes #553
  • Loading branch information
erikbra committed Jul 24, 2024
1 parent 8b45ba0 commit 9b744d8
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 7 deletions.
12 changes: 5 additions & 7 deletions src/grate.core/Migration/GrateMigrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,7 @@ public async Task Migrate()
// Run these first without a transaction, to make sure the tables are created even on a potential rollback
await CreateGrateStructure(dbMigrator);

string? newVersion;
long versionId;
(versionId, newVersion) = await VersionTheDatabase(dbMigrator);
var (versionId, newVersion) = await VersionTheDatabase(dbMigrator);

Separator('=');
_logger.LogInformation("Migration Scripts");
Expand Down Expand Up @@ -211,17 +209,17 @@ public async Task Migrate()
// TODO: Clean up the try - catch here - it's only used in initial bootstrapping if the
// TODO: version table _does_ exist, but it doesn't have the version table.
// TODO: This will be just once for each of legacy RoundhousE databases migrated to grate.

try
{
//If we get here this means no exceptions are thrown above, so we can conclude the migration was successful!
if (anySqlRun)
if (anySqlRun || config.Baseline)
{
await DbMigrator.Database.ChangeVersionStatus(MigrationStatus.Finished, versionId);
}
else
{
// as we have an issue with the versioning table, we need to delete the version record
// Delete the version record if no actual migration was performed, to avoid having a lot of "no-op"
// migrations if grate is run a lot without any changes
await DbMigrator.Database.DeleteVersionRecord(versionId);
}
}
Expand Down Expand Up @@ -637,7 +635,7 @@ private async Task<GrateConfiguration> GetInternalGrateConfiguration(string inte
// If they do, check if the tables are already logged as run in their own tables.
// If they are, the tables are already known to grate. If they are not, the tables are created by RoundhousE, or
// an earlier version of grate, and we need to run in baseline mode, to register the scripts as run, without
// actually running them.
// actually running them.
var baseline = internalFolderName == "Baseline"
&& await this.Database.VersionTableExists()
&& !(await this.Database.GrateInternalTablesAreProperlyLogged());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,44 @@ public async Task Logs_internal_scripts_run_in_own_structure(string name)

//await Context.DropDatabase(db);
}

[Fact]
[Trait("Category", "Versioning")]
public async Task A_version_witht_the_current_application_version_is_inserted_into_the_GrateVersion_table()
{
var db = TestConfig.RandomDatabase();
var dbVersion = "1.2.3.1";

var parent = CreateRandomTempDirectory();
var knownFolders = Folders.Default;
CreateDummySql(parent, knownFolders[Up]);

var config = GrateConfigurationBuilder.Create(Context.DefaultConfiguration)
.WithConnectionString(Context.ConnectionString(db))
.WithFolders(knownFolders)
.WithSqlFilesDirectory(parent)
.WithVersion(dbVersion)
.Build();

await using (var migrator = Context.Migrator.WithConfiguration(config))
{
await migrator.Migrate();
}

IEnumerable<(string version, string status)> entries;
string sql = $"SELECT version, status FROM {Context.Syntax.TableWithSchema("grate", "GrateVersion")}";

using (var conn = Context.CreateDbConnection(db))
{
entries = (await conn.QueryAsync<(string version, string status)>(sql)).ToArray();
}

entries.Should().HaveCount(1);
var version = entries.Single();
version.version.Should().Be(ApplicationInfo.Version);
version.status.Should().Be(MigrationStatus.Finished);
}


// This was failing, because the tokens were already replaced before the internal scripts were run,
// and the tokens were lazily initialized. So we had to clear the tokens when running the internal scripts.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,81 @@ public async Task Creates_a_new_version_with_status_InProgress()

//await Context.DropDatabase(db);
}

[Fact]
[Trait("Category", "Versioning")]
public async Task Migrating_creates_a_new_version_record()
{
var db = TestConfig.RandomDatabase();
var dbVersion = "1.2.3.1";

var parent = CreateRandomTempDirectory();
var knownFolders = Folders.Default;
CreateDummySql(parent, knownFolders[Up]);

var config = GrateConfigurationBuilder.Create(Context.DefaultConfiguration)
.WithConnectionString(Context.ConnectionString(db))
.WithFolders(knownFolders)
.WithSqlFilesDirectory(parent)
.WithVersion(dbVersion)
.Build();

await using (var migrator = Context.Migrator.WithConfiguration(config))
{
await migrator.Migrate();
}

IEnumerable<(string version, string status)> entries;
string sql = $"SELECT version, status FROM {Context.Syntax.TableWithSchema("grate", "Version")}";

using (var conn = Context.CreateDbConnection(db))
{
entries = (await conn.QueryAsync<(string version, string status)>(sql)).ToArray();
}

entries.Should().HaveCount(1);
var version = entries.Single();
version.version.Should().Be(dbVersion);
version.status.Should().Be(MigrationStatus.Finished);
}

[Fact]
[Trait("Category", "Versioning")]
public async Task Migrating_creates_a_new_version_record_even_in_baseline_mode()
{
var db = TestConfig.RandomDatabase();
var dbVersion = "1.2.3.4";

var parent = CreateRandomTempDirectory();
var knownFolders = Folders.Default;
CreateDummySql(parent, knownFolders[Up]);

var config = GrateConfigurationBuilder.Create(Context.DefaultConfiguration)
.WithConnectionString(Context.ConnectionString(db))
.WithFolders(knownFolders)
.WithSqlFilesDirectory(parent)
.WithVersion(dbVersion)
.Baseline()
.Build();

await using (var migrator = Context.Migrator.WithConfiguration(config))
{
await migrator.Migrate();
}

IEnumerable<(string version, string status)> entries;
string sql = $"SELECT version, status FROM {Context.Syntax.TableWithSchema("grate", "Version")}";

using (var conn = Context.CreateDbConnection(db))
{
entries = (await conn.QueryAsync<(string version, string status)>(sql)).ToArray();
}

entries.Should().HaveCount(1);
var version = entries.Single();
version.version.Should().Be(dbVersion);
version.status.Should().Be(MigrationStatus.Finished);
}

[Fact]
[Trait("Category", "Versioning")]
Expand Down

0 comments on commit 9b744d8

Please sign in to comment.