chore: Deployer configuration for the production host
Built locally from the committed state (git archive, composer install --no-dev, theme build) and synced with rsync, so the host needs neither Composer nor Node. Shared: secrets.php, logs, locks, typo3temp/assets and the MyE&P import baseline. fileadmin links to the production fileadmin of the TYPO3 10 release, which the CDN origin serves. extension:setup before the switch, OPcache and TYPO3 caches after it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
96a9c7217d
commit
214b4b6b86
1 file changed
+122
+122
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
namespace Deployer;
|
||||
|
||||
// Run inside DDEV after "ddev auth ssh": ddev exec vendor/bin/dep deploy
|
||||
// Prerequisites on the host: see .ddev/plans/TYPO3-13-GO-LIVE.md (PHP 8.5.12, database, secrets.php)
|
||||
|
||||
require 'recipe/typo3.php';
|
||||
require 'contrib/rsync.php';
|
||||
require 'contrib/cachetool.php';
|
||||
|
||||
set('application', 'ep-reisen-13');
|
||||
set('keep_releases', 3);
|
||||
|
||||
// The release is built locally from the committed state, so nothing uncommitted is ever deployed
|
||||
// and the host needs neither Composer nor Node
|
||||
set('build_dir', __DIR__ . '/var/deploy-build');
|
||||
set('use_rsync', true);
|
||||
set('rsync_src', '{{build_dir}}');
|
||||
|
||||
// fileadmin is the production fileadmin of the TYPO3 10 release: it is the CDN origin's fileadmin
|
||||
// (static/ep-reisen/fileadmin links there too), and TYPO3 13 writes its processed images into it
|
||||
set('fileadmin_path', '/usr/home/eptypo3/public_html/ep-reisen-typo3/shared/public/fileadmin');
|
||||
|
||||
set('shared_dirs', [
|
||||
'{{typo3/public_dir}}/typo3temp/assets',
|
||||
'var/lock',
|
||||
'var/log',
|
||||
'var/session',
|
||||
'var/spool',
|
||||
// Baseline of the MyE&P import: without it every deploy would trigger a full re-import
|
||||
'var/transient/ep_products_import',
|
||||
]);
|
||||
set('shared_files', [
|
||||
'config/system/secrets.php',
|
||||
]);
|
||||
set('writable_dirs', [
|
||||
'{{typo3/public_dir}}/typo3temp/assets',
|
||||
'var/cache',
|
||||
'var/lock',
|
||||
'var/log',
|
||||
'var/transient',
|
||||
]);
|
||||
set('writable_mode', 'chmod');
|
||||
|
||||
$rsync = get('rsync');
|
||||
$rsync['exclude'] = array_merge($rsync['exclude'], [
|
||||
'/{{typo3/public_dir}}/fileadmin',
|
||||
'node_modules',
|
||||
'/packages/*/Resources/Private/Assets',
|
||||
'/.ddev',
|
||||
'/deploy.php',
|
||||
'/rector.php',
|
||||
'/fractor.php',
|
||||
'/webpack.config.js',
|
||||
'/tailwind.config.js',
|
||||
'/package.json',
|
||||
'/package-lock.json',
|
||||
'/.nvmrc',
|
||||
]);
|
||||
// The build directory has no .gitignore filtering to do, and the filter would drop the built assets
|
||||
$rsync['filter'] = [];
|
||||
// -t preserves mtimes: without it every file lands with a fresh timestamp, so unchanged
|
||||
// files get a new Last-Modified on every deploy and every conditional request revalidates
|
||||
// into a full response instead of a 304.
|
||||
$rsync['flags'] = 'rzt';
|
||||
$rsync['options'] = ['delete', 'links', 'chmod=D755,F664'];
|
||||
set('rsync', $rsync);
|
||||
|
||||
host('prod')
|
||||
->setHostname('dedi10193.your-server.de')
|
||||
->setRemoteUser('eptypo3')
|
||||
->setForwardAgent(true)
|
||||
->setSshMultiplexing(true)
|
||||
->setDeployPath('/usr/home/eptypo3/public_html/{{application}}')
|
||||
// Verify on the host once Hetzner has installed it
|
||||
->set('bin/php', '/usr/bin/php85')
|
||||
->set('http_user', 'eptypo3')
|
||||
// The temp script goes into the shared typo3temp, which resolves to the same directory from every
|
||||
// release: PHP workers with a stale realpath cache still map "current" to the previous release and
|
||||
// would 404 on a script placed inside the new one.
|
||||
->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{deploy_path}}/shared/{{typo3/public_dir}}/typo3temp/assets/ --web-url=https://www.ep-reisen.de/typo3temp/assets')
|
||||
;
|
||||
|
||||
desc('Build the release locally: committed state, production dependencies, theme assets');
|
||||
task('build', function () {
|
||||
runLocally('rm -rf {{build_dir}} && mkdir -p {{build_dir}}');
|
||||
runLocally('git archive HEAD | tar -x -C {{build_dir}}');
|
||||
runLocally('cd {{build_dir}} && composer install --no-dev --prefer-dist --no-progress --no-interaction --optimize-autoloader');
|
||||
runLocally('cd {{build_dir}} && npm ci --no-audit --no-fund && npm run build');
|
||||
})->once();
|
||||
|
||||
desc('Link the production fileadmin into the release');
|
||||
task('typo3:fileadmin', function () {
|
||||
run('test -d {{fileadmin_path}}');
|
||||
run('ln -sfn {{fileadmin_path}} {{release_path}}/{{typo3/public_dir}}/fileadmin');
|
||||
});
|
||||
|
||||
desc('Deploys TYPO3 13');
|
||||
task('deploy', [
|
||||
'deploy:info',
|
||||
// Build first, so a failing build aborts before the server is touched at all.
|
||||
'build',
|
||||
'deploy:setup',
|
||||
'deploy:lock',
|
||||
'deploy:release',
|
||||
'rsync',
|
||||
'deploy:shared',
|
||||
'typo3:fileadmin',
|
||||
'deploy:writable',
|
||||
// The schema has to exist before the new code starts serving traffic (adds and changes only).
|
||||
'typo3:extension:setup',
|
||||
// deploy:publish == deploy:symlink, deploy:unlock, deploy:cleanup, deploy:success
|
||||
'deploy:publish',
|
||||
]);
|
||||
|
||||
// Caches belong to the release that goes live, so they are cleared after the symlink flip. Hooking
|
||||
// into deploy:symlink rather than appending to the list above keeps them inside deploy:publish, ahead
|
||||
// of deploy:unlock and deploy:success - a failing cache task must not follow a declared success.
|
||||
after('deploy:symlink', 'cachetool:clear:opcache');
|
||||
after('deploy:symlink', 'typo3:cache:flush');
|
||||
|
||||
after('deploy:failed', 'deploy:unlock');
|
||||
Reference in new issue
Block a user