set('cachetool', '/var/run/phpfpm/PROJECT.cloonar.dev.sock'); * host('production')->set('cachetool', '/var/run/phpfpm/PROJECT.TLD.sock'); */ namespace Deployer; require 'recipe/common.php'; require 'contrib/rsync.php'; require 'contrib/cachetool.php'; set('release_or_current_path', function () { $releaseExists = test('[ -h {{deploy_path}}/release ]'); if ($releaseExists) { $link = run("readlink {{deploy_path}}/release"); return substr($link, 0, 1) === '/' ? $link : get('deploy_path') . '/' . $link; } return get('current_path'); }); // ============================================================================= // PHP Configuration // ============================================================================= set('bin/php', function () { return '/run/current-system/sw/bin/php'; }); // ============================================================================= // Shared Directories & Files // ============================================================================= set('shared_dirs', [ 'public/fileadmin', 'var' ]); set('shared_files', [ '.env', 'config/system/additional.php', ]); set('writable_dirs', [ 'public/typo3temp' ]); // ============================================================================= // Rsync Configuration // ============================================================================= set('rsync_src', '../'); set('rsync', [ 'exclude' => [ // Shared (will be symlinked) 'public/fileadmin', 'var', '.env', 'config/system/additional.php', // Build & dev '.composer-cache', 'build', '.git*', '.ddev', '.editorconfig', '.idea', 'tests', 'node_modules', // Config files '.php-cs-fixer.php', 'phpstan.neon', 'phpstan-baseline.neon', 'psalm.xml', 'psalm-baseline.xml', 'renovate.json', 'deploy-lib.php', '*.md', ], 'exclude-file' => false, 'include' => [], 'include-file' => false, 'filter' => ['dir-merge,-n /.gitignore'], 'filter-file' => false, 'filter-perdir' => false, 'flags' => 'avz', 'options' => ['delete'], 'timeout' => 300 ]); // Disable git-based code update (we use rsync) task('deploy:update_code')->hidden()->disable(); // ============================================================================= // TYPO3 Tasks // ============================================================================= task('typo3:extension:setup', function () { cd('{{release_or_current_path}}'); run('{{bin/php}} bin/typo3 extension:setup'); })->desc('Run TYPO3 extension:setup'); task('typo3:database:updateschema', function() { cd('{{release_or_current_path}}'); run('{{bin/php}} bin/typo3 database:updateschema'); }); task('typo3:referenceindex:update', function() { cd('{{release_or_current_path}}'); run('{{bin/php}} bin/typo3 referenceindex:update'); }); task('typo3:install:fixfolderstructure', function() { cd('{{release_or_current_path}}'); run('{{bin/php}} bin/typo3 install:fixfolderstructure'); }); task('typo3:cache:flush', function () { cd('{{release_or_current_path}}'); run('{{bin/php}} bin/typo3 cache:flush'); })->desc('Flush TYPO3 caches'); task('typo3:cache:warmup', function () { cd('{{release_or_current_path}}'); // Append exit code so run() won't throw before we can read the output $result = run('{{bin/php}} -d display_errors=1 bin/typo3 cache:warmup 2>&1; echo EXIT_CODE:$?'); if (!str_contains($result, 'EXIT_CODE:0')) { throw new \RuntimeException("cache:warmup failed:\n" . $result); } })->desc('Warmup TYPO3 caches'); task('typo3:language:update', function () { cd('{{release_or_current_path}}'); run('{{bin/php}} bin/typo3 language:update'); })->desc('Update TYPO3 language files'); // ============================================================================= // PHP-FPM Reload (for NixOS infrastructure) // ============================================================================= // needed for t3o infrastructure task('php:reload', function() { run('php-reload'); })->select('stage=contentmaster'); task('php:reload-prod', function() { run('php-reload'); })->select('stage=production'); // ============================================================================= // Deployment Strategies // ============================================================================= /** * release:create - Upload new release without switching * Use for staged deployments where you want to test before switching */ task('release:create', [ 'deploy:prepare', 'rsync', 'deploy:vendors', 'deploy:shared', 'deploy:writable', 'typo3:install:fixfolderstructure', // Safe, just creates folders 'deploy:unlock', 'deploy:success' ])->desc('Create new release (upload only, no switch)'); /** * release:switch - Switch to latest release and cleanup * Run after release:create once testing passes */ task('release:switch', [ 'deploy:symlink', 'php:reload', 'php:reload-prod', 'typo3:extension:setup', // DB schema for extensions 'typo3:database:updateschema', // Core DB migrations 'typo3:cache:flush', 'typo3:referenceindex:update', // Fix reference index 'typo3:language:update', 'typo3:cache:warmup', 'deploy:unlock', 'deploy:cleanup', 'deploy:success' ])->desc('Switch to latest release'); // ============================================================================= // Hooks // ============================================================================= // Unlock on failure after('deploy:failed', 'deploy:unlock'); // set release path after symlink after('deploy:symlink', function () { set('release_path', get('current_path')); }); // clear opcache after symlink after('deploy:symlink', 'cachetool:clear:opcache');