Как откатить миграции базы данных в CI/CD с помощью Goose и Golang

    При доставке приложений через CI/CD (например, GitLab CI) часто возникает задача не только применить миграции базы данных, но и автоматически откатить их при необходимости. Особенно это актуально для Go-проектов, где популярен инструмент Goose. Рассмотрим, как организовать отмену миграций в пайплайне, избегая ручного труда и путаницы с версиями.

    Проблема отката миграций в автоматических релизах

    Когда релиз включает несколько файлов миграций (например, 00100_add_table.sql и 00101_add_fields_to_table.sql), простое применение через стандартные инструменты не запоминает, какие именно миграции были выполнены в рамках конкретного релиза. При откате нужно точно знать, какие шаги отменять, особенно если между релизами были промежуточные изменения.

    Варианты решения для CI/CD

    • Тегирование миграций - присвоение общего тега (например, ID релиза) всем файлам миграций в рамках одного MR.
    • Хранение списка - ведение отдельной таблицы или файла с перечнем применённых миграций для каждого релиза.
    • Динамический анализ - использование git diff для выявления добавленных или изменённых файлов миграций в Merge Request.
    • Ручной откат - не рекомендуется из-за риска ошибок и потери времени.

    Реализация отката с Goose в Golang

    Goose поддерживает команды up и down, но для автоматического отката в CI/CD нужно передать точное количество шагов или версию. Лучший подход - сохранять в переменных окружения или артефактах пайплайна список версий миграций, применённых в текущем релизе. Например, в GitLab CI можно записать номера миграций в файл и передать его в джобу отката.

    Пример пайплайна с Goose

    В .gitlab-ci.yml можно добавить шаг:

    migrate:apply:
      script:
        - goose up
        - goose version > migrations.txt
      artifacts:
        paths:
          - migrations.txt

    Для отката:

    migrate:rollback:
      script:
        - count=$(wc -l < migrations.txt)
        - goose down $count

    Этот метод гарантирует, что откатятся только те миграции, которые были применены в данном релизе.

    Альтернативные инструменты миграций для Go

    Кроме Goose, популярны golang-migrate и sql-migrate. Они также поддерживают тегирование и версионирование. Например, golang-migrate позволяет использовать файлы с префиксами версий и команды down N. Выбор зависит от предпочтений команды и интеграции с базой данных.

    Рекомендации для надёжного отката

    • Всегда храните артефакты версий миграций в CI/CD.
    • Используйте уникальные идентификаторы релизов (например, теги Git) для группировки миграций.
    • Тестируйте откат на стейджинге перед применением в продакшене.
    • Документируйте процесс для разработчиков, чтобы избежать путаницы.

    Автоматизация отката миграций с Goose в CI/CD - реальная задача, решаемая через сохранение списка версий и передачу его в джобу отката. Это исключает ручные ошибки и ускоряет развёртывание.

    Часто задаваемые вопросы