Skip to content

Commit 54acde1

Browse files
author
Rens van Moorsel
committed
feat: add migrations to container
1 parent 477ad8b commit 54acde1

5 files changed

Lines changed: 60 additions & 28 deletions

File tree

‎.github/workflows/build-and-publish-release.yml‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,22 @@ jobs:
2626
- name: Checkout repository
2727
uses: actions/checkout@v4
2828

29+
# --- .NET Setup voor Migration Bundle ---
30+
- name: Setup .NET
31+
uses: actions/setup-dotnet@v4
32+
with:
33+
dotnet-version: '8.0.x'
34+
35+
- name: Install dotnet-ef
36+
run: dotnet tool install --global dotnet-ef
37+
38+
- name: Restore dependencies
39+
run: dotnet restore Backend/Backend.csproj
40+
41+
- name: Create Migration Bundle
42+
run: |
43+
dotnet ef migrations bundle --project Backend/ -o efbundle --self-contained -r linux-x64 --force
44+
2945
- name: Log in to the Container registry
3046
uses: docker/login-action@v3
3147
with:

‎Backend/Database/DatabaseSeeder.cs‎

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
using Backend.Services;
44
using Backend.Utils.DateTime;
55
using Microsoft.EntityFrameworkCore;
6+
using Npgsql;
67

78
namespace Backend.Database;
89

910
/// <summary>
1011
/// The DatabaseSeeder class is responsible for seeding the database with initial data and ensuring that certain essential settings and groups exist when the application starts. It implements the IHostedService interface, allowing it to run as a background service during the application's startup process. The seeder checks for the existence of specific settings and groups, creating them if they do not already exist, and also ensures that a backup board account is created if there are no existing board members. This helps to ensure that the application has the necessary configuration and data in place for proper functionality from the moment it is launched.
1112
/// </summary>
1213
/// <param name="scopeFactory">The factory for creating service scopes.</param>
13-
public class DatabaseSeeder(IServiceScopeFactory scopeFactory) : IHostedService
14+
public class DatabaseSeeder(IServiceScopeFactory scopeFactory, Logger<DatabaseSeeder> logger) : IHostedService
1415
{
1516
/// <summary>
1617
/// Starts the database seeding process. This method is called when the application starts and is responsible for ensuring that essential settings and groups are present in the database. It creates a new service scope to access the database context and performs checks to create default settings and groups if they do not already exist. Additionally, it ensures that a backup board account is created if there are no existing board members, providing a fallback option for administrative access. The seeding process helps to establish a baseline configuration for the application, allowing it to function correctly from the outset.
@@ -19,43 +20,50 @@ public class DatabaseSeeder(IServiceScopeFactory scopeFactory) : IHostedService
1920
/// <returns>A task representing the asynchronous operation.</returns>
2021
public async Task StartAsync(CancellationToken cancellationToken)
2122
{
22-
using var scope = scopeFactory.CreateScope();
23+
try
24+
{
25+
using var scope = scopeFactory.CreateScope();
2326

24-
var db = scope.ServiceProvider.GetRequiredService<PostgresDbContext>();
27+
var db = scope.ServiceProvider.GetRequiredService<PostgresDbContext>();
2528

26-
string boardGroupId = await EnsureSettingExists(db, "BoardGroupId", "1");
27-
28-
string candidateBoardGroupId = await EnsureSettingExists(db, "CandidateBoardGroupId", "2");
29-
30-
await EnsureGroupExists(db, "Board", GroupType.Committee, uint.Parse(boardGroupId));
31-
32-
await EnsureGroupExists(db, "Candidate Board", GroupType.Committee, uint.Parse(candidateBoardGroupId));
29+
string boardGroupId = await EnsureSettingExists(db, "BoardGroupId", "1");
30+
31+
string candidateBoardGroupId = await EnsureSettingExists(db, "CandidateBoardGroupId", "2");
32+
33+
await EnsureGroupExists(db, "Board", GroupType.Committee, uint.Parse(boardGroupId));
34+
35+
await EnsureGroupExists(db, "Candidate Board", GroupType.Committee, uint.Parse(candidateBoardGroupId));
3336

34-
await EnsureSettingExists(db, "MollieFee", "0.39");
37+
await EnsureSettingExists(db, "MollieFee", "0.39");
3538

36-
await EnsureSettingExists(db, "MollieFeeGLAccount", "5007");
39+
await EnsureSettingExists(db, "MollieFeeGLAccount", "5007");
3740

38-
await EnsureSettingExists(db, "MollieFeeCostUnit", "TRX");
41+
await EnsureSettingExists(db, "MollieFeeCostUnit", "TRX");
3942

40-
await EnsureSettingExists(db, "MembershipGLAccount", "8000");
41-
42-
await EnsureSettingExists(db, "ActivityGLAccount", "7001");
43+
await EnsureSettingExists(db, "MembershipGLAccount", "8000");
44+
45+
await EnsureSettingExists(db, "ActivityGLAccount", "7001");
4346

44-
await EnsureSettingExists(db, "MolliePaymentsCondition", "2");
47+
await EnsureSettingExists(db, "MolliePaymentsCondition", "2");
4548

46-
await EnsureSettingExists(db, "MollieRelationCode", "473");
49+
await EnsureSettingExists(db, "MollieRelationCode", "473");
4750

48-
await EnsureSettingExists(db, "MembershipVATCode", "0");
51+
await EnsureSettingExists(db, "MembershipVATCode", "0");
4952

50-
await EnsureSettingExists(db, "MollieFeeVATCode", "21");
53+
await EnsureSettingExists(db, "MollieFeeVATCode", "21");
5154

52-
await EnsureSettingExists(db, "MembershipPrice", "7.50");
55+
await EnsureSettingExists(db, "MembershipPrice", "7.50");
5356

54-
var keycloakOutboxWorker = scope.ServiceProvider.GetRequiredService<KeycloakOutboxWorker>();
57+
var keycloakOutboxWorker = scope.ServiceProvider.GetRequiredService<KeycloakOutboxWorker>();
5558

56-
var createNewBoardService = scope.ServiceProvider.GetRequiredService<ICreateNewBoardService>();
59+
var createNewBoardService = scope.ServiceProvider.GetRequiredService<ICreateNewBoardService>();
5760

58-
await EnsureBoardAccountExists(db, keycloakOutboxWorker, createNewBoardService);
61+
await EnsureBoardAccountExists(db, keycloakOutboxWorker, createNewBoardService);
62+
}
63+
catch (NpgsqlException ex) when (ex.SqlState == "42P01")
64+
{
65+
logger.LogWarning("Tables not found. Skipping seeder; migrations might be pending.");
66+
}
5967
}
6068

6169
/// <summary>

‎Backend/Dockerfile‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,15 @@ FROM build AS publish
1919
ARG BUILD_CONFIGURATION=Release
2020
RUN dotnet publish "Backend.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
2121

22-
# Finally, copy over the published project into the base stage
22+
# Copy over the published project into the base stage
2323
FROM base AS final
2424
WORKDIR /app
2525
COPY --from=publish /app/publish .
26+
27+
# Copy the efbundle tool to the final image and make it executable
28+
COPY efbundle .
29+
USER root
30+
RUN chmod +x ./efbundle
31+
USER $APP_UID
32+
2633
ENTRYPOINT ["dotnet", "Backend.dll"]

‎Backend/Program.cs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Microsoft.AspNetCore.HttpLogging;
1616
using System.Text;
1717
using System.Net.Http.Headers;
18+
using Npgsql;
1819

1920
Env.Load();
2021

@@ -156,12 +157,12 @@
156157

157158
c.SupportNonNullableReferenceTypes();
158159
});
159-
string connectionstring = Environment.GetEnvironmentVariable("PostgresqlConnectionString") ?? throw new InvalidOperationException("PostgresConnectionString environment variable is not set.");
160+
string connectionstring = Environment.GetEnvironmentVariable("PostgresqlConnectionString") ?? string.Empty;
160161
builder.Services.AddNpgsql<PostgresDbContext>(connectionString: connectionstring);
161162
builder.Services.AddControllers().AddNewtonsoftJson();
162163
builder.Services.AddMollieApi(options =>
163164
{
164-
options.ApiKey = Environment.GetEnvironmentVariable("MollieApiKey") ?? throw new Exception("No Mollie Key initialized");
165+
options.ApiKey = Environment.GetEnvironmentVariable("MollieApiKey") ?? string.Empty;
165166
});
166167
builder.Services.AddHostedService<PaymentSyncService>();
167168
builder.Services.AddHttpClient("KeycloakAdmin", client =>

‎compose.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ services:
1111
env_file:
1212
- .env
1313
environment:
14-
- PostgresqlConnectionString=${PostgresConnectionString}
14+
- PostgresqlConnectionString=${PostgresqlConnectionString}
1515
- ASPNETCORE_ENVIRONMENT=Production
1616

1717
tavern-frontend:

0 commit comments

Comments
 (0)