Автоматический deploy Symfony 2 используя Capifony

При разработке, и тем более поддержке действующего проекта на Symfony 2 одной из задач, которые приходится постоянно делать, это выгрузка изменений на сервер: рабочей или тестовой. Но так как программисты народ достаточно ленивый, чтобы автоматизировать повторяющиеся монотонные задачи, есть достаточное количество инструментов для облегчения данного процесса. Для Symfony2 мы используем Сapifony. Он основан на Capistrano но оптимизирован для Symfony.

Установка

Тут все просто, делается командой $ gem install capifony. Если у вас не установлен RubyGem, тогда вам необходимо будет обратится к официальной документации.
Далее переходим к проекту который нам необходимо обновлять на серверах, в нашем случае это будет блог $ cd ~/Sites/blog . Если вы думаете что всегда будет один сервер, не будет к примеру демо сервера или тестового, тогда можно инициализировать Сapifony командой $ capifony . Т.к. такой случай бывает редко, мы будем использовать несколько серверов и создадим файл $ vim Capfile с данным содержимым:

load 'deploy' if respond_to?(:namespace) # cap2 differentiator

require 'capifony_symfony2'
load 'app/config/deploy/deploy'

В данном случае нас интересует только последняя строчка она указывает на файл конфигурации для загрузки на сервера.

Настройка базовой конфигурации

Создаем файл $ vim app/config/deploy/deploy.rb, все таки не забываем что мы работаем с Ruby, с таким содержимым:

set :stages, %w(prod develop staging)
set :default_stage, "develop"
set :stage_dir, "app/config/deploy"
require 'capistrano/ext/multistage'

ssh_options[:forward_agent] = true

set :application, "4devs"
set :domain, "#{application}.io"
# set :deploy_to, "/var/www/#{domain}"
set :app_path, "app"
set :bin_path, "bin"
set :var_path, "var"
set :web_path, "web"
set :symfony_env_prod, "prod"
set :symfony_console, bin_path + "/console"
set :log_path, var_path + "/logs"
set :cache_path, var_path + "/cache"

set :shared_files, ["app/config/parameters.yml"]
set :shared_children, [var_path + "/logs", "vendor", web_path + "/uploads"]

set :writable_dirs, ["var/cache", "var/logs"]
set :webserver_user, "nginx"
set :permission_method, :acl
set :use_set_permissions, true

set :use_composer, true
# set :update_vendors, true
set :dump_assetic_assets, true

set :repository, "git@github.com:4devs/blog.git"
set :scm, :git


role :web, domain # Your HTTP server, Apache/etc
role :app, domain, :primary => true # This may be the same as your `Web` server

set :keep_releases, 3
set :use_sudo, false

# Be more verbose by uncommenting the following line
# logger.level = Logger::MAX_LEVEL

Остановлюсь на некоторых строчках подробнее. В первой строке мы указывает сколько вариантов stages у нас будет, в данном варианте у нас их три это pro, develop и staging. Вторая строчка указывает какой
stage у нас будет по умолчанию, в данном случае это develop, мы не хотим по ошибке обновлять prod сервер, вообще тут указан stage который будет использоваться при команде $ cap develop , если нам надо будет использовать prod то команда будет выглядеть $ cap prod deploy. Строка require 'capistrano/ext/multistage’ обязательна, мы подключаем для работы с нескольколькими stages. Дальше идет установка переменных, так как мы используем структуру папок Symfony 3, то нам приходится это указывать, в виде дополнительных переменных.
Строка set :shared_files, ["app/config/parameters.yml”] указывает на файлы которые не будут обновляться, на сервере они будут в отдельной папке и при обновлении в рабочую директорию просто будет создаваться символическая ссылка, у нас это файл настроек, если в вашем проекте есть еще файлы то их надо будет добавить в данную переменную. Аналогична переменная set :shared_children, [var_path + "/logs", var_path + "/spool", "vendor", web_path + "/uploads"] только она используется для папок, тут видно что можно использовать перченные заданные нами ранее.
Строкой set :writable_dirs, [var_path + "/cache", var_path + "/logs", var_path + "/spool"] задаются папки доступные для записи.
Строки set :repository, "git@github.com:4devs/blog.git” и set :scm, :git указывают репозиторий и его тип, в каждом stage мы можем указать ветку, для того чтобы соответствовать нашему workflow
set :keep_releases, 3 указывает столько версий оставлять, на сервре они будут в папке releases под уникальным идентификатором. После релиза лишние будут удаляться, но необходимо добавить команду after "deploy", “deploy:cleanup” в конец файла. logger.level = Logger::MAX_LEVEL необходим если при обновлении возникла ошибка чтобы узнать детали.

Настройка для develop stage

Создаем файл $ vim app/config/deploy/develop.rb с данный содержимым:

server '4devs.io', :app, :web, :primary => true

set :domain, "4devs.io"
set :user, "andrey"
set :deploy_to, "/var/www/#{domain}"
set :branch, "develop"

set :symfony_env_prod, "dev"

Первая строка указывает на наш сервер. Следущая строка на домен, потом идет пользователь от имени которого мы будет подсоединяться, будет команда по аналогии $ ssh andrey@4devs.io. на пятой строке указано куда ставить, но на самом деле там будет три папки, и нужно будет настраивать веб сервер на папку /var/www/4devs.io/current. Также вам необходимо настроить авторизацию по SSH ключу на сервер. Строка set :branch, “develop” указывает какую ветку использовать в репозитории. А set :symfony_env_prod, “dev” указывает на окружение в Symfony 2 , будут выполняться команды типа $ bin/console {command} —env=dev.

На данном этапе настройка закончена.

Загрузка на сервер

Сначала нам необходимо создать структуру командой $ cap deploy:setup . На сервере в папке /var/www/4devs.io будут созданы три папки current, releases и shared. После для обновления сервера воспользуемся командой $ cap deploy . В зависимости от уровня logger.level нам выведутся необходимые сообщения.
Если все пройдет удачно при минимальном logger.level выведется такое сообщение:

--> Updating code base with checkout strategy
--> Creating cache directory................................✔
--> Creating symlinks for shared directories................✔
--> Creating symlinks for shared files......................✔
--> Normalizing asset timestamps............................✔
--> Downloading Composer....................................✔
--> Installing Composer dependencies........................✔
--> Dumping all assets to the filesystem....................✔
--> Warming up cache........................................✔
--> Clear controllers.......................................✔
--> Setting permissions.....................................✔
--> Successfully deployed!

Для большинства проектов такой информации достаточно, но что если нам необходимо в процессе выполнять дополнительные команды?

Дополнительные команды

К примеру в проекте мы используем cronos-bundle и процессе обновления сервера соответсвенно необходимо выполнять команду $ bin/console cronos:replace
В файле $ vim app/config/deploy/deploy.rb добавлем следующий код:

namespace :cronos do
    task :replace do
        desc "Replace Cron Task"
        run "cd #{latest_release} && #{php_bin} #{symfony_console} cronos:replace --env=#{symfony_env_prod}"
    end
end

и добавляем также строчку after 'deploy:update', ‘cronos:replace’ чтобы наша команда выполнялась в процессе загрузки. Если мы не так часто добавляем задачи, то можно не добавлять данную задачу, а делать все самому командой $ cap cronos:replace .

Подключаем дополнения

Многие задачи уже написаны до нас, к примеру очистка memcаhed, нам не надо будет писать для типичных задач свои команды, просто подключим расширение например eycap
поставить его командой $ gem install eycap и добавляем в наш файл app/config/deploy/deploy.rb строку require "eycap/recipes” у нас появляются дополнительный набор команд. Можно также посмотреть все доступные команды $ cap -vT .

Вывод

Настройка Сapifony экономит очень много времени, и позволяет более эффективно использовать ваше время, не писать длинных инструкций, и допускать меньше ошибок. Для дальнейшего ознакомления я рекомендую воспользоваться официальной документацией Сapifony и Сapistrano.

Читайте также:

Docker установка и настройка

При разработке используется множество технологий. К примеру данный блог использует php(Symfony 2), mongodb, elastic, nginx это основные но также используется nodejs к примеру для минификации css, js. При разработке приходится настраивать все технологии как показано в статье. Но что делать если проектов несколько или они используют разные технологии, например другой проект использует MySQL, или еще могут использовать разные версии php или других библиотек. Для разработки и поддержки проектов на разных технологиях можно использовать Виртуальную машину и поставить на нее к примеру centos, но это не совсем удобно, надо все равно настраивать подобное окружение как на сервере и на других машинах разработчиков. Мы будет использовать контейнеры, такие как Docker. Настроем блог разработчиков чтобы использовать Docker для разработки.

Как использовать произвольное хранилище пользователей в FOSUserBundle

Практически все используют FOSUserBundle в своих Symfony проектах т.к. он ускоряет разработку и обладает хорошим набором функциональности для управления пользователями. Бандл предоставляет несколько готовых реализаций хранилищ данных: Propel и несколько для Doctrine (ORM и ODM). Это здорово, но иногда возникает необходимость работы с другими хранилищами данных. FOSUserBundle достаточно гибок и позволяет реализовать, и использовать произвольное хранилище. Для того, чтобы использовать все возможности FOSUserBundle Вам достаточно будет написать свой менеджер пользователей под конкретного провайдера.

Интеграция Paysera в Symfony

Сегодня сложно представить себе серьезный проект, где не понадобилась бы интеграция с платежными системами. Не смотря на то что существует множество популярных систем и аггрегаторов, таких как PayPal, RBKMoney, Paymentwall, Robokassa и т.д., я хочу рассказать о Paysera. Это еще одна, довольно новая платежная система. Они позиционируют себя как выгодных с точки зрения комиссий за их услуги. Paysera позволяет вашим пользователям расплачиваться карточками, SMS и т.д. Интеграция довольно простая, однако имеет некоторые неочевидные моменты, которые я и хочу осветить.

Настройка php, MySQL, nodejs, nginx и mongodb в OS X El Capitan

Недавно вышла OS X El Capitan, давайте обновим систему. Систему будем устанавливать с usb-flash. Из рабочего окружения мы поставим  php, nginx, mariadb, mongodb, elasticsearch, nodejs используя brew и настроем проект на symfony2.

Создание сайта “Обратный отсчет” на Symfony2

Мы иногда видим сайты с обратным отсчетом, проект стартует через … Его сделать достаточно просто, и не займет много времени. Мы воспользуемся проектом fdevs/coming-soon, который основан на Symfony2. Также будем сохранять введеный пользователями адреса электронной почтой в базу данных MongoDB. У нас есть настроенное рабочее окружение Osx, о настройке можно прочитать в статье Yosemite настройка рабочего окружения. Но главное версия php не меньше 5.4. В проекте можно также использовать реляционную базу данных типа MySQL. По умолчанию в проекте вообще не используется база данных, а введеный email отправляется на почту.