Deployer PHP-CLI
CI/CD Deployment tool written in PHP supported for popular frameworks, (*1)
, (*2)
FEATURES
-
Deploy to multiple servers by projects/groups, (*3)
-
Yii2, Laravel, Codeigniter3 Frameworks support, (*4)
-
Pipeline support for Git, Composer, test and customized tasks, (*5)
-
CI/CD automation solution, (*6)
Helping developers to deploy codes from local instance to remote instances., (*7)
OUTLINE
DEMONSTRATION
, (*8)
Command Line
Deploy local project to remote servers by just executing the deployer in command after installation:, (*9)
$ deployer
Alternatively, you could call the original bootstrap: $ ./deployer, $ php ./deployer, (*10)
The interactive result could like be:, (*11)
$ deployer
Your available projects in configuration:
[0] your.project.com
[1] second.project.com
[2] other.site.com
Please select a project [number or project, Ctrl+C to quit]:0
Selected Project: your.project.com
Successful Excuted Task: Git
Successful Excuted Task: Composer
Successful Excuted Task: Composer
Successful Excuted Task: Test UnitTest
Successful Excuted Task: Commands before: Minify assets
Successful Excuted Task: Deploy to 127.0.0.11
Successful Excuted Task: Deploy to 127.0.0.12
Successful Excuted Task: Deploy
Successful Excuted Task: Commands after: Email notification
Or you could run by non-interactive mode with the same purpose:, (*12)
$ deployer --project="your.project.com"
REQUIREMENTS
This library requires the following:, (*13)
INSTALLATION
Composer Installation
Using Composer by sudoer or root to install is the easiest way with auto-installer:, (*14)
composer create-project --prefer-dist yidas/deployer-php-cli
Wget Installation
You could see Release for picking up the package with version, for example:, (*15)
$ wget https://github.com/yidas/deployer-php-cli/archive/master.tar.gz -O deployer-php-cli.tar.gz
After download, uncompress the package:, (*16)
$ tar -zxvf deployer-php-cli.tar.gz
In addition, you can rename the unzipped folder by mkdir deployer-php-cli && tar -zxvf deployer-php-cli.tar.gz --strip-components 1 -C deployer-php-cli, (*17)
Make Command
To make a command for deployer, if the package folder is deployer-php-cli then create a symbol by following command:, (*18)
$ sudo chmod +x $(pwd -L)/deployer-php-cli/deployer
$ sudo ln -s $(pwd -L)/deployer-php-cli/deployer /usr/bin/deployer
Startup
After installation, you could start to set up the config.inc.php for deployer, and enjoy to use:, (*19)
$ deployer
Upgrade
To upgrade, you could re-install the deployer and copy the old config.inc.php to the new one, for example:, (*20)
$ cp ./deployer-php-cli/config.inc.php ./
$ rm -r deployer-php-cli
$ composer create-project --prefer-dist yidas/deployer-php-cli
$ mv ./config.inc.php ./deployer-php-cli
CONFIGURATION
Project Setting:
You need to set up the projects configuration such as servers, source and destination in config.inc.php file:, (*21)
<?php
return [
// This project config processes deployment only for simple usage
'default' => [
'servers' => [
'127.0.0.1',
],
'source' => '/home/user/project',
'destination' => '/var/www/html/prod/',
],
];
You could refer config.inc.php file as an example.., (*22)
Config Options:
Configuration provides many features' setting, you could customize and pick up the setting you need., (*23)
| Key |
Type |
Description |
| servers |
array |
Distant server host list |
| user |
array\ |
string|Local/Remote server user, auto detect current user if empty |
| source |
string |
Local directory for deploy, use / as end means *
|
| destination |
string |
Remote path for synchronism |
| exclude |
array |
Excluded files based on sourceFile path |
| verbose |
bool |
Enable verbose with more infomation or not |
Git
To use Git into deploy task, you need to init or clone Git to the source directory at the first time:, (*24)
$ git clone git@gitlab.com:username/project-to-deploy.git sourceDir
| Key |
Type |
Description |
| enabled |
bool |
Enable git or not |
| checkout |
bool |
Execute git checkout -- . before git pull |
| branch |
string |
Branch name for git pull, pull default branch if empty |
| submodule |
bool |
Git submodule enabled |
Composer
To use Composer into deploy task, make sure that there are composer files in the source directory., (*25)
| Key |
Type |
Description |
| enabled |
bool |
Enable Composer or not |
| path |
string |
Composer executing relative path which supports multiple array paths |
| command |
string |
Update command likes composer update
|
Test
To use Test into deploy task, make sure that there are test configuration in the source directory., (*26)
| Key |
Type |
Description |
| enabled |
bool |
Enable Test or not |
| name |
string |
The test name for display |
| type |
string |
Test type, support phpunit. |
| command |
string |
The test bootstrap command supported relative filepath such as ./vendor/bin/phpunit
|
| configuration |
string |
The test configuration file supported relative filepath such as ./phpunit.xml
|
Tests
For multiple test tasks, using array to declare each test options:, (*27)
return [
'default' => [
'tests' => [
[
'name' => 'Test Task 1',
// ...
],
[
'name' => 'Test Task 2',
// ...
],
],
// ...
Rsync
| Key |
Type |
Description |
| enabled |
bool |
Enable rsync or not |
| params |
string |
Addition params of rsync command |
| timeout |
int |
Timeout seconds of each rsync connections |
| sleepSeconds |
int |
Seconds waiting of each rsync connections |
| identityFile |
string |
Identity file path for appling rsync |
Commands
Commands provides you to customize deploy tasks with many trigger hooks., (*28)
| Key |
Type |
Description |
| init |
array |
Addition commands triggered at initialization |
| before |
array |
Addition commands triggered before deploying |
| after |
array |
Addition commands triggered after deploying |
Example
- Copy
project directory form /var/www/html/ to destination under /var/www/html/test/:
'source' => '/var/www/html/project',
'destination' => '/var/www/html/test/',
- Copy all files (
*) form /var/www/html/project/ to destination under /var/www/html/test/:
'source' => '/var/www/html/project/',
'destination' => '/var/www/html/test/',
USAGE
Usage:
deployer [options] [arguments]
./deployer [options] [arguments]
Options:
-h, --help Display this help message
--version Show the current version of the application
-p, --project Project key by configuration for deployment
--config Show the seleted project configuration
--configuration
--skip-git Force to skip Git process
--skip-composer Force to skip Composer process
--git-reset Git reset to given commit with --hard option
-v, --verbose Increase the verbosity of messages
Interactive Project Select
$ deployer
Your available projects in configuration:
[0] default
[1] your.project.com
Please select a project [number or project, Ctrl+C to quit]:your.project.com
Selected Project: your.project.com
Successful Excuted Task: Git
Successful Excuted Task: Composer
Successful Excuted Task: Deploy to 127.0.0.11
Successful Excuted Task: Deploy
Non-Interactive Project Select
$ deployer --project="your.project.com"
Skip Flows
You could force to skip flows such as Git and Composer even when you enable then in config., (*29)
$ deployer --project="default" --skip-git --skip-composer
Revert & Reset back
You could reset git to specified commit by using --git-reset option when you get trouble after newest release., (*30)
$ deployer --project="default" --git-reset="79616d"
This option is same as executing git reset --hard 79616d in source project., (*31)
IMPLEMENTATION
Assuming project1 is the developing project which you want to deploy., (*32)
Developers must has their own site to develop, for example:, (*33)
# Dev host
/var/www/html/dev/nick/project1
/var/www/html/dev/eric/project1
In general, you would has stage project1 which the files are same as production:, (*34)
# Dev/Stage host
/var/www/html/project1
The purpose is that production files need to be synchronous from stage:, (*35)
# Production host
/var/www/html/project1
This tool regard stage project as source, which means production refers to destination, so the config file could like:, (*36)
return [
'project1' => [
...
'source' => '/var/www/html/project1',
'destination' => '/var/www/html/',
...
After running this tool to deploy project1, the stage project's files would execute processes likes git pull then synchronise to production., (*37)
Permissions Handling
1. Local and Remote Users
You could create a user on local for runing Deployer with umask 002. It will run process by the local user you set even you run Deployer by root:, (*38)
return [
'project1' => [
'user' => [
'local' => 'deployer',
'remote' => 'deployer',
],
...
2. Application File Permissions
Deployer uses rsync to deploy local source project to remote without --no-perms, which means that the source files' permission would keep on remote, but the files' owner would re-generate by remote user including root with --no-owner --no-group., (*39)
On the remote user, you could set the user's default groud ID to www-data in /etc/passwd, which the local user generates 664/775 mod files to deploy for remote www-data access., (*40)
For local user, umask 002 could be set in ~/.bashrc or global. Note that the permission need to apply for source files such as init from Git clone., (*41)
CI/CD
Webhook
Deployer provides webhook feature for triggering project deployment by any webhook service such as Gitlab., (*42)
To use webhook, you need add webhook setting into the projects you needed in config.inc.php:, (*43)
return [
'project' => [
// ...
'webhook' => [
'enabled' => true,
'provider' => 'gitlab',
'project' => 'yidas/deployer-php-cli',
'token' => 'da39a3ee5e6b4b0d3255bfef95601890afd80709',
'branch' => 'release',
'log' => '/tmp/deployer-webhook-project.log'
],
],
];
| Key |
Type |
Description |
| enabled |
bool |
Enable Webhook or not |
| provider |
string |
Webhook provider such as gitlab
|
| project |
string |
Provider's project name likes username/project
|
| token |
string |
Webhook secret token |
| branch |
string |
Listening branch for push event |
| log |
bool\ |
string|Enabled log and specify the log file |
PHP Web Setting
Deployer need a user to excute deployment, and the user is usually not the PHP web user., (*44)
For PHP-FPM, you could add a new PHP pool socket with the current user setting for the webhook site, for example /etc/php/fpm/pool.d/deployer.conf:, (*45)
[deployer]
user = deployer
group = www-data
listen = /run/php/php7.0-fpm_deployer.sock
Then give the new socket to the webhook server setting, for Nginx eaxmple /etc/nginx/site-enabled/webhook:, (*46)
server_name webhook.your.com;
root /srv/deployer/deployer-php-cli/webhook;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/run/php/php7.0-fpm_deployer.sock;
}
After a successful webhook, Deployer would prepare to process while responding the status and the result url for checking the deployment result., (*47)
Note: The PATH environment variable between Shell and PHP should be set to the same to prevent any unexpected problems., (*48)
Gitlab
According to above Nginx website setting, the webhook URL could be https://webhook.your.com/gitlab. After setting config.inc.php and setting up scecret token, you could give a push event to go!, (*49)
, (*50)
Note: Default setting is listen release branch's push event to trigger., (*51)
To browse the web page for result log report, enter the same webhook URL with log and token parameters to access.
For example: https://webhook.your.com/gitlab?log={project-name}&token={project-token}, (*52)
ADDITIONS
Rsync without Password:
You can put your local user's SSH public key to destination server user for authorization., (*53)
.ssh/id_rsa.pub >> .ssh/authorized_keys
Save Binary Encode File:
While excuting script, if you get the error like Exception: Zend Extension ./deployer does not exist, you may save the script file with binary encode, which could done by using vim:, (*54)
:set ff=unix
Yii2 Deployment
For yii2-app-advanced, you need to enable Composer and set yii2 init command in config.inc.php:, (*55)
'composer' => [
'enabled' => true,
],
'commands' => [
'before' => [
'yii2 init prod' => './init --env=Production --overwrite=All',
],
],
Minify/Uglify by Gulp
1. Install NPM, for Debian/Ubuntu:
apt-get install npm
2. Install Gulp by NPM
npm install -g gulp
3. Create Gulp Project
cd /srv/tools/minify-project
npm init
npm install gulp --save-dev
touch gulpfile.js
4. Set Gulp with packages
Package: gulp-uglify, (*56)
$ npm install gulp-uglify --save-dev
$ npm install pump --save-dev
gulpfile.js:, (*57)
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var pump = require('pump');
var assetPath = '/srv/your.project.com/assets/js';
gulp.task('compress', function (callback) {
pump([
gulp.src(assetPath+'/**/*.js'),
uglify(),
gulp.dest(assetPath)
],
callback
);
});
5. Set Gulp Process into Deployer
'source' => '/srv/project',
'commands' => [
'before' => [
'Minify inner JS' => [
'command' => 'cd /srv/tools/minify-project; gulp compress',
],
],
],