From 65f03d2e207f73a5554ef5fa27dc856cd7151a9b Mon Sep 17 00:00:00 2001 From: Sergey Nazarov Date: Sat, 30 Mar 2024 11:31:23 +0300 Subject: [PATCH] Add Nocr.TextMatcher.Migrator --- Directory.Packages.props | 4 +- Nocr.TextMatcher.sln | 6 +++ src/Nocr.TextMatcher.Migrator/AddMigration.sh | 2 + .../DesignTimeTextMatcherContextFactory.cs | 37 ++++++++++++++++++ src/Nocr.TextMatcher.Migrator/Dockerfile | 19 ++++++++++ ...240330082504_InitialMigration.Designer.cs} | 6 +-- .../20240330082504_InitialMigration.cs} | 2 +- .../TextMatcherContextModelSnapshot.cs | 4 +- .../Nocr.TextMatcher.Migrator.csproj | 38 +++++++++++++++++++ src/Nocr.TextMatcher.Migrator/Program.cs | 22 +++++++++++ src/Nocr.TextMatcher.Migrator/Readme.md | 10 +++++ .../appsettings.json | 6 +++ .../DesignTimeTextMatcherContextFactory.cs | 22 ----------- .../Nocr.TextMatcher.Persistence.csproj | 9 ----- .../ServiceCollectionExtensions.cs | 3 +- .../appsettings.json | 5 --- 16 files changed, 150 insertions(+), 45 deletions(-) create mode 100755 src/Nocr.TextMatcher.Migrator/AddMigration.sh create mode 100644 src/Nocr.TextMatcher.Migrator/DesignTimeTextMatcherContextFactory.cs create mode 100644 src/Nocr.TextMatcher.Migrator/Dockerfile rename src/{Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.Designer.cs => Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.Designer.cs} (93%) rename src/{Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.cs => Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.cs} (97%) rename src/{Nocr.TextMatcher.Persistence => Nocr.TextMatcher.Migrator}/Migrations/TextMatcherContextModelSnapshot.cs (95%) create mode 100644 src/Nocr.TextMatcher.Migrator/Nocr.TextMatcher.Migrator.csproj create mode 100644 src/Nocr.TextMatcher.Migrator/Program.cs create mode 100644 src/Nocr.TextMatcher.Migrator/Readme.md create mode 100644 src/Nocr.TextMatcher.Migrator/appsettings.json delete mode 100644 src/Nocr.TextMatcher.Persistence/DesignTimeTextMatcherContextFactory.cs delete mode 100644 src/Nocr.TextMatcher.Persistence/appsettings.json diff --git a/Directory.Packages.props b/Directory.Packages.props index 0ffdc0f..ea615f3 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -25,9 +25,11 @@ + + + - diff --git a/Nocr.TextMatcher.sln b/Nocr.TextMatcher.sln index d698a8a..d93c47d 100644 --- a/Nocr.TextMatcher.sln +++ b/Nocr.TextMatcher.sln @@ -28,6 +28,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.TextMatcher.Persistenc EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Contracts", "Contracts", "{0B8E28B3-EECC-4981-A87F-6D74C4F23371}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nocr.TextMatcher.Migrator", "src\Nocr.TextMatcher.Migrator\Nocr.TextMatcher.Migrator.csproj", "{6C429E86-0344-40C2-8898-BBA551E50403}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -66,6 +68,10 @@ Global {D578EE54-B55A-4B45-859D-7F343C73EEF5}.Debug|Any CPU.Build.0 = Debug|Any CPU {D578EE54-B55A-4B45-859D-7F343C73EEF5}.Release|Any CPU.ActiveCfg = Release|Any CPU {D578EE54-B55A-4B45-859D-7F343C73EEF5}.Release|Any CPU.Build.0 = Release|Any CPU + {6C429E86-0344-40C2-8898-BBA551E50403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C429E86-0344-40C2-8898-BBA551E50403}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C429E86-0344-40C2-8898-BBA551E50403}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C429E86-0344-40C2-8898-BBA551E50403}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {B721E055-84AF-44C6-973D-33241FD2EA7C} = {6E4D9F75-861F-4C00-A5C8-00D1BEE5A659} diff --git a/src/Nocr.TextMatcher.Migrator/AddMigration.sh b/src/Nocr.TextMatcher.Migrator/AddMigration.sh new file mode 100755 index 0000000..f6b37a3 --- /dev/null +++ b/src/Nocr.TextMatcher.Migrator/AddMigration.sh @@ -0,0 +1,2 @@ +export DOTNET_ENVIRONMNET=Development +dotnet ef migrations add $1 diff --git a/src/Nocr.TextMatcher.Migrator/DesignTimeTextMatcherContextFactory.cs b/src/Nocr.TextMatcher.Migrator/DesignTimeTextMatcherContextFactory.cs new file mode 100644 index 0000000..fef3c26 --- /dev/null +++ b/src/Nocr.TextMatcher.Migrator/DesignTimeTextMatcherContextFactory.cs @@ -0,0 +1,37 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using Nocr.TextMatcher.Persistence; + +namespace Nocr.TextMatcher.Migrator; + +public class DesignTimeTextMatcherContextFactory : IDesignTimeDbContextFactory +{ + private const string EnvironmentVariableKey = "DOTNET_ENVIRONMENT"; + + public TextMatcherContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + + var configuration = new ConfigurationBuilder() + .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddEnvironmentVariables() + .Build(); + + var environment = configuration.GetValue(EnvironmentVariableKey); + if (string.IsNullOrWhiteSpace(environment)) + { + throw new InvalidOperationException($"Отсутствует переменная окружения {EnvironmentVariableKey}"); + } + + var connectionString = configuration.GetConnectionString(environment); + if (string.IsNullOrWhiteSpace(connectionString)) + throw new InvalidOperationException($"ConnectionString for environment `{environment}` not found"); + + optionsBuilder.UseMySql(connectionString, new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion), + builder => builder.MigrationsAssembly("Nocr.TextMatcher.Migrator")); + + return new TextMatcherContext(optionsBuilder.Options); + } +} \ No newline at end of file diff --git a/src/Nocr.TextMatcher.Migrator/Dockerfile b/src/Nocr.TextMatcher.Migrator/Dockerfile new file mode 100644 index 0000000..d31b91f --- /dev/null +++ b/src/Nocr.TextMatcher.Migrator/Dockerfile @@ -0,0 +1,19 @@ +FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src +COPY . . + +RUN dotnet nuget add source -n "musk.fun.nocr" "https://gitea.musk.fun/api/packages/nocr/nuget/index.json" +RUN dotnet restore "src/Nocr.TextMatcher.Migrator/Nocr.TextMatcher.Migrator.csproj" +WORKDIR "/src/src/Nocr.TextMatcher.Migrator" +RUN dotnet build "Nocr.TextMatcher.Migrator.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Nocr.TextMatcher.Migrator.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Nocr.TextMatcher.Migrator.dll"] diff --git a/src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.Designer.cs b/src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.Designer.cs similarity index 93% rename from src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.Designer.cs rename to src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.Designer.cs index e443aa6..9b77d01 100644 --- a/src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.Designer.cs +++ b/src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.Designer.cs @@ -9,10 +9,10 @@ using Nocr.TextMatcher.Persistence; #nullable disable -namespace Nocr.TextMatcher.Persistence.Migrations +namespace Nocr.TextMatcher.Migrator.Migrations { [DbContext(typeof(TextMatcherContext))] - [Migration("20240328201810_InitialMigration")] + [Migration("20240330082504_InitialMigration")] partial class InitialMigration { /// @@ -25,7 +25,7 @@ namespace Nocr.TextMatcher.Persistence.Migrations MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - modelBuilder.Entity("Nocr.TextMatcher.AppServices.TextMatches.TextSubscription", b => + modelBuilder.Entity("Nocr.TextMatcher.AppServices.TextSubscriptions.TextSubscription", b => { b.Property("Id") .ValueGeneratedOnAdd() diff --git a/src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.cs b/src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.cs similarity index 97% rename from src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.cs rename to src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.cs index 7d7822b..50f58c7 100644 --- a/src/Nocr.TextMatcher.Persistence/Migrations/20240328201810_InitialMigration.cs +++ b/src/Nocr.TextMatcher.Migrator/Migrations/20240330082504_InitialMigration.cs @@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore.Migrations; #nullable disable -namespace Nocr.TextMatcher.Persistence.Migrations +namespace Nocr.TextMatcher.Migrator.Migrations { /// public partial class InitialMigration : Migration diff --git a/src/Nocr.TextMatcher.Persistence/Migrations/TextMatcherContextModelSnapshot.cs b/src/Nocr.TextMatcher.Migrator/Migrations/TextMatcherContextModelSnapshot.cs similarity index 95% rename from src/Nocr.TextMatcher.Persistence/Migrations/TextMatcherContextModelSnapshot.cs rename to src/Nocr.TextMatcher.Migrator/Migrations/TextMatcherContextModelSnapshot.cs index 5dced80..3d22638 100644 --- a/src/Nocr.TextMatcher.Persistence/Migrations/TextMatcherContextModelSnapshot.cs +++ b/src/Nocr.TextMatcher.Migrator/Migrations/TextMatcherContextModelSnapshot.cs @@ -8,7 +8,7 @@ using Nocr.TextMatcher.Persistence; #nullable disable -namespace Nocr.TextMatcher.Persistence.Migrations +namespace Nocr.TextMatcher.Migrator.Migrations { [DbContext(typeof(TextMatcherContext))] partial class TextMatcherContextModelSnapshot : ModelSnapshot @@ -22,7 +22,7 @@ namespace Nocr.TextMatcher.Persistence.Migrations MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - modelBuilder.Entity("Nocr.TextMatcher.AppServices.TextMatches.TextSubscription", b => + modelBuilder.Entity("Nocr.TextMatcher.AppServices.TextSubscriptions.TextSubscription", b => { b.Property("Id") .ValueGeneratedOnAdd() diff --git a/src/Nocr.TextMatcher.Migrator/Nocr.TextMatcher.Migrator.csproj b/src/Nocr.TextMatcher.Migrator/Nocr.TextMatcher.Migrator.csproj new file mode 100644 index 0000000..769e9ce --- /dev/null +++ b/src/Nocr.TextMatcher.Migrator/Nocr.TextMatcher.Migrator.csproj @@ -0,0 +1,38 @@ + + + + Exe + false + Linux + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + .dockerignore + + + + Always + + + + + + + + diff --git a/src/Nocr.TextMatcher.Migrator/Program.cs b/src/Nocr.TextMatcher.Migrator/Program.cs new file mode 100644 index 0000000..62d28e0 --- /dev/null +++ b/src/Nocr.TextMatcher.Migrator/Program.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore; + +namespace Nocr.TextMatcher.Migrator; + +public class Program +{ + public static async Task Main(string[] args) + { + var contextFactory = new DesignTimeTextMatcherContextFactory(); + using (var context = contextFactory.CreateDbContext(Array.Empty())) + { + await context.Database.MigrateAsync(); + await context.SaveChangesAsync(); + var appliedMigrations = await context.Database.GetAppliedMigrationsAsync(); + Console.WriteLine("Applied migrations:"); + foreach (var appliedMigration in appliedMigrations) + { + Console.WriteLine(appliedMigration); + } + } + } +} \ No newline at end of file diff --git a/src/Nocr.TextMatcher.Migrator/Readme.md b/src/Nocr.TextMatcher.Migrator/Readme.md new file mode 100644 index 0000000..205ee9e --- /dev/null +++ b/src/Nocr.TextMatcher.Migrator/Readme.md @@ -0,0 +1,10 @@ +# Nocr.TextMatcher.Migrator + +Проект содержит консольное приложение для применения миграций к БД. +Для выбора строки подключения при запуске необходимо передать переменную окружения `DOTNET_ENVIRONMENT`. Для локальной разработки следует использовать `DOTNET_ENVIRONMENT=Development`. + +## Добавление миграций + +В приложении реализована логика выбора строки подключения, а dotnet ef не позволяет передать переменную окружения. Поэтому был создан скрипт AddMigration, который устанавливает значение `DOTNET_ENVIRONMENT=Development`. + +Пример использования: `./AddMigration MyMigration` \ No newline at end of file diff --git a/src/Nocr.TextMatcher.Migrator/appsettings.json b/src/Nocr.TextMatcher.Migrator/appsettings.json new file mode 100644 index 0000000..d6d0aba --- /dev/null +++ b/src/Nocr.TextMatcher.Migrator/appsettings.json @@ -0,0 +1,6 @@ +{ + "ConnectionStrings": { + "Development": "server=localhost;port=3306;database=nocr_text_matcher;uid=root;pwd=toor", + "DockerCompose": "server=nocr-text-matcher-db;port=3306;database=nocr_text_matcher;uid=root;pwd=toor" + } +} \ No newline at end of file diff --git a/src/Nocr.TextMatcher.Persistence/DesignTimeTextMatcherContextFactory.cs b/src/Nocr.TextMatcher.Persistence/DesignTimeTextMatcherContextFactory.cs deleted file mode 100644 index a419121..0000000 --- a/src/Nocr.TextMatcher.Persistence/DesignTimeTextMatcherContextFactory.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.Configuration; - -namespace Nocr.TextMatcher.Persistence; - -public class DesignTimeTextMatcherContextFactory : IDesignTimeDbContextFactory -{ - public TextMatcherContext CreateDbContext(string[] args) - { - var optionsBuilder = new DbContextOptionsBuilder(); - var configuration = new ConfigurationBuilder() - .AddJsonFile("appsettings.json") - .Build(); - - var connectionString = configuration.GetConnectionString("MariaLocal"); - optionsBuilder.UseMySql(connectionString, - new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion)); - - return new TextMatcherContext(optionsBuilder.Options); - } -} \ No newline at end of file diff --git a/src/Nocr.TextMatcher.Persistence/Nocr.TextMatcher.Persistence.csproj b/src/Nocr.TextMatcher.Persistence/Nocr.TextMatcher.Persistence.csproj index 348a1f4..6b3d97f 100644 --- a/src/Nocr.TextMatcher.Persistence/Nocr.TextMatcher.Persistence.csproj +++ b/src/Nocr.TextMatcher.Persistence/Nocr.TextMatcher.Persistence.csproj @@ -10,8 +10,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - @@ -19,11 +17,4 @@ - - - - Always - - - diff --git a/src/Nocr.TextMatcher.Persistence/ServiceCollectionExtensions.cs b/src/Nocr.TextMatcher.Persistence/ServiceCollectionExtensions.cs index dd63d31..d2be272 100644 --- a/src/Nocr.TextMatcher.Persistence/ServiceCollectionExtensions.cs +++ b/src/Nocr.TextMatcher.Persistence/ServiceCollectionExtensions.cs @@ -21,8 +21,7 @@ public static class ServiceCollectionExtensions services.AddDbContext( (ctx, context) => { - context.UseMySql(connectionString, new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion), - builder => builder.MigrationsAssembly(typeof(TextMatcherContext).Assembly.FullName)) + context.UseMySql(connectionString, new MariaDbServerVersion(MariaDbServerVersion.LatestSupportedServerVersion)) .UseLoggerFactory(ctx.GetRequiredService()); } ); diff --git a/src/Nocr.TextMatcher.Persistence/appsettings.json b/src/Nocr.TextMatcher.Persistence/appsettings.json deleted file mode 100644 index 78c0e88..0000000 --- a/src/Nocr.TextMatcher.Persistence/appsettings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ConnectionStrings": { - "MariaLocal": "server=localhost;port=3306;database=nocr_text_matcher;uid=root;pwd=toor" - } -} \ No newline at end of file