Как автоматически откатить в CI/CD миграции при помощи Goose, если их было несколько?
Ситуация: в разработке приложений и последующей их доставке через CI/CD GitLab'а или других подобных сервисов миграция базы данных зачастую происходит так же автоматически в момент доставки приложения в среду. С самой доставкой вопросов обычно нет, можно использовать любой полюбившийся инструмент. Однако, если мы хотим не только применять, но и отменять миграции, возникает проблема: нужно каким-либо образом запоминать, какие миграции были применены в момент доставки (релиза) приложения в среду, чтобы иметь возможность автоматизированно их отменить.
Представим, что у нас есть релиз, в котором есть код приложения и две новых миграции:
00100_add_table.sql
00101_add_fields_to_table.sql
Применив с помощью практически любого инструмента данные миграции, мы будем довольны результатом.
Однако, как откатить через CI/CD данный релиз и одновременно миграцию? Необходим некий способ понять, что именно было в ней применено. При этом будет лучше, если это не просто количество примененных миграций (здесь это 2).
Я вижу несколько способов:
1. Инструмент миграции должен уметь помечать миграции неким общим тегом.
2. Написать некий инструмент (например с использованием git diff), который будет вычленять из релиза (по сути Merge Request'а) добавленные файлы миграций или хотя бы их количество.
3. Хранить где-то список примененных миграций самостоятельно.
4. Ручной труд.
Вопрос: как именно механизм отката возможно реализовать с помощью Goose в случае Golang в CI/CD? Есть ли примеры, или возможно есть примеры с другим инструментом миграций для Go (либо универсальным)?
Не знаю про Go, но в Laravel ведётся таблица миграций, в которой есть инкрементируемое поле batch. Соответственно, rollback (без дополнительных аргументов) откатывает всё, у чего максимальный batch.
Станислав, если в разрезе "неких универсальных сервисов" обновляемых под нагрузкой - не откатывайте миграции, тем более автоматически. Одномоментное обновление и БД, и приложения невозможно. Поэтому любая версия приложения должна работать с ближайшими версиями БД. А значит в случае отката - возвращаете предыдущую версию приложения и не трогаете БД. Да, возможность отката БД должна быть, но в ручном режиме, на всякий случай.
Откат миграции, в отличии от отката приложения, это не возвращение предыдущей версии БД, а новое состояние, новая версия, которая лишь теоретически должна соответствовать предыдуущей версии БД. Откатываем мы тогда, когда чтото пошло не так, чтото чего мы не предусмотрели при разработке и не проверили при тестировании. Т.е. творится невесть что, а мы не разбираясь автоматом вызываем еще дополнительные DDL операции - это плохо.
К тому же, если ваша среда в нормальном состоянии, то вы не словите ошибку при накате миграций, а словите ее тогда, когда приложение начнет активно писать в соответствии с новой версией БД. А в таком состоянии, откат БД как правило будет сопровождаться потерей данных.
> goose тоже хранит историю миграций, вы открывали доку?
Смотря что мы под этим имеем ввиду. Он хранит просто список примененных миграций по их именам, или же именно сами миграции (их код DDL) в некоей таблице в БД? Нужно второе.