Как мне структурировать Rakefile с некоторыми задачами, которые должны выполняться во время развертывания, и другими, которые даже не могут быть определены во время развертывания?
Я работаю с простым (или я так думал) приложением Sinatra, которое использует несколько гемов на разных этапах цикла разработки / развертывания приложения:
- Бандлер для управления зависимостями
- Грабли для задач сборки
- Звездочки для прекомпиляции активов
- RSpec 2 для испытаний
- Капистрано для развертывания
Gemfile включает в себя rspec
в test
группа.
Rakefile определяет assets:compile
задача по переводу Sass в CSS и CoffeeScript в JavaScript и конкатенации полученных файлов.
Капистрано бежит bundle install --without development test
поэтому на рабочий сервер устанавливаются только гемы, необходимые для производства (и компиляции активов). Он также запускает задачу Cap, которая в конечном итоге выполняется bundle exec rake assets:compile
на сервере.
Пока это все хорошо, но я бы хотел добавить задачу RSpec Rake в мой Rakefile, и там все пошло не так. Он работает нормально, когда я бегу локально, но когда я бегу cap deploy
Я получаю сообщение об ошибке на сервере: no such file to load -- rspec/core/rake_task
,
Это имеет смысл: RSpec не устанавливается на сервере, когда мы устанавливаем пакет, и задача spec на самом деле никогда не будет выполняться там. Ошибка происходит только из-за попытки определить задачу.
Я могу придумать несколько вариантов, чтобы справиться с этим, но ни один из них не кажется мне вполне подходящим:
- Заворачивать
require 'rspec/core/rake_task'
вbegin...rescue
блокировать и игнорировать ошибки - принимать
rspec
внеtest
группа или иным образом заставить его быть установленным на сервере - Используйте другой rakefile во время развертывания, который включает только
assets:compile
задача - Определите мое собственное
spec
задача, которая требует только RSpec при вызове - Запускайте прекомпиляцию локально, а не на сервере (мой любимый из этих вариантов)
Каковы лучшие практики здесь?
3 ответа
Лично, учитывая, что Rake не вызывается на сервере очень часто, я бы сделал его простым и удобным rescue
:
begin
require 'rspec/core/rake_take'
rescue LoadError
end
Я не уверен, почему с Rails я никогда не сталкивался с этим.
Я бы решил это, сделав
require 'rspec/core/rake_task' if defined?(RSpec)
Аргументация проста. Другие решения, вероятно, также подойдут, но я считаю, что они добавляют больше сложности, чем гибкости. Если в будущем появится больше подобных случаев, я бы рассмотрел альтернативное решение.
У меня была почти идентичная проблема.
Не уверен, что это "лучшая практика", но в итоге я сделал это в Rakefile:
if (Rails.env.migration? || Rails.env.production?)
# define rake tasks that depend on gems installed only in dev/test envs
end
(Я использую отдельную среду для миграций, которая указывает на ту же базу данных, что и рабочая, но имеет более высокие привилегии базы данных, необходимые для внесения изменений в схему.)