100 lines
8.5 KiB
Markdown
100 lines
8.5 KiB
Markdown
# Проверка импорта на изолированном PostgreSQL
|
|
|
|
Запускается средствами проекта: pytest, SQLAlchemy, psycopg и отдельный Docker
|
|
Compose. Не использует production Compose, `.env`, SSH или данные сотрудников.
|
|
PostgreSQL 16 и runner работают в отдельной `internal`-сети без опубликованных
|
|
портов. Данные PostgreSQL находятся в tmpfs, без постоянных volumes. Базы:
|
|
`miem_import_test` и `miem_crawl_test`. Все сотрудники, статьи и credentials
|
|
синтетические; тестовые пароли непригодны для реальных систем.
|
|
|
|
Dockerfile копирует только нужный код и requirements. Его отдельный dockerignore
|
|
исключает `.git`, `.env`, файлы ключей/credentials, CSV владельца, данные
|
|
`app/data` и остальные файлы workspace. Runtime не получает переменные хоста.
|
|
CLI subprocess дополнительно получает только явно заданные тестовые libpq
|
|
параметры; `.pgpass`/service-файлы отключены. Не изменяйте адрес `postgres-test`
|
|
или имена тестовых БД для подключения к существующему серверу.
|
|
|
|
Синтетическая роль `import_test` создаётся только init-скриптом одноразового
|
|
тестового кластера. Fixture выдаёт ей документированные column grants и USAGE
|
|
sequence. Проверяется отсутствие CREATE схемы, INSERT сотрудников, DELETE
|
|
публикаций и sequence UPDATE. Это не создание временного доступа к рабочей БД.
|
|
Таблицы создаются моделью приложения и очищаются только в тестовых БД.
|
|
|
|
HTTP заблокирован test fixture; входные профили полного обхода подставляются
|
|
локально. Это проверяет настоящий SQL, транзакции, savepoint и сериализацию JSON,
|
|
но не парсинг сайта ВШЭ. Fixtures SQLite и подмена psycopg для интеграционных
|
|
тестов не используются.
|
|
|
|
## Что проверяется
|
|
|
|
1. Dry-run: все строки всех таблиц и состояния sequences совпадают до/после.
|
|
2. Apply: одна вставка, одно обновление, пропуск отсутствующего сотрудника.
|
|
3. Повторный импорт: ноль INSERT/UPDATE, неизменные таблицы/sequences.
|
|
4. CHECK constraint тестовой БД вызывает ошибку третьего действия после UPDATE
|
|
и успешного INSERT; все строки возвращаются в исходное состояние. Sequence
|
|
может продвинуться при rollback — это ожидаемое поведение PostgreSQL.
|
|
5. Обновление только года без raw_data сохраняет существующий JSONB.
|
|
6. Поздние строки CSV дополняют метаданные; первое непустое значение сохраняется
|
|
при конфликте, отчёт содержит названия конфликтующих полей. Повтор идемпотентен.
|
|
7. Два последовательных crawl сохраняют CSV-статью, отсутствующую у ВШЭ;
|
|
появившаяся статья получает HSE ID без второй записи и потери метаданных.
|
|
8. Полный `run_crawl` обрабатывает двух сотрудников. Два HSE ID на одну CSV-запись
|
|
откатывают savepoint первого, сохраняя JSONB, авторов, ID, хеш и updated_at;
|
|
публикация второго сохраняется. Проверяются обе очередности ID и уже
|
|
установленная привязка; неоднозначность отражается в CrawlError.
|
|
|
|
Всего 10 PostgreSQL-тестов (восьмой сценарий параметризован). В обычном
|
|
`python -m pytest -q` они пропускаются. Opt-in `MIEM_POSTGRES_INTEGRATION=1`
|
|
разрешён только с точным тестовым DATABASE_URL Compose-проекта.
|
|
|
|
## Команды владельцу
|
|
|
|
Выполняйте на локальной машине с Docker Engine/Compose v2 из корня репозитория
|
|
после независимого ревью. Команды явно выбирают локальный Unix socket и очищают
|
|
наследуемое окружение. Для Docker Desktop/Windows используйте Linux/WSL с
|
|
доступным локальным `/var/run/docker.sock`. Для отдельного стенда на VPS используйте
|
|
[отдельную инструкцию](postgresql-import-vps.md) и `compose.vps.yml`: этот локальный
|
|
Compose не предназначен для запуска на сервере с работающими сервисами.
|
|
Первый шаг:
|
|
|
|
```sh
|
|
env -i PATH="$PATH" docker --host unix:///var/run/docker.sock version
|
|
```
|
|
|
|
Ожидается exit code 0 и секции `Client` и `Server`. `command not found`,
|
|
`permission denied` или только Client с ошибкой подключения означает, что
|
|
до запуска этого варианта нужен локальный Docker. При его отсутствии сначала
|
|
выполните только read-only диагностику из инструкции VPS.
|
|
|
|
Дальнейшие точные команды сохранены здесь для воспроизводимого запуска:
|
|
|
|
```sh
|
|
env -i PATH="$PATH" docker --host unix:///var/run/docker.sock compose --env-file /dev/null --project-name miem-publication-integration -f tests/postgres/compose.yml config --quiet
|
|
env -i PATH="$PATH" docker --host unix:///var/run/docker.sock compose --env-file /dev/null --project-name miem-publication-integration -f tests/postgres/compose.yml build tests
|
|
env -i PATH="$PATH" docker --host unix:///var/run/docker.sock compose --env-file /dev/null --project-name miem-publication-integration -f tests/postgres/compose.yml up --abort-on-container-exit --exit-code-from tests
|
|
```
|
|
|
|
Первые две команды проверяют Compose и собирают runner с уже используемыми
|
|
зависимостями. Сборка/скачивание образов требуют registry/PyPI, но тестовая
|
|
runtime-сеть не имеет внешнего доступа и запросов к ВШЭ нет. При успехе третьей
|
|
команды ожидаются `10 passed` и exit code 0. Фактическую совместимость образа,
|
|
column grants и PostgreSQL можно считать подтверждённой **только после такого
|
|
выполнения**, не по unit-тестам или статическому чтению файлов.
|
|
|
|
После сохранения вывода тестов удалите именно этот тестовый проект:
|
|
|
|
```sh
|
|
env -i PATH="$PATH" docker --host unix:///var/run/docker.sock compose --env-file /dev/null --project-name miem-publication-integration -f tests/postgres/compose.yml down
|
|
```
|
|
|
|
Это уничтожит только синтетические данные в tmpfs тестового PostgreSQL. Не
|
|
используйте `docker system prune`, production Compose или удаление рабочих
|
|
volumes. Перед повторным прогоном выполните этот же `down`, чтобы следующий
|
|
кластер начинался с чистого init.sql; не запускайте два прогона одновременно.
|
|
|
|
## Статус подготовки
|
|
|
|
В среде подготовки Docker отсутствует; настоящие PostgreSQL-тесты не запускались.
|
|
Локально доступны только unit-тесты, проверка Python и статические проверки.
|
|
Production/VPS и доступ к рабочей БД не изменялись.
|