Last active
September 14, 2021 06:14
-
-
Save ntd/3f3af953802eeb55bd3aee7213044dd5 to your computer and use it in GitHub Desktop.
Deployer strategy for SilverStripe 4 (with public enabled)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This is the shared deployer code I use in my projects. I put it | |
* somewhere in the filesystem and then, in each SilverStripe project, | |
* I add `deploy.php`: | |
* ``` | |
* <?php | |
* require '/path/to/my/deployer-silverstripe4.php'; | |
* Deployer\set('application', 'my_application_name'); | |
* ``` | |
* and `hosts.yml`: | |
* ``` | |
* mytestingdeployment: | |
* hostname: myserver | |
* stage: staging | |
* deploy_path: "/var/staging/{{application}}" | |
* myfinaldeployment: | |
* hostname: myserver | |
* stage: production | |
* deploy_path: "/var/www/{{application}}" | |
* ``` | |
*/ | |
namespace Deployer; | |
require 'recipe/silverstripe.php'; | |
// Fallback settings, overridable in `hosts.yml` | |
set('default_stage', 'production'); | |
set('shared_dirs', [ 'public/assets' ]); | |
set('writable_dirs', [ 'public/assets' ]); | |
set('writable_chmod_mode', 'g+rwX'); | |
set('http_group', 'www-data'); | |
set('env_candidates', [ './.env.{{hostname}}', './.env.{{stage}}', './.env' ]); | |
inventory('hosts.yml'); | |
// This will require the proper `cachetool` binary installed in path: | |
// https://github.com/gordalina/cachetool | |
desc('Clear opcache cache'); | |
task('cachetool:clear:opcache', function () { | |
run('cachetool opcache:reset -n --fcgi'); | |
}); | |
desc('Clear APCU cache'); | |
task('cachetool:clear:apcu', function () { | |
run('cachetool apcu:cache:clear -n --fcgi'); | |
}); | |
// Override the writable task to change the group *and* the mode, so | |
// the group will be able to write. AFAIK the default writable task | |
// performs one (and only one!) of those actions. | |
desc('Make writable dirs'); | |
task('deploy:writable', function () { | |
$dirs = join(' ', get('writable_dirs')); | |
if (empty($dirs)) { | |
return; | |
} | |
$group = get('http_group'); | |
$mode = get('writable_chmod_mode'); | |
$recurse = get('writable_recursive') ? '-R' : ''; | |
cd('{{release_path}}'); | |
run("mkdir -p $dirs"); | |
// Ignore errors (likely due to bogus permission denied) | |
run("chgrp --quiet $recurse -H $group $dirs || :"); | |
run("chmod --quiet $recurse $mode $dirs || :"); | |
}); | |
// Use `rsync` for updating code on the remote host | |
desc('Update code'); | |
task('deploy:update_code', function () { | |
// `rsync` options | |
$options = [ | |
'-R', | |
// The `-FF` argument allows to override the rules below | |
// with local `.rsync-filter` files: see `man rsync` | |
'-FF', | |
// Default filter rules | |
'--filter="+ /app/***"', | |
'--filter="+ /composer.*"', | |
'--filter="+ /main/***"', | |
'--filter="+ /themes/***"', | |
'--filter="- /public/assets/"', | |
'--filter="- /public/resources/"', | |
'--filter="+ /public/***"', | |
'--filter="- *"', | |
]; | |
upload('./', '{{release_path}}', [ 'options' => $options ]); | |
}); | |
// Custom task that uploads the proper `.env` file | |
desc('Upload the environment file'); | |
task('silverstripe:environment', function () { | |
foreach (get('env_candidates') as $candidate) { | |
$env = parse($candidate); | |
if (file_exists($env)) { | |
upload($env, '{{release_path}}/.env'); | |
return; | |
} | |
} | |
throw new Exception('No valid .env file found.'); | |
}); | |
desc('Deploy your project'); | |
task('deploy', [ | |
'deploy:info', | |
'deploy:prepare', | |
'deploy:lock', | |
'deploy:release', | |
'deploy:update_code', | |
'silverstripe:environment', | |
'deploy:shared', | |
'deploy:writable', | |
'deploy:vendors', | |
'deploy:clear_paths', | |
'deploy:symlink', | |
'cachetool:clear:opcache', | |
'cachetool:clear:apcu', | |
'silverstripe:buildflush', | |
'deploy:unlock', | |
'cleanup', | |
'success', | |
]); | |
// Automatically unlock the deployment on failures | |
after('deploy:failed', 'deploy:unlock'); | |
task('backup:info', function () { | |
writeln("✈︎ Starting backup of <fg=cyan>{{hostname}}</fg=cyan>"); | |
}) | |
->setPrivate() | |
->shallow(); | |
// Create a local dump of the remote database | |
desc('Update the local database dump with remote content'); | |
task('backup:database', function () { | |
// Source .env to get database access settings | |
$dump = run( | |
'source {{ release_path }}/.env && mysqldump --compact' . | |
' -h$SS_DATABASE_SERVER -u$SS_DATABASE_USERNAME' . | |
' -p$SS_DATABASE_PASSWORD $SS_DATABASE_NAME' | |
); | |
// Store the database dump in the root folder of the project | |
$db = get('application', 'dump'); | |
file_put_contents("./$db.sql", $dump); | |
}); | |
// Fetch assets from the remote | |
desc('Download assets'); | |
task('backup:assets', function () { | |
// By default, consider the first shared_dirs as the assets dir | |
$dir = current(get('shared_dirs', [])); | |
if (empty($dir)) { | |
return; | |
} | |
// Download all the crap | |
$from = get('deploy_path') . '/shared/' . $dir . '/'; | |
$to = './' . $dir . '/'; | |
download($from, $to, [ 'options' => [ | |
'--delete', | |
'-a', | |
]]); | |
}); | |
task('backup:success', function () { | |
writeln('<info>Backup terminated successfully!</info>'); | |
}) | |
->local() | |
->shallow() | |
->setPrivate(); | |
desc('Backup your project'); | |
task('backup', [ | |
'backup:info', | |
'backup:database', | |
'backup:assets', | |
'backup:success', | |
]) | |
->onStage('production'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment