dev-master
9999999-dev https://github.com/jordillonch/JordiLlonchDeployBundleA Symfony2 deploy bundle
MIT
The Requires
- php >=5.4.0
- yriveiro/php-fslock 0.1
The Development Requires
by Jordi Llonch
symfony2 deploy deployer
Wallogit.com
2017 © Pedro PelĆ”ez
A Symfony2 deploy bundle
WIP, (*1)
This bundle aims to be a deploy system for your projects., (*3)
It is a Symfony2 Bundle but it can be used to deploy several kind of projects., (*4)
The bundle provides some commands to automatize deploy process. Here are main commands:, (*5)
Deployer have zones configured to deploy new code., (*6)
Zones are a project and environment (e.g. prod_api, our project Api for the production environment)., (*7)
Deployer uses GitHub repository, a configured branch, and HEAD as a target to deploy., (*8)
You can use this bundle adding it to your projects via composer (see installation section) but my recommendation is that you create a new project to deploy because you may be want to not have your production configurations in your repository project. So it is a good idea to delegate add productions configuration to the deploy system., (*9)
Furthermore this bundle offers helpers to automatize common operations like install composer dependencies, do a cache warm up for Symfony2 projects, refresh php-fpm after put code to production, get url to GitHub with diffs of new deployed code..., (*10)
There are two basic ideas that allows to deploy several code versions and put one of them to production and rollback between them., (*11)
When you want to deploy new code you have to do a "download" operation. That operation clones code from your git repository to a new directory (e.g. 20130704_180131_a618a56b08549794ec4c9d5db29058a01a58977f) then do adaptations to the code. Adaptations are the step where configurations are added, app cache is warned up, dependencies are downloaded and installed, symlinks are created to shared directoriesā¦, (*12)
Shared directories are directories where there are data that you want to keep between deploys. (e.g. logs, reports, generated images...), (*13)
After that, code is copied to configured servers. Ssh authorized keys are used to allow copy and execute commands to remote servers., (*14)
Then, when you want to use last downloaded code to production you have to execute "code to production" operation. This operation modify a symlink to the directory where last version are downloaded., (*15)
Usually, after that you should restart webserver or php-fpm., (*16)
Note: These ideas are taken from Capistrano., (*17)
php composer.phar create-project symfony/framework-standard-edition path/ 2.3.0
Add following lines to your composer.json file:, (*18)
"require": {
"jordillonch/deploy-bundle": "dev-master"
},
"minimum-stability": "dev",
Execute:, (*19)
php composer.phar update
Add it to the AppKernel.php class:, (*20)
new JordiLlonch\Bundle\DeployBundle\JordiLlonchDeployBundle(),
app/config/parameters.yml, (*21)
jordi_llonch_deploy:
config:
project: MyProject
vcs: git
servers_parameter_file: app/config/parameters_deployer_servers.yml
local_repository_dir: /home/deploy/local_repository
clean_max_deploys: 7
ssh:
user: myuser
public_key_file: '/home/myuser/.ssh/id_rsa.pub'
private_key_file: '/home/myuser/.ssh/id_rsa'
private_key_file_pwd: 'mypassword'
zones:
prod_myproj:
deployer: myproj
environment: prod
checkout_url: 'git@github.com:myrepo/myproj.git'
checkout_branch: master
repository_dir: /var/www/production/myproj/deploy
production_dir: /var/www/production/myproj/code
app/config/parameters_deployer_servers.yml, (*22)
prod_myproj:
urls:
- deploy@testserver1:8822
- deploy@testserver2:8822
parameters_deployers_servers.yml) because this file contains a dynamic configuration that would be changed in a scalable environment like AWS.php app/console generate:bundle --namespace=MyProj/DeployBundle --dir=src --no-interaction
src/MyProj/DeployBundle/Service/Test.php:, (*23)
<?php
namespace MyProj/DeployBundle/Service;
use JordiLlonch\Bundle\DeployBundle\Service\BaseDeployer;
class Test extends BaseDeployer
{
public function downloadCode()
{
$this->logger->debug('Downloading code...');
$this->output->writeln('<info>Downloading code...</info>');
$this->downloadCodeVcs();
$this->logger->debug('Adapting code');
$this->output->writeln('<info>Adapting code...</info>');
// Here you can download vendors, add productions configuration,
// do cache warm up, set shared directories...
$this->logger->debug('Copying code to zones...');
$this->output->writeln('<info>Copying code to zones...</info>');
$this->code2Servers();
}
public function downloadCodeRollback()
{
}
protected function runClearCache()
{
$this->logger->debug('Clearing cache...');
$this->output->writeln('<info>Clearing cache...</info>');
$this->execRemoteServers('sudo pkill -USR2 -o php-fpm');
}
}
jordi_llonch_deploy
<service id="myproj.deployer.test" class="MyProj/DeployBundle/Service/Test">
<tag name="jordi_llonch_deploy" deployer="myproj"/>
</service>
myproj is used in the configuration as deployer value.It is necessary to add the public key of the deploy user to .ssh/authorized_keys in remote servers in order to allow access to the deploy system., (*24)
After configure the deployer you have to do the initialization., (*25)
app/console deployer:initialize --zones=prod_myproj
Now you can download code from your repository and copy to your servers., (*26)
app/console deployer:download --zones=prod_myproj
After download you just need to put code into production., (*27)
app/console deployer:code2production --zones=prod_myproj
If there is any problem you can roll back to a previous version. See rollback command help., (*28)
Prepare deployer and remote servers creating a directories structure to host new code., (*29)
app/console deployer:initialize --zones=[zone1,zone2...]
Download code from repository, adapt, warn up⦠and ship it to remote servers in order to put new code to production., (*30)
app/console deployer:download --zones=[zone1,zone2...]
Deploy new code to production atomically and reload web server, app..., (*31)
app/console deployer:code2production --zones=[zone1,zone2...]
Ensure that all downloaded versions of code are copied to all servers. Useful when you add a new server to a zone. If you not syncronize the new server the rollback operation will break the code in the new server., (*32)
app/console deployer:syncronize --zones=prod_myproj
If there is any problem and you need to roll back to a previous version you have two options:, (*33)
app/console deployer:rollback execute [steps_backward] --zones=[zone1]
steps_backward should be 1.1) Ask deploy for available versions to rollback., (*34)
app/console deployer:rollback list --zones=[zone1]
2) Execute rollback to specific version, (*35)
app/console deployer:rollback execute [version] --zones=[zone1]
Shows running version and last downloaded version prepared to put to production., (*36)
app/console deployer:status [--zones=[zone1,zone2...]]
Configure remote servers for zones. Useful for automatize scaling., (*37)
app/console deployer:configure zone [add, set, rm, list, list_json] [url]
Remove old code. Left clean_max_deploys deploys., (*38)
app/console deployer:clean
Executes command passed as argument to all configured servers., (*39)
app/console deployer:exec2servers [command]
Deployer configurations are set in parameters.yml., (*40)
You must set general configurations and zones., (*41)
app/config/parameters.yml, (*42)
jordi_llonch_deploy:
config:
project: MyProject
vcs: git
local_repository_dir: /home/deploy/deploy_repository
clean_max_deploys: 7
sudo: true
ssh:
user: myuser
public_key_file: '/home/myuser/.ssh/id_rsa.pub'
private_key_file: '/home/myuser/.ssh/id_rsa'
private_key_file_pwd: 'mypassword'
Your project name., (*43)
Mail from., (*44)
Mail to send emails about deployments. It is an array., (*45)
Path where the servers parameters file is. A common configuration could be app/config/parameters_deployer_servers.yml., (*46)
Servers urls are in this file because it contains a dynamic configuration that would be changed in a scalable environment like AWS by some script., (*47)
Directory where deployer clone your repositories, adapt code and save data about versions in the deploy system., (*48)
Used in the clean command to remove previous downloaded versions. Left clean_max_deploys downloaded versions., (*49)
Add sudo to all commands send to remote servers. If you want to use, you should set your deploy user to sudoers on all remote servers with NOPASSWD:, (*50)
/etc/sudoers:, (*51)
deployer_user ALL=(ALL) NOPASSWD: ALL
Ssh configuration to establish connections on remote servers to execute commands., (*52)
Here an example of configuration:, (*53)
ssh:
proxy: cli
user: jllonch
password: 'mypassword'
public_key_file: '/home/myuser/.ssh/id_rsa.pub'
private_key_file: '/home/myuser/.ssh/id_rsa'
private_key_file_pwd: 'mykeypassword'
Client to use to execute remote commands., (*54)
It could be:, (*55)
pecl: php-ssh2 extensioncli: console ssh commandIf it is not defined it will try to use pecl if it is installed, otherwise it will use cli., (*56)
Username used in auth by password and auth by public key., (*57)
Password used in auth by password., (*58)
Public key file path., (*59)
Private key file path., (*60)
Private key password., (*61)
Helper parameters that can be get in your deploy class., (*62)
You need to set a minimum of one zone. Here is created your zone prod_myproj:, (*63)
app/config/parameters.yml, (*64)
jordi_llonch_deploy:
...
zones:
prod_myproj:
deployer: myproj
environment: prod
checkout_url: 'git@github.com:myrepo/myproj.git'
checkout_branch: master
checkout_proxy: true
repository_dir: /var/www/production/myproj/deploy
production_dir: /var/www/production/myproj/code
custom:
my_key1: value1
my_key2: value2
app/config/parameters_deployer_servers.yml, (*65)
prod_myproj:
urls:
- deploy@testserver1:8822
- deploy@testserver2:8822
Name of the service used to deploy the zone., (*66)
<service id="myproj.deployer.test" class="MyProj/DeployBundle/Service/Test">
<tag name="jordi_llonch_deploy" deployer="myproj"/>
</service>
Environment., (*67)
Remote servers where deployed code will be copied and set to production., (*68)
Format is: [user]@[server]:[port], (*69)
Url to git repository., (*70)
Git branch to clone., (*71)
Deployer always clone a repository for every deploy. If you want to avoid to download from remote server you can clone your repository locally, then set checkout_url to your local local repository (file:///home/deploy/proxy_repositories/myproj). Then before download operation, deployer execute a git pull to your local repository., (*72)
Path on remote servers where to copy new deployed code., (*73)
Path that is updated by deployer when new deployed code is set to production. So you must set this path to your webserver as a root path., (*74)
Custom parameters that can be get in your deploy class., (*75)
Helper parameters that must be set to use some helpers., (*76)
If helper parameters are set in general configuration those configuration are merged here., (*77)
Hepers automatize common operations like to install composer dependencies, to do a cache warm up for Symfony2 projects, to restart php-fpm after to put code to production, to get url to GitHub with differences of new deployed code..., (*78)
You can use Helpers in your Deployer classes to execute common operartions., (*79)
Here and example:, (*80)
src/MyProj/DeployBundle/Service/Test.php:, (*81)
<?php
namespace MyProj/DeployBundle/Service;
use JordiLlonch\Bundle\DeployBundle\Service\BaseDeployer;
class Test extends BaseDeployer
{
public function initialize()
{
parent::initialize();
// Shared dirs
$this->getHelper('shared_dirs')->initialize('logs');
}
public function downloadCode()
{
$this->logger->debug('Downloading code...');
$this->output->writeln('<info>Downloading code...</info>');
$this->downloadCodeVcs();
$this->logger->debug('Adapting code');
$this->output->writeln('<info>Adapting code...</info>');
// composer
$this->getHelper('composer')->install();
$this->getHelper('composer')->executeInstall();
// cache warm:up
$this->getHelper('symfony2')->cacheWarmUp();
// shared directories
$this->getHelper('shared_dirs')->set('app/logs', 'logs');
$this->logger->debug('Copying code to zones...');
$this->output->writeln('<info>Copying code to zones...</info>');
$this->code2Servers();
}
public function downloadCodeRollback()
{
}
protected function runClearCache()
{
$this->logger->debug('Clearing cache...');
$this->output->writeln('<info>Clearing cache...</info>');
$this->getHelper('phpfpm')->refresh();
}
}
helper⦠to install composer dependencies, doing cache warm up, setting shared directories and restarting php-fpm.Easy way to manage shared directories., (*82)
$this->getHelper('shared_dirs')->initialize($path), (*83)
$this->getHelper('shared_dirs')->set($pathInAppToLink, $pathInSharedDir), (*84)
Provides methods to restart php-fpm gracefully., (*85)
$this->getHelper('phpfpm')->refresh(), (*86)
$this->getHelper('phpfpm')->refreshCommand(), (*87)
Helpers to manage composer installation and some commands., (*88)
$this->getHelper('composer')->install(), (*89)
$this->getHelper('composer')->executeInstall(), (*90)
For now only provides a method to do a cache warm up., (*91)
$this->getHelper('symfony2')->cacheWarmupOnServers(), (*92)
$this->getHelper('symfony2')->cacheWarmUp(), (*93)
Useful methods to have feedback of your deploy in GitHub., (*94)
$this->getHelper('github')->getCompareUrl($gitUidFrom, $gitUidTo), (*95)
helper:
github:
url: https://github.com/YourUser/Repository
$this->getHelper('github')->getCompareUrlFromCurrentCodeToNewRepository(), (*96)
Provides a method to send messages to a room in a HipChat., (*97)
$this->getHelper('hipchat')->send($msg, $color='purple'), (*98)
helper:
hipchat:
token: your_token
room_id: your_room_id
Jordi Llonch - llonch.jordi at gmail dot com, (*99)
DeployBundle is licensed under the MIT License. See the LICENSE file for full details., (*100)
A Symfony2 deploy bundle
MIT
symfony2 deploy deployer