這篇文章介紹deployer工具.
它支持并行部署,版本回退,可以很方便的編寫(xiě)命令并設(shè)置執(zhí)行時(shí)機(jī),并且支持很多主流的php框架提供開(kāi)箱可用的一些方案.
使用deployer的情況下:
circleCI配置文件中的deployment模塊需要修改,其中dep -v deploy staging
命令會(huì)執(zhí)行當(dāng)前目錄中的deploy.php文件
deployment:
staging:
branch: develop
commands:
- curl -LO https://deployer.org/deployer.phar
- sudo mv deployer.phar /usr/local/bin/dep
- chmod +x /usr/local/bin/dep
- dep -v deploy test
- dep -v deploy staging
production:
branch: master
commands:
- curl -LO https://deployer.org/deployer.phar
- sudo mv deployer.phar /usr/local/bin/dep
- chmod +x /usr/local/bin/dep
- dep -v deploy production
我使用的deployer的一個(gè)例子:
要說(shuō)明一下腳本中的幾個(gè)host,其實(shí)是有三組host,里面的stage分別是test/staging/production對(duì)應(yīng)不同的環(huán)境,這個(gè)不是這篇文章的重點(diǎn)所以不介紹.
并且host配置的這么奇怪是因?yàn)閔ost不能重名...所以我就各種辦法...
<?php
namespace Deployer;
require 'recipe/laravel.php';
use Symfony\Component\Console\Input\InputOption;
//dep -vv deploy --first true --branch develop -- test
option('first', null, InputOption::VALUE_OPTIONAL, 'If first deploy.');
// Configuration
set('repository', 'git@github.com:never615/easy-admin.git');
set('allow_anonymous_stats', false);
// Hosts
host('server-1.xxx.com', 'server-2.xxx.com')
->stage('production')
->set("branch", "master")
->user("user")
->port("88888")
->set('deploy_path', '/app/xxx/easy_admin/production')
->forwardAgent(true)
->multiplexing(true)
->addSshOption('UserKnownHostsFile', '/dev/null')
->addSshOption('StrictHostKeyChecking', 'no');
host('119.23.111.111', '120.76.111.112')
->stage('staging')
->set("branch", "develop")
->user("user")
->port("88888")
->set('deploy_path', '/app/xxx/easy_admin/staging')
->forwardAgent(true)
->multiplexing(true)
->addSshOption('UserKnownHostsFile', '/dev/null')
->addSshOption('StrictHostKeyChecking', 'no');
host('test')
->hostname('119.23.111.111')
->stage('test')
->set("branch", "develop")
->user("user")
->port("88888")
->set('deploy_path', '/app/xxx/easy_admin/test')
->forwardAgent(true)
->addSshOption('UserKnownHostsFile', '/dev/null')
->addSshOption('StrictHostKeyChecking', 'no');
// Tasks
desc('first deploy');
task('deploy:first', function () {
if (input()->hasOption('first')) {
$first = input()->getOption('first');
if ($first) {
run('{{bin/php}} {{release_path}}/artisan tool:install');
run('{{bin/php}} {{release_path}}/artisan admin:install');
run('{{bin/php}} {{release_path}}/artisan user:install');
run('{{bin/php}} {{release_path}}/artisan mall:install');
run('{{bin/php}} {{release_path}}/artisan activity:install');
//生成的key需要各個(gè)地方一樣
// run('{{bin/php}} {{release_path}}/artisan passport:install');
// run('{{bin/php}} {{release_path}}/artisan passport:keys');
run('{{bin/php}} {{release_path}}/artisan passport:client --personal');
}
}
});
desc('update');
task('deploy:update',function(){
run('yes|{{bin/php}} {{release_path}}/artisan tool:update');
run('yes|{{bin/php}} {{release_path}}/artisan admin:update');
run('yes|{{bin/php}} {{release_path}}/artisan user:update');
run('yes|{{bin/php}} {{release_path}}/artisan mall:update');
run('yes|{{bin/php}} {{release_path}}/artisan activity:update');
});
task('deploy:chown_chgrp',function(){
run('sudo chown -R nginx {{release_path}}');
run('sudo chgrp -R www {{release_path}}');
run('sudo chmod -R 775 {{release_path}}');
});
desc('copy env');
task('deploy:cp_env', 'cp .env.{{stage}} .env');
desc('copy composer');
task('deploy:cp_composer', 'cp composer.json.circle composer.json');
desc('Restart PHP-FPM service');
task('php-fpm:restart', function () {
// The user must have rights for restart service
// /etc/sudoers: username ALL=NOPASSWD:/bin/systemctl restart php-fpm.service
run('sudo systemctl restart php-fpm.service');
});
task("artisan:vendor", '
php artisan queue:restart;
');
after('deploy:symlink', 'php-fpm:restart');
after('deploy:update_code', 'deploy:cp_env');
after('deploy:update_code', 'deploy:cp_composer');
// [Optional] if deploy fails automatically unlock.
after('deploy:failed', 'deploy:unlock');
// first deploy run
after('artisan:vendor', 'deploy:first');
// plugin install
after('artisan:vendor', 'deploy:update');
after('deploy:symlink', 'deploy:chown_chgrp');
// publish vendor
before('deploy:symlink', 'artisan:vendor');
// Migrate database before symlink new release.
before('deploy:symlink', 'artisan:migrate');
于是新的部署流程如下:
部署流程
- 平時(shí)在開(kāi)發(fā)環(huán)境直接使用文件上傳的方式更新代碼
- 每開(kāi)發(fā)完成一個(gè)功能,就提交代碼到開(kāi)發(fā)分支(github)
- 提交到github后會(huì)觸發(fā)鉤子,CircleCI開(kāi)始執(zhí)行測(cè)試,然后使用deployer部署代碼到各服務(wù)器
- 測(cè)試沒(méi)有問(wèn)題后,提交代碼到master分支,會(huì)自動(dòng)部署到各服務(wù)器的正式環(huán)境
整個(gè)部署流程,不需要人參與,就像平常一樣,開(kāi)發(fā)完一個(gè)功能提交到github而已.
參考: