Skip to content

Commit

Permalink
Database migrator (#623)
Browse files Browse the repository at this point in the history
* chore: only migrate admin api and consumer api if in development mode

* feat: add DatabaseMigrator

* feat: add RunMigration config property

* chore: add Rider run config

* feat: add Dockerfile

* ci: add database migrator to docker-compose.test.yml

* feat: also migrate AdminApiDbContext

* chore: add rolling update configuration to eventhandler deployment

* feat: add databasemigrator to helm chart

* ci: add database migrator to publish pipeline

* ci: add database migrator to test pipeline

* feat: implement rollback behavior

* ci: make buildContainerImage script executable

* ci: map config into database migrator

* feat: update setup-postgres.sql

* chore: remove unused using directive

* refactor: change structure of files in helm folder

* feat: remove CREATE TABLE permission from setup-sqlserver script

* feat: don't set schema owners for sqlserver

* chore: use default user (sa/postgres) in all modules for local development

* ci: set environment variables with admin connection string for database-migrator

* fix: base dockerfile on aspnet instead of runtime

* fix: add name for all resources to values

* ci: change dependencies in docker-compsoe files

* feat: add special configmap for database migrator

* feat: improve logging for Executor

* chore: remove commented out code

* feat: set default log level of DatabaseMigrator to Information

* chore: explicitly set helm.sh/hook-delete-policy annotation for databasemigrator job

* chore: remove redundant blank

* ci: add missing condition in docker-compose.test.yml

* ci: add health check for sqlserver docker compose service

* ci: let seed-client depend on consumer-api health

* ci: fix cyclic reference

* ci: let consumer-api depend on database-migrator

* refactor: fix duplicated log event names

* ci: test

* ci: test

* ci: test

* ci: change health check of sql server

* ci: fix health check

* fix: remove duplicated role in ALTER DEFAULT PRIVILEGES commands

* ci: reduce sleep time for sqlserver start

* ci: further reduce sleep time for sqlserver start

* ci: reduce sleep

* feat: update permissions in setup-sqlserver.sql script

* ci: try to not update docker-compose

* ci: remove debug statement

* chore: only allow RunMigrations flag if environment is Development or Local

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
tnotheis and mergify[bot] authored Apr 26, 2024
1 parent c0e45a6 commit ff91a68
Show file tree
Hide file tree
Showing 40 changed files with 1,010 additions and 176 deletions.
11 changes: 11 additions & 0 deletions .ci/dbm/buildContainerImage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env node

import { $ } from "zx";
import { getRequiredEnvVar } from "../lib.js";

const tag = getRequiredEnvVar("TAG");

const platforms = process.env.PLATFORMS ?? "linux/amd64,linux/arm64";
const push = process.env.PUSH === "1" ? ["--push", "--provenance=true", "--sbom=true"] : "";

await $`docker buildx build --file ./DatabaseMigrator/Dockerfile --tag ghcr.io/nmshd/backbone-database-migrator:${tag} --platform ${platforms} ${push} .`;
10 changes: 5 additions & 5 deletions .ci/docker-compose.test.postgres.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ services:

seed-database:
image: postgres
volumes:
- ../setup-db:/app/setup-db
environment:
- PGPASSWORD=Passw0rd
command: psql -h postgres -U postgres -d enmeshed -f /app/setup-db/setup-postgres.sql
depends_on:
database:
condition: service_healthy

seed-client:
environment:
Database__Provider: Postgres
Database__ConnectionString: "Server=postgres;Database=enmeshed;User Id=devices;Password=Passw0rd;Port=5432"

database-migrator:
environment:
Infrastructure__SqlDatabase__Provider: Postgres
Infrastructure__SqlDatabase__ConnectionString: "Server=postgres;Database=enmeshed;User Id=postgres;Password=Passw0rd;Port=5432"

configs:
Config:
file: appsettings.override.postgres.json
Expand Down
14 changes: 10 additions & 4 deletions .ci/docker-compose.test.sqlserver.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,30 @@ services:
- MSSQL_SA_PASSWORD=Passw0rd
- ACCEPT_EULA=Y
- MSSQL_PID=Express
healthcheck:
test: ["CMD", "echo"]
interval: 1s
timeout: 1s
retries: 1
ports:
- 1433:1433

### seeds ###

seed-database:
image: mcr.microsoft.com/mssql-tools
volumes:
- ../setup-db:/app/setup-db
command: bash -c " sleep 20 && /opt/mssql-tools/bin/sqlcmd -S sqlserver -U SA -P Passw0rd -i /app/setup-db/setup-sqlserver.sql "
depends_on:
- database

seed-client:
environment:
Database__Provider: SqlServer
Database__ConnectionString: "Server=sqlserver;Database=enmeshed;User Id=devices;Password=Passw0rd;TrustServerCertificate=True"

database-migrator:
environment:
Infrastructure__SqlDatabase__Provider: SqlServer
Infrastructure__SqlDatabase__ConnectionString: "Server=sqlserver;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True"

configs:
Config:
file: appsettings.override.sqlserver.json
Expand Down
37 changes: 27 additions & 10 deletions .ci/docker-compose.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ services:
ports:
- "5000:8080"
depends_on:
database:
condition: service_started
database-migrator:
condition: service_completed_successfully
rabbitmq:
condition: service_started
seed-database:
condition: service_completed_successfully
azure-storage-emulator:
condition: service_started
configs:
Expand All @@ -34,12 +32,10 @@ services:
ports:
- "5173:8080"
depends_on:
database:
condition: service_started
database-migrator:
condition: service_completed_successfully
rabbitmq:
condition: service_started
consumer-api:
condition: service_healthy
configs:
- source: Config
target: app/appsettings.override.json
Expand All @@ -52,14 +48,28 @@ services:
environment:
- ASPNETCORE_ENVIRONMENT=Development
depends_on:
database:
condition: service_started
database-migrator:
condition: service_completed_successfully
rabbitmq:
condition: service_started
configs:
- source: Config
target: app/appsettings.override.json

database-migrator:
container_name: database-migrator-test
build:
context: ..
dockerfile: DatabaseMigrator/Dockerfile
depends_on:
seed-database:
condition: service_completed_successfully
environment:
- ASPNETCORE_ENVIRONMENT=Development
configs:
- source: Config
target: app/appsettings.override.json

### infrastructure ###

azure-storage-emulator:
Expand All @@ -79,6 +89,13 @@ services:

### seeds ###

seed-database:
volumes:
- ../setup-db:/app/setup-db
depends_on:
database:
condition: service_healthy

seed-client:
container_name: seed-client-test
build:
Expand Down
2 changes: 1 addition & 1 deletion .ci/helm/buildChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ const version = getRequiredEnvVar("VERSION");

await $`helm dependency update helm`;

await $`helm package --version ${version} --app-version ${version} helm`;
await $`helm package --version ${version} --app-version ${version} helm`;
39 changes: 39 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,45 @@ jobs:
TAG: ${{ steps.extract-version-from-git-tag.outputs.VERSION }}
PUSH: 1

publish-database-migrator:
name: Publish Database Migrator Container Image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install script dependencies
run: npm install --prefix ./.ci
- name: Docker Login
uses: docker/[email protected]
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from git tag
id: extract-version-from-git-tag
run: echo "VERSION=$(./.ci/extractVersionFromGitTag.js)" >> $GITHUB_OUTPUT
env:
GIT_TAG: ${{ github.ref_name }}
- name: Log in to Docker Hub for accessing the cloud builder
uses: docker/login-action@v3
with:
username: ${{ secrets.CLOUD_BUILDER_USERNAME }}
password: ${{ secrets.CLOUD_BUILDER_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: "lab:latest"
driver: cloud
endpoint: "jssoft/js-soft"
- name: Build and Push Container Image
run: ./.ci/dbm/buildContainerImage.js
env:
TAG: ${{ steps.extract-version-from-git-tag.outputs.VERSION }}
PUSH: 1

publish-helm-chart:
name: Publish Helm Chart
runs-on: ubuntu-latest
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,22 @@ jobs:
TAG: test
PLATFORMS: linux/amd64

build-dbm-container-image:
name: Build Database Migrator Container Image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install script dependencies
run: npm install --prefix ./.ci
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build image
run: ./.ci/dbm/buildContainerImage.js
env:
TAG: test
PLATFORMS: linux/amd64

build-aui-container-image:
name: Build Admin UI Container Image
runs-on: ubuntu-latest
Expand Down
43 changes: 43 additions & 0 deletions .run/Backbone.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Backbone" type="com.intellij.execution.configurations.multilaunch" factoryName="MultiLaunchConfiguration">
<rows>
<ExecutableRowSnapshot>
<option name="condition">
<ConditionSnapshot>
<option name="type" value="immediately"/>
</ConditionSnapshot>
</option>
<option name="executable">
<ExecutableSnapshot>
<option name="id" value="runConfig:Docker.docker-compose: Compose Deployment"/>
</ExecutableSnapshot>
</option>
</ExecutableRowSnapshot>
<ExecutableRowSnapshot>
<option name="condition">
<ConditionSnapshot>
<option name="type" value="immediately"/>
</ConditionSnapshot>
</option>
<option name="executable">
<ExecutableSnapshot>
<option name="id" value="runConfig:.NET Launch Settings Profile.AdminApi: Default"/>
</ExecutableSnapshot>
</option>
</ExecutableRowSnapshot>
<ExecutableRowSnapshot>
<option name="condition">
<ConditionSnapshot>
<option name="type" value="immediately"/>
</ConditionSnapshot>
</option>
<option name="executable">
<ExecutableSnapshot>
<option name="id" value="runConfig:.NET Launch Settings Profile.ConsumerApi: Default"/>
</ExecutableSnapshot>
</option>
</ExecutableRowSnapshot>
</rows>
<method v="2"/>
</configuration>
</component>
6 changes: 4 additions & 2 deletions AdminApi/src/AdminApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Backbone.Tooling.Extensions;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Logging;
using Serilog;
using Serilog.Exceptions;
using Serilog.Exceptions.Core;
Expand Down Expand Up @@ -79,7 +80,8 @@ static WebApplication CreateApp(string[] args)
var app = builder.Build();
Configure(app);

app.MigrateDbContext<AdminApiDbContext>();
if ((app.Environment.IsLocal() || app.Environment.IsDevelopment()) && app.Configuration.GetValue<bool>("RunMigrations"))
app.MigrateDbContext<AdminApiDbContext>();

return app;
}
Expand Down Expand Up @@ -175,7 +177,7 @@ static void Configure(WebApplication app)
app.UseSwagger().UseSwaggerUI();

if (app.Environment.IsDevelopment())
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
IdentityModelEventSource.ShowPII = true;

app.UseCors();

Expand Down
13 changes: 7 additions & 6 deletions AdminApi/src/AdminApi/appsettings.override.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"RunMigrations": true,
"Authentication": {
"ApiKey": "test"
},
Expand All @@ -24,8 +25,8 @@
},
"SqlDatabase": {
"Provider": "Postgres",
"ConnectionString": "User ID=adminUi;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
//"ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=adminUi;Password=Passw0rd;TrustServerCertificate=True"
"ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True"
}
},
"Modules": {
Expand All @@ -40,8 +41,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
"ConnectionString": "User ID=devices;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
//"ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=devices;Password=Passw0rd;TrustServerCertificate=True"
"ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True"
},
"PushNotifications": {
"Provider": "Dummy"
Expand All @@ -58,8 +59,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
"ConnectionString": "User ID=quotas;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
//"ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=quotas;Password=Passw0rd;TrustServerCertificate=True"
"ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True"
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions Backbone.sln
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHandlerService", "Even
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHandlerService.Tests", "EventHandlerService\test\EventHandlerService.Tests\EventHandlerService.Tests.csproj", "{D47E0FE1-23A0-4A96-AF57-E3CE71A132AD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseMigrator", "DatabaseMigrator\DatabaseMigrator.csproj", "{143EAC38-A2D0-4F74-88F1-3EF27413A8C6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -715,6 +717,10 @@ Global
{D47E0FE1-23A0-4A96-AF57-E3CE71A132AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D47E0FE1-23A0-4A96-AF57-E3CE71A132AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D47E0FE1-23A0-4A96-AF57-E3CE71A132AD}.Release|Any CPU.Build.0 = Release|Any CPU
{143EAC38-A2D0-4F74-88F1-3EF27413A8C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{143EAC38-A2D0-4F74-88F1-3EF27413A8C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{143EAC38-A2D0-4F74-88F1-3EF27413A8C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{143EAC38-A2D0-4F74-88F1-3EF27413A8C6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Microsoft.Extensions.Logging;
using Npgsql;
using Polly;
using Polly.Retry;

namespace Backbone.BuildingBlocks.API.Extensions;

Expand Down
23 changes: 13 additions & 10 deletions ConsumerApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,19 @@ static WebApplication CreateApp(string[] args)
var app = builder.Build();
Configure(app);

app
.MigrateDbContext<ChallengesDbContext>()
.MigrateDbContext<DevicesDbContext>()
.MigrateDbContext<FilesDbContext>()
.MigrateDbContext<RelationshipsDbContext>()
.MigrateDbContext<QuotasDbContext>()
.MigrateDbContext<MessagesDbContext>()
.MigrateDbContext<SynchronizationDbContext>()
.MigrateDbContext<TokensDbContext>()
.MigrateDbContext<QuotasDbContext>();
if ((app.Environment.IsLocal() || app.Environment.IsDevelopment()) && app.Configuration.GetValue<bool>("RunMigrations"))
{
app
.MigrateDbContext<ChallengesDbContext>()
.MigrateDbContext<DevicesDbContext>()
.MigrateDbContext<FilesDbContext>()
.MigrateDbContext<RelationshipsDbContext>()
.MigrateDbContext<QuotasDbContext>()
.MigrateDbContext<MessagesDbContext>()
.MigrateDbContext<SynchronizationDbContext>()
.MigrateDbContext<TokensDbContext>()
.MigrateDbContext<QuotasDbContext>();
}

app
.SeedDbContext<DevicesDbContext, DevicesDbContextSeeder>()
Expand Down
Loading

0 comments on commit ff91a68

Please sign in to comment.