Files
Deal/.superpowers/sdd/deal-scaffold/task-7-report.md
T
Rustam Khalimov 27c7831910
ci / build-test (push) Canceled after 0s
Deal — единая кодовая база
SaaS-мониторинг Telegram: ядро (модули Cards/Kanban/Pipeline/Tenants/Settings/
Discovery, Api, Infrastructure), сервисы telegram/ai/ml/storage, фронт Vue,
контракты и grpc-hosting, деплой-конфиги (dev/prod/observability/CI-раннер),
Gitea Actions CI, документация (ТЗ, техдок, api-map, код-стайл, планы, бэклог).

Текущее состояние: все этапы роадмапа 0–12 закрыты, сборка 5 sln 0/0,
тесты 1340/130/52/38/9 зелёные.
2026-09-11 23:56:47 +03:00

8.7 KiB
Raw Blame History

Task 7 — EF Core + миграции (public) (отчёт)

Дата: 2026-09-05 Статус: Выполнено (build 0 warnings / 0 errors; 4 теста PASS; миграция InitialPublic применена к public)

Файлы

Созданы (по коду плана, verbatim)

  • src/core/Deal.Infrastructure/Persistence/Entities/TenantEntity.csTenantEntity (Guid Id, Name = string.Empty, Status = "active", CreatedAt).
  • src/core/Deal.Infrastructure/Persistence/DealDbContext.csDealDbContext + DbSet<TenantEntity> Tenants; в OnModelCreating: ToTable("tenants", "public"), HasKey(Id), Name max 200 / required.
  • src/core/Deal.Infrastructure/Persistence/DealDbDesignTimeFactory.csIDesignTimeDbContextFactory<DealDbContext>; строка из env DEAL_PG_CONNECTION, fallback Host=localhost;Port=5433;Database=deal;Username=deal;Password=deal_dev_password (рабочий dev-Postgres Task 5).
  • src/core/Deal.Infrastructure/Migrations/20260905190044_InitialPublic.cs + .Designer.cs + DealDbContextModelSnapshot.cs — сгенерированы dotnet ef migrations add InitialPublic.
  • tests/Deal.Tests.Unit/TenantEntityTests.cs — тест дефолтов (см. Concern 3: строка Assert.NotEqual из плана скорректирована).

Изменены

  • src/core/Deal.Infrastructure/Deal.Infrastructure.csproj — добавлены пакеты (см. ниже).
  • src/core/Deal.Api/Deal.Api.csproj — добавлен Microsoft.EntityFrameworkCore.Design 10.0.11 с PrivateAssets=all (см. Concern 2).
  • src/core/Deal.Api/Program.cs — добавлены using Deal.Infrastructure.Persistence; и using Microsoft.EntityFrameworkCore;; после CreateBuilder добавлены GetConnectionString("DealPostgres") с тем же fallback и builder.Services.AddDbContext<DealDbContext>(options => options.UseNpgsql(connectionString));. Существующие 2 singleton-регистрации, /api/health и public partial class Program не тронуты.
  • src/core/Deal.Api/appsettings.Development.json — файл уже существовал (стандартный Logging от шаблона); блок ConnectionStrings:DealPostgres добавлен к существующему содержимому (merge, а не замена).
  • tests/Deal.Tests.Unit/Deal.Tests.Unit.csproj — добавлен ProjectReference на Deal.Infrastructure (Ruling 3, командой dotnet add).

Пакеты NuGet (версии, resolved latest stable для net10.0)

Deal.Infrastructure:

  • Microsoft.EntityFrameworkCore 10.0.11
  • Microsoft.EntityFrameworkCore.Design 10.0.11 (PrivateAssets=all, добавлен dotnet add автоматически)
  • Microsoft.EntityFrameworkCore.Relational 10.0.11 (см. Concern 1 — добавлен сверх списка плана)
  • Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3
  • (ранее, Task 6) Microsoft.Extensions.Configuration.Abstractions 10.0.11

Deal.Api:

  • Microsoft.EntityFrameworkCore.Design 10.0.11 (PrivateAssets=all; см. Concern 2)

dotnet-ef: локальный tool

Глобально dotnet-ef не установлен (dotnet tool list --global: только dotnet-dump, ilspycmd). По Ruling 5 создан локальный манифест:

  • dotnet new tool-manifest → SDK 10 создал манифест в src/core/dotnet-tools.json (не в .config/, как в документации SDK 8/9).
  • dotnet tool install dotnet-efdotnet-ef 10.0.11, запись добавлена в src/core/dotnet-tools.json (isRoot: true). Никакой манифест «выше» не найден — dotnet new tool-manifest сообщений о существующем не выдавал.

Миграция и БД

Команды (из src/core, локальный tool):

dotnet ef migrations add InitialPublic --project Deal.Infrastructure --startup-project Deal.Api
Build started... Build succeeded. Done.
dotnet ef database update --project Deal.Infrastructure --startup-project Deal.Api
Applying migration '20260905190044_InitialPublic'. Done.

Проверка (docker exec deal-postgres psql -U deal -d deal -c "\dt public.*"):

 Schema |         Name          | Type  | Owner
--------+-----------------------+-------+-------
 public | __EFMigrationsHistory | table | deal
 public | tenants               | table | deal
(2 rows)

Дизайн-тайм фабрика использовала fallback-строку (env DEAL_PG_CONNECTION не задан).

Build

Команда: dotnet build Deal.sln (из src/core)

Deal.SharedKernel net10.0 успешно выполнено
...
Deal.Api net10.0 успешно выполнено (0,4 с)
Сборка успешно выполнено через 2,3 с

Результат: 0 warnings, 0 errors (11 проектов).

Tests

Команда: dotnet test tests/Deal.Tests.Unit

Сводка теста: всего: 4; сбой: 0; успешно: 4; пропущено: 0; длительность: 1,0 с

PASS: MarkerTests (1) + TenantIdTests (2) + TenantEntityTests (1) = ровно 4.

Concerns / заметки

  1. Microsoft.EntityFrameworkCore.Relational 10.0.11 добавлен явно (сверх 3 пакетов плана). Причина: пакет Microsoft.EntityFrameworkCore 10.0.11 НЕ зависит от Relational (его nuspec тянет только Abstractions/Analyzers/Caching.Memory/Logging). Единственным источником Relational в графе Deal.Api оказывается Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3 с диапазоном [10.0.4, 11.0.0); NuGet выбирает минимальную версию диапазона → Relational 10.0.4, тогда как Deal.Infrastructure собирается против 10.0.11 (через Design 10.0.11 с PrivateAssets=all — виден только в собственном графе). Итог: MSB3277 (конфликт версий Relational) в сборке Deal.Api. Явная ссылка Relational 10.0.11 в Infrastructure (транзитивно утекает в Api) выравнивает все EF-сборки на 10.0.11. MSB3277 — MSBuild-warning (не C#), поэтому TreatWarningsAsErrors его не превращал в error, но требование «0 warnings» нарушалось.
  2. Microsoft.EntityFrameworkCore.Design добавлен в Deal.Api (PrivateAssets=all). dotnet ef требует Design-пакет в startup-проекте: Your startup project 'Deal.Api' doesn't reference Microsoft.EntityFrameworkCore.Design.... Ссылка в Infrastructure имеет PrivateAssets=all и в Api не утекает, поэтому первая попытка migrations add упала с этой ошибкой. После добавления в Api миграция создалась штатно (дизайн-тайм фабрика при этом по-прежнему из Infrastructure).
  3. Тест скорректирован (единственное отступление от verbatim-кода плана). Строка плана Assert.NotEqual(Guid.Empty, entity.Id == Guid.Empty ? Guid.Empty : entity.Id); невыполнима: TenantEntity.Id — автосвойство Guid без инициализатора → всегда Guid.Empty, тернарник всегда возвращает Guid.Empty, и NotEqual(Guid.Empty, Guid.Empty) падает (проверено: 1 FAIL на verbatim-версии). План под кодом сам разрешает правку: «тест проверяет дефолты; при необходимости скорректировать под реальную модель». Строка заменена на проверки реальных дефолтов: Status == "active", Name == string.Empty, CreatedAt == default(DateTimeOffset). Ожидание Task 13 (4 PASS) при verbatim-строке недостижимо.
  4. appsettings.Development.json уже существовал (Logging-блок); ConnectionStrings добавлены merge-правкой — стандартный шаблонный блок сохранён.
  5. .editorconfig/Directory.Build.props не редактировались. Генерённые миграционные файлы (.Designer.cs, Snapshot) предупреждений при сборке не дают.
  6. Проект не является git-репозиторием: коммиты/ветки не создавались (как и во всех предыдущих задачах).