diff --git a/config/system/additional.php b/config/system/additional.php index c648e23..4cd8155 100644 --- a/config/system/additional.php +++ b/config/system/additional.php @@ -61,7 +61,9 @@ if (getenv('IS_DDEV_PROJECT') == 'true') { ); } -if (is_file(__DIR__ . '/secrets.php')) { +// Deployer creates an empty secrets.php if none exists yet: only an array counts +$secrets = is_file(__DIR__ . '/secrets.php') ? require __DIR__ . '/secrets.php' : null; +if (is_array($secrets)) { $withoutEmptyValues = static function (array $values) use (&$withoutEmptyValues): array { foreach ($values as $key => $value) { if (is_array($value)) { @@ -74,7 +76,8 @@ if (is_file(__DIR__ . '/secrets.php')) { }; $GLOBALS['TYPO3_CONF_VARS'] = array_replace_recursive( $GLOBALS['TYPO3_CONF_VARS'], - $withoutEmptyValues(require __DIR__ . '/secrets.php') + $withoutEmptyValues($secrets) ); unset($withoutEmptyValues); } +unset($secrets); diff --git a/deploy.php b/deploy.php index af23698..d2ec180 100644 --- a/deploy.php +++ b/deploy.php @@ -1,4 +1,5 @@ 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'); @@ -89,6 +85,33 @@ task('build', function () { runLocally('cd {{build_dir}} && npm ci --no-audit --no-fund && npm run build'); })->once(); +desc('Read-only checks of the host before the first deploy (see .ddev/plans/TYPO3-13-GO-LIVE.md)'); +task('host:check', function () { + $checks = [ + 'PHP CLI 8.5.12+' => '{{bin/php}} -r \'exit(version_compare(PHP_VERSION, "8.5.12", ">=") ? 0 : 1);\' && {{bin/php}} -v | head -1', + 'PHP extensions' => '{{bin/php}} -r \'$m = array_diff(["mysqli", "pdo_mysql", "intl", "mbstring", "xml", "zip", "gd", "fileinfo", "openssl", "curl", "zlib"], get_loaded_extensions()); echo $m ? "missing: " . implode(", ", $m) : "ok"; exit($m ? 1 : 0);\'', + 'image processor (GraphicsMagick)' => 'test -x /usr/bin/gm && /usr/bin/gm version | head -1', + 'production fileadmin' => 'test -d {{fileadmin_path}} && du -sh {{fileadmin_path}} 2>/dev/null | cut -f1', + 'static/ep-reisen/fileadmin links there' => 'test "$(readlink -f /usr/home/eptypo3/public_html/static/ep-reisen/fileadmin)" = "$(readlink -f {{fileadmin_path}})" && echo yes', + 'free disk space' => 'df -h /usr/home/eptypo3 | tail -1', + 'secrets.php in place' => 'test -s {{deploy_path}}/shared/config/system/secrets.php && {{bin/php}} -r \'exit(is_array(require "{{deploy_path}}/shared/config/system/secrets.php") ? 0 : 1);\' && echo yes', + 'MyE&P reachable' => 'curl -s -o /dev/null -w "%{http_code}" --max-time 10 https://my.ep-reisen.de/api/last-update', + ]; + $failed = false; + foreach ($checks as $label => $command) { + try { + writeln(sprintf('✔ %s: %s', $label, trim(run($command)))); + } catch (\Throwable $e) { + writeln(sprintf('✘ %s', $label)); + $failed = true; + } + } + writeln('Not checkable from the CLI: open_basedir and PHP 8.5.12 (FPM) of the static vhosts, see the go-live plan.'); + if ($failed) { + throw new \RuntimeException('Host checks failed'); + } +}); + desc('Link the production fileadmin into the release'); task('typo3:fileadmin', function () { run('test -d {{fileadmin_path}}'); @@ -116,7 +139,9 @@ task('deploy', [ // 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'); +// No OPcache reset (cachetool): its web adapter would need PHP under www.ep-reisen.de/typo3temp, which +// is the static docroot. Not needed either: the front controller stubs in the static docroots resolve +// "current" with readlink() on every request, so a new release is always loaded under new paths. after('deploy:symlink', 'typo3:cache:flush'); after('deploy:failed', 'deploy:unlock'); diff --git a/public/.htaccess b/public/.htaccess index 04cc6e2..9154983 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -296,8 +296,10 @@ AddDefaultCharset utf-8 # Rules to set ApplicationContext based on hostname #RewriteCond %{HTTP_HOST} ^dev\.example\.com$ #RewriteRule .? - [E=TYPO3_CONTEXT:Development] - #RewriteCond %{HTTP_HOST} ^staging\.example\.com$ - #RewriteRule .? - [E=TYPO3_CONTEXT:Production/Staging] + # Test vhost of the hybrid go-live (base variant in config/sites/ep-reisen); production + # traffic never reaches this file, the static docroots have their own .htaccess + RewriteCond %{HTTP_HOST} ^staging\.ep-reisen\.de$ + RewriteRule .? - [E=TYPO3_CONTEXT:Production/Staging] #RewriteCond %{HTTP_HOST} ^www\.example\.com$ #RewriteRule .? - [E=TYPO3_CONTEXT:Production]