From fbede956e943c95861c2ee5f3ce15a3917dbcad6 Mon Sep 17 00:00:00 2001 From: Aaron Po Date: Sat, 12 Sep 2026 17:11:02 -0400 Subject: [PATCH] Fix seed pipeline crash and make seeding failures fail CI (#309) --- .github/workflows/tests.yml | 2 +- web/backend/Database/Database.Seed/Program.cs | 13 ++++--- .../Sqlite/PipelineSeedDataReader.cs | 38 +++++++++---------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index aaba03c0..d24adbc0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,7 +33,7 @@ jobs: if: always() run: | status=0 - for name in test-env-api-specs test-env-unit-tests test-env-frontend-tests; do + for name in test-env-database-migrations test-env-database-seed test-env-api-specs test-env-unit-tests test-env-frontend-tests; do code="$(docker inspect -f '{{.State.ExitCode}}' "$name" 2>/dev/null || echo 1)" echo "$name exited with $code" if [ "$code" != "0" ]; then diff --git a/web/backend/Database/Database.Seed/Program.cs b/web/backend/Database/Database.Seed/Program.cs index dbfad0cb..7c127b41 100644 --- a/web/backend/Database/Database.Seed/Program.cs +++ b/web/backend/Database/Database.Seed/Program.cs @@ -19,7 +19,7 @@ namespace Database.Seed; internal class Program { - private static IMediator CreateMediator() + private static ServiceProvider BuildServiceProvider() { IConfiguration configuration = new ConfigurationBuilder().AddEnvironmentVariables().Build(); @@ -38,11 +38,10 @@ internal class Program .RegisterServicesFromAssemblyContaining() ); - using ServiceProvider provider = services.BuildServiceProvider(); - return provider.GetRequiredService(); + return services.BuildServiceProvider(); } - public static async Task Main() + public static async Task Main() { using CancellationTokenSource cts = new(); Console.CancelKeyPress += (_, e) => @@ -54,20 +53,24 @@ internal class Program try { - IMediator mediator = CreateMediator(); + await using ServiceProvider provider = BuildServiceProvider(); + IMediator mediator = provider.GetRequiredService(); SeedRepository reader = new SeedRepository( connectionString: "Data Source=SeedData/biergarten_seed_2026-08-25T20-45-50.697244Z.sqlite" ); await new BiergartenDataSeeder(mediator, reader).Run(cts.Token); + return 0; } catch (OperationCanceledException) { AnsiConsole.MarkupLine("[yellow]Seeding cancelled.[/]"); + return 1; } catch (Exception ex) { AnsiConsole.MarkupLine("[red]Seeding failed.[/]"); AnsiConsole.WriteException(ex); + return 1; } } } diff --git a/web/backend/Database/Database.Seed/Sqlite/PipelineSeedDataReader.cs b/web/backend/Database/Database.Seed/Sqlite/PipelineSeedDataReader.cs index 12e715fb..b18580ec 100644 --- a/web/backend/Database/Database.Seed/Sqlite/PipelineSeedDataReader.cs +++ b/web/backend/Database/Database.Seed/Sqlite/PipelineSeedDataReader.cs @@ -58,13 +58,13 @@ public sealed class SeedRepository : IDisposable } private sealed record BreweryRow( - int Id, + long Id, string NameEn, string DescriptionEn, string NameLocal, string DescriptionLocal, - int AddressId, - int CityId, + long AddressId, + long CityId, double Longitude, double Latitude, string AddressLine1, @@ -101,27 +101,27 @@ public sealed class SeedRepository : IDisposable return [.. rows.Select(row => new BreweryResult { - Id = row.Id, + Id = (int)row.Id, NameEn = row.NameEn, DescriptionEn = row.DescriptionEn, NameLocal = row.NameLocal, DescriptionLocal = row.DescriptionLocal, Address = new BreweryAddress { - Id = row.AddressId, - CityId = row.CityId, - BreweryId = row.Id, + Id = (int)row.AddressId, + CityId = (int)row.CityId, + BreweryId = (int)row.Id, Longitude = row.Longitude, Latitude = row.Latitude, AddressLine1 = row.AddressLine1, PostalCode = row.PostalCode, - City = cities[row.CityId], + City = cities[(int)row.CityId], }, })]; } private sealed record UserRow( - int Id, + long Id, string FirstName, string LastName, string Gender, @@ -130,8 +130,8 @@ public sealed class SeedRepository : IDisposable double ActivityWeight, string Email, string DateOfBirth, - int AddressId, - int CityId, + long AddressId, + long CityId, double Longitude, double Latitude ); @@ -172,16 +172,16 @@ public sealed class SeedRepository : IDisposable DateOfBirth = row.DateOfBirth, Address = new UserAddress { - Id = row.AddressId, - CityId = row.CityId, - UserId = row.Id, + Id = (int)row.AddressId, + CityId = (int)row.CityId, + UserId = (int)row.Id, Longitude = row.Longitude, Latitude = row.Latitude, - City = cities[row.CityId], + City = cities[(int)row.CityId], }, User = new UserResult { - Id = row.Id, + Id = (int)row.Id, FirstName = row.FirstName, LastName = row.LastName, Gender = row.Gender, @@ -193,7 +193,7 @@ public sealed class SeedRepository : IDisposable } private sealed record CityRow( - int Id, + long Id, string CityName, string StateProvince, string Iso31662, @@ -231,10 +231,10 @@ public sealed class SeedRepository : IDisposable IEnumerable rows = await connection.QueryAsync(command); return rows.ToDictionary( - row => row.Id, + row => (int)row.Id, row => new City { - Id = row.Id, + Id = (int)row.Id, CityName = row.CityName, StateProvinceName = row.StateProvince, ISO_3166_2 = row.Iso31662,