Установка
Модуль, CLI и файл конфигурации.
Модуль#
go get github.com/AlexAli29/ormРантайм зависит только от стандартной библиотеки и github.com/jackc/pgx/v5. Эта граница проверяется тестом, поэтому она не размывается со временем.
CLI#
Генератор и планировщик миграций — один бинарник:
go install github.com/AlexAli29/orm/cmd/orm@latestИли без установки — так это обычно и попадает в Makefile:
go run github.com/AlexAli29/orm/cmd/orm generateЗафиксируйте версию в tools.go, если хотите отслеживать её вместе со всем остальным.
Дополнительные адаптеры#
Каждый — отдельный модуль, поэтому проект, который им не пользуется, его и не компилирует:
go get github.com/AlexAli29/orm/ormotel # трейсинг OpenTelemetry
go get github.com/AlexAli29/orm/ormtest/postgres # помощники Testcontainersormslog, ormhealth и ormtest лежат в основном модуле и ничего не стоят, пока не импортированы.
orm.yaml#
Файл конфигурации лежит в корне проекта:
version: 1
schema:
# managed: схемой владеют декларации, миграции её применяют.
# Уберите mode для режима database-first, где авторитетна база.
mode: managed
dsn: ${DATABASE_URL}
search_path:
- public
migrations:
dir: migrations
packages:
- path: ./internal/domain
output: same
# Типы, которых в Go нет, приходят через конфигурацию. Библиотека отказывается
# выбирать за вас пакет для uuid: популярные варианты не взаимозаменяемы.
types:
uuid:
go: github.com/google/uuid.UUID
codec: uuid${DATABASE_URL} подставляется из окружения, поэтому файл не содержит секретов и его можно коммитить.
Проверка установки#
orm checkВ пустом проекте это сообщит, что деклараций не найдено — правильный ответ, доказывающий, что CLI дотянулся до базы.
Разобранные примеры#
Database-first, поверх существующей базы#
Ни mode, ни каталога миграций: авторитетна база, а вы пишете декларации,
описывающие её:
version: 1
schema:
dsn: ${DATABASE_URL}
search_path:
- public
- reporting
packages:
- path: ./internal/domain
output: sameManaged с несколькими ограниченными контекстами#
У каждого контекста свой пакет, и генератор пишет рядом с каждым:
version: 1
schema:
mode: managed
dsn: ${DATABASE_URL}
search_path:
- public
- billing
- identity
migrations:
dir: migrations
packages:
- path: ./internal/billing/domain
output: same
- path: ./internal/identity/domain
output: same
- path: ./internal/catalog/domain
output: sameДва контекста могут владеть таблицами с одинаковым именем в разных схемах: у них будут разные дескрипторы и разное состояние миграций.
Типы, которых в Go нет#
types:
uuid:
go: github.com/google/uuid.UUID
codec: uuid
numeric:
go: github.com/shopspring/decimal.Decimal
codec: decimalЭто те два, которые библиотека отказывается выбирать за вас: популярные пакеты
не взаимозаменяемы, а неверный numeric тихо портит деньги.
Makefile, который держит всё в согласии#
generate:
go run github.com/AlexAli29/orm/cmd/orm makemigrations
go run github.com/AlexAli29/orm/cmd/orm migrate
go run github.com/AlexAli29/orm/cmd/orm generate
check:
go run github.com/AlexAli29/orm/cmd/orm makemigrations --check
go run github.com/AlexAli29/orm/cmd/orm check --generatedЗапуск CLI из контейнера#
Если ставить Go на CI-раннер не хочется, CLI публикуется образом. Их два, потому что командам нужно разное:
$ docker run --rm -v "$PWD":/work -e DATABASE_URL \
ghcr.io/alexali29/orm:latest migrate --config /work/orm.yaml
Applying 0001_initial ... OKghcr.io/alexali29/orm — это CLI на distroless: около 16 МБ, без оболочки, без
libc, запуск не от root. Он покрывает migrate, sqlmigrate и inspect —
набор для развёртывания.
ghcr.io/alexali29/orm:latest-toolchain добавляет Go. check, generate и
makemigrations читают исходники сущностей через go list, поэтому им нужен
тулчейн и модуль, который разрешается, — а смонтировать свой модуль
недостаточно, если его зависимостей рядом нет:
$ docker run --rm -v "$PWD":/work -e DATABASE_URL \
ghcr.io/alexali29/orm:latest-toolchain check --config /work/orm.yaml
reconciliation clean: the entities and the schema agreeЕсли попросить у маленького образа одну из этих трёх команд, он сразу падает и
говорит почему — go command required, not found, — а не выдаёт неверный ответ.
Ради этого разделение и существует, вместо одного образа, который иногда
работает.
Оба собираются под linux/amd64 и linux/arm64. Теги следуют за релизами:
1.2.3, 1.2, latest и edge для вершины main.
В пайплайне#
migrate:
image: ghcr.io/alexali29/orm:latest
script:
- orm migrate --config orm.yamlТочка входа — сам бинарник, поэтому аргументы и есть команда. Оболочка нигде не нужна, что ценно в шаге, окружение которого держит строку подключения к базе.