PHP 製のデプロイツール Deployer で複数プロジェクトのデプロイを行う
Deployer は PHP で書かれたデプロイツールです。世代管理機能により、デプロイ時にトラブルが起きてもロールバックできますし、PHP で書かれているので、Laravel など PHP を使ったシステムのデプロイと相性が良いです。今回は、この Deployer を使って、複数のプロジェクトのデプロイを行えるようにします。
Deployer のインストール
Deployer のインストールは、composer を使って行うことができます。Laravel や Symphony、CakePHP など主なフレームワークについては、Deployer のパッケージに付属しているレシピを利用することでデプロイ時に必要な作業を簡単に設定することができます。
composer require deployer/deployer --dev
デプロイ実行時に Slack で通知したいなどのニーズがあるときは、deployer/recipes
パッケージをあわせてインストールするとよいでしょう(deployer/recipes
パッケージで追加できるレシピの内容はこちら)。
デプロイの設定を書く
このあたりは、プロジェクトの内容にもよるので、参考程度に。下記のような内容を deploy.php
という名前で保存します。工夫しているのは、デプロイするプロジェクトや本番デプロイ時のタグの指定を選択式にしていることです。扱っているプロジェクトの数が増えてくると、手入力する際に間違う可能性も増えますし、タグの指定を間違って、異なるバージョンのものをデプロイしてしまう可能性もあります。そのようなミスを防ぐため、askChoice
を使って選択肢を表示するようにしています。
加えて、セマンティックバージョニングに基づいて v1.0.0
の形式でタグを付けていることを前提に、バージョンの昇順で並び替えて表示するとともに、minimum_version
未満のメジャーバージョンのものを選択肢に表示しないようにしています(set('minimum_version', 2)
を指定すると、v2.0.0
以降のものだけが表示されます)。
<?php
namespace Deployer;
require 'recipe/common.php';
// すべてのプロジェクトに共通の設定はここに記述
// 設定の説明は https://deployer.org/docs/configuration.html を参照
set('git_tty', false);
set('writable_use_sudo', true);
set('allow_anonymous_stats', false);
desc('Deploy Application');
task('deploy', function () {
// デプロイするものをユーザー選択式にする
$hostname = askChoice('デプロイするものを選択してください:',
['prod_foo', 'stg_foo', 'prod_bar', 'stg_bar']
);
set('hostname', $hostname);
// 各デプロイの設定
switch ($hostname) {
case 'prod_foo':
set('repository', 'git@github-foo:example/foo.git');
set('deploy_path', '/var/www/prod_foo');
set('minimum_version', 2);
break;
case 'stg_foo':
set('repository', 'git@github-foo:example/foo.git');
set('deploy_path', '/var/www/stg_foo');
set('branch', 'staging');
break;
case 'prod_bar':
set('repository', 'git@github-bar:example/bar.git');
set('deploy_path', '/var/www/prod_bar');
set('minimum_version', 0);
break;
case 'stg_bar':
set('repository', 'git@github-bar:example/bar.git');
set('deploy_path', '/var/www/stg_bar');
set('branch', 'staging');
break;
default:
exit();
}
// 本番の場合にはタグを取得して選択式にする
if (stripos(get('hostname'), 'prod') !== false) {
set('branch', function () {
$repository = get('repository');
exec("git ls-remote --tags -h {$repository}", $outputLines);
$versions = [];
foreach ($outputLines as $line) {
if (preg_match('#refs/tags/v([0-9]+?)\.([0-9]+?)\.([0-9]+?)$#', $line, $matches)) {
// minimum_version 未満のバージョンは表示しない
if ($matches[1] < get('minimum_version')) {
continue;
}
$versions[] = [
'major' => $matches[1],
'minor' => $matches[2],
'patch' => $matches[3]
];
}
}
// タグをバージョン順に並び替える
$major = array_column($versions, 'major');
$minor = array_column($versions, 'minor');
$patch = array_column($versions, 'patch');
array_multisort($major, SORT_ASC, $minor, SORT_ASC, $patch, SORT_ASC, $versions);
$tags = array_map(static function ($array) {
return 'v'.$array['major'].'.'.$array['minor'].'.'.$array['patch'];
}, $versions);
$tag = askChoice("デプロイするバージョンを選択してください:", $tags);
if ( ! askConfirmation("本番環境を {$tag} にして問題ありませんか?", false)) {
writeln('deploy was stopped');
exit();
}
return $tag;
});
}
if (stripos(get('hostname'), 'foo') !== false) {
// プロジェクトごとの設定はここで。このサンプルは Laravel のデプロイ
require 'recipe/laravel.php';
invoke('deploy:info');
invoke('deploy:prepare');
invoke('deploy:lock');
invoke('deploy:release');
invoke('deploy:update_code');
invoke('deploy:shared');
invoke('deploy:vendors');
invoke('deploy:writable');
invoke('artisan:storage:link');
invoke('artisan:view:cache');
invoke('artisan:config:cache');
invoke('artisan:queue:restart');
invoke('artisan:migrate');
invoke('deploy:symlink');
invoke('deploy:unlock');
invoke('cleanup');
} elseif (stripos(get('hostname'), 'bar') !== false) {
// 一般的な PHP プロジェクトのデプロイ
set('shared_files', [
'.env',
'.htaccess'
]);
invoke('deploy:info');
invoke('deploy:prepare');
invoke('deploy:lock');
invoke('deploy:release');
invoke('deploy:update_code');
invoke('deploy:shared');
invoke('deploy:vendors');
invoke('deploy:writable');
invoke('deploy:symlink');
invoke('deploy:unlock');
invoke('cleanup');
}
});
after('deploy', 'success');
// [Optional] if deploy fails automatically unlock.
fail('deploy', 'deploy:failed');
after('deploy:failed', 'deploy:unlock');
もう一つの工夫は、ソースコードを取得してくるリポジトリの指定の部分(set('repository', 'git@github-foo:example/foo.git');
の部分)です。複数の GitHub のリポジトリを扱う場合、上記のような記載をしたうえで、.ssh/config
に以下のような設定を行うことで、複数のリポジトリを使い分けることができます。
Host github-foo
User git
Port 22
HostName github.com
IdentityFile ~/.ssh/github-foo
TCPKeepAlive yes
IdentitiesOnly yes
Host github-bar
User git
Port 22
HostName github.com
IdentityFile ~/.ssh/github-bar
TCPKeepAlive yes
IdentitiesOnly yes
デプロイの実行
deploy.php
を作成したら、以下のコマンドでデプロイを実行します。
vendor/bin/dep deploy -vvv
ディスカッション
コメント一覧
まだ、コメントがありません