Я на своих проектах использую следующий подход:
1. создается сборка, на тестовом сервере, устанавливаются зависимости. При этом база создается каждый раз новая (схема), либо перезаписывается существующая. Дамп используется тот, который был взят с прода, спустя некоторое время существования последних обновлений кода на проде. Накатываются все миграции, обновления (миграциями пользуюсь только для тех случаев, когда надо что то подредактировать в данных, при обновлении сущностей).
2. Прогоняются тесты
3. При успешном прохождении тестов, создается архив кода, с исключением из него директорий var, vendor
3. Делается архив (полный) на проде текущего состояния приложения, помещается в отдельную папку. Этот архив служит для резервного отката
4. Заливается архив из шага 3, устанавливаются все зависимости, и В РУЧНУЮ накатываются миграции и обновления на БД
Проблем не знаю при таком подходе. Можно откатится в любой момент, ничего не сломается никогда. Даже БД, всегда есть дамп из хостинга или облака (тут отдельная настройка, например если у облака есть CLI, можно посылать в начале деплоя команду на прод, чтобы создался дамп). Но тут индивидуальный подход всегда