Deploying a Silverstripe project, being it a typical website or a custom web application, can be quite easy once you have deployer 8 installed and configured properly.
In my case I have full SSH access to all the servers I use for web development. My requirements are quite common: I should to be able to use staging hosts (so I can try or let try my latest changes before shipping the final product), easy rollback support and the ability to make database/assets backups.
Deployer is a PHP based program that does what I need in a quite straightforward way. In my opinion the fact that it is developed in PHP is not an advantage at all... quite the opposite: I need to keep a version of the PHP interpreter around just to run it. In modern days I use docker for PHP development, but deployer needs to access a lot of stuff in your local machine so I opted for a native installation.
You need to save the following deployer script somewhere in your filesystem as deployer8-silverstripe6.php. Its latest version is also available as gist.
/**
* This is the shared deployer code I use in my projects. Put it
* somewhere in your filesystem and then, for each Silverstripe project,
* add a `deploy.yaml` similar to this one:
* ```yaml
* import: /path/to/deployer8-silverstripe6.php
*
* config:
* application: 'www.my.site'
*
* hosts:
* staging:
* hostname: myvps
* deploy_path: '/var/www/staging'
* production:
* hostname: myvps
* deploy_path: '/var/www/{{application}}'
* ```
* `dep provision` is **not** needed here: webserver, PHP and database
* configuration are your responsibility. Just be sure to have a working
* ssh connection to your server and to install composer, cachetool,
* unzip, acl and rsync.
*/
namespace Deployer;
require 'recipe/silverstripe.php';
// Any setting is overridable in `deploy.yml`
set('bin/php', '/usr/bin/php8.4');
set('bin/composer', '{{bin/php}} /usr/local/bin/composer');
set('bin/cachetool', '{{bin/php}} /usr/local/bin/cachetool');
set('bin/dbdump', << false ]
);
});
// Use `rsync` for updating code on the remote host
task('deploy:update_code', function () {
upload(
get('webroot'),
get('release_or_current_path'),
[ 'options' => get('upload_options') ]
);
});
// If `deployer` is run by different user from the web user (as I do),
// `sake db:build` will fail when regenerating the static error pages
// if the old ones were generated from the web.
// Avoid the problem by removing them before the regeneration process.
task('silverstripe:remove_static_pages', function () {
run('rm {{release_or_current_path}}/{{ shared_assets }}/error-*.html', nothrow: true);
})
->hidden();
before('silverstripe:build', 'silverstripe:remove_static_pages');
before('silverstripe:buildflush', 'silverstripe:remove_static_pages');
desc('Clear opcache cache');
task('cachetool:clear:opcache', function () {
run('{{bin/cachetool}} opcache:reset -n --fcgi');
});
after('deploy:success', 'cachetool:clear:opcache');
desc('Clear APCU cache');
task('cachetool:clear:apcu', function () {
run('{{bin/cachetool}} apcu:cache:clear -n --fcgi');
});
after('deploy:success', 'cachetool:clear:apcu');
// Automatically unlock the deployment on failures
after('deploy:failed', 'deploy:unlock');
task('backup:info', function () {
info("backup of {{what}} from {{where}}");
})
->hidden();
desc('Create a local dump of the remote database');
task('backup:database', function () {
// Source .env to get database settings
$dump = run('source {{current_path}}/.env && {{bin/dbdump}}');
// TODO `$dump` contains the whole database:
// this approach is not really scalable
// Store the database dump in the root folder of the project
$db = get('application', 'dump');
file_put_contents("./$db.sql", $dump);
});
desc('Fetch assets from the remote');
task('backup:assets', function () {
download(
'{{deploy_path}}/shared/{{shared_assets}}/',
'./{{shared_assets}}/',
[ 'options' => [ '--delete', '-a' ] ]
);
});
task('backup:success', function () {
info('backup terminated successfully!');
})
->hidden();
desc('Backup your project');
task('backup', [
'backup:info',
'backup:database',
'backup:assets',
'backup:success',
]);
With that in place, adding deployer support to a Silverstripe project should be a breeze. Just add something similar to the following YAML code as deploy.yaml to your repository:
import: /path/to/deployer8-silverstripe6.php
hosts:
staging:
hostname: myserver
keep_releases: 1 # No need to rollback in staging
deploy_path: '/path/to/staging'
production:
hostname: myserver
deploy_path: '/path/to/release'
You would likely need to have different environment files to match different server configurations, i.e. I have a .env for the development machine, .env.staging for the staging host and .env.production for the production host.
When everything is in place, you can trigger whatever needed directly from the command line:
dep deploy staging # Deploy to staging host dep deploy production # Deploy to production host dep rollback production # Rollback to previous version dep backup production # Backup both assets and database dump
I do not use the provisioning feature of deployer because I think that can be better achieved with ansible, NixOS or even interactive SSH sessions.
- Posted in Software,
- PHP Silverstripe Admin
- Posted 10 hours ago by Nicola Fontana
Post your comment
Comments
No one has commented on this page yet.
RSS feed for comments on this page | RSS feed for all comments