Deal — единая кодовая база
ci / build-test (push) Canceled after 0s

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 зелёные.
This commit is contained in:
Rustam Khalimov
2026-09-11 23:56:47 +03:00
commit 27c7831910
1383 changed files with 158436 additions and 0 deletions
@@ -0,0 +1,91 @@
# 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.cs``TenantEntity` (`Guid Id`, `Name = string.Empty`, `Status = "active"`, `CreatedAt`).
- `src/core/Deal.Infrastructure/Persistence/DealDbContext.cs``DealDbContext` + `DbSet<TenantEntity> Tenants`; в `OnModelCreating`: `ToTable("tenants", "public")`, `HasKey(Id)`, `Name` max 200 / required.
- `src/core/Deal.Infrastructure/Persistence/DealDbDesignTimeFactory.cs``IDesignTimeDbContextFactory<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-ef`**dotnet-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-репозиторием: коммиты/ветки не создавались (как и во всех предыдущих задачах).