From 8a43cbb232a1483fa3500b8afa807f9b6a92df58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Sun, 13 Sep 2026 19:35:01 +0200 Subject: [PATCH] chore: adapt the deploy recipe to assetmapper --- config/packages/ux_icons.yaml | 12 +++ deploy.php | 153 ++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 deploy.php diff --git a/config/packages/ux_icons.yaml b/config/packages/ux_icons.yaml index e2c4739..9006ea4 100644 --- a/config/packages/ux_icons.yaml +++ b/config/packages/ux_icons.yaml @@ -25,3 +25,15 @@ when@prod: ux_icons: # Suppress exceptions for missing icons in production ignore_not_found: true + iconify: + # Every icon this app uses is vendored under assets/icons/ by `ux:icons:import`, so + # nothing should ever be fetched at runtime -- and more importantly, nothing should be + # fetched during `asset-map:compile`, which is a deploy step. Left enabled it reaches + # api.iconify.design and fails the build on any host without outbound internet (it + # did exactly that: "Idle timeout reached for https://api.iconify.design/collections"). + # + # Deliberately prod-only: in dev the on-demand fetch plus auto_lock above is what lets + # you write ux_icon('lucide:something') and have it downloaded and committed for you. + # The trade is that an icon nobody imported renders as nothing in prod, because + # ignore_not_found is on -- so import first, then use. + enabled: false diff --git a/deploy.php b/deploy.php new file mode 100644 index 0000000..8fffa5a --- /dev/null +++ b/deploy.php @@ -0,0 +1,153 @@ + [ + '.claude', + '.cursor', + '.idea', + '.vscode', + '.DS_Store', + '.ddev', + '.git', + '.github', + '.jj', + 'node_modules', + '.editorconfig', + '.env.dev', + '.env.dev.local', + '.env.dev.local.php', + '.env.test', + '.env.test.local', + '.gitignore', + '.nvmrc', + // Tooling this project does not carry yet, but both sibling projects do. + '.php-cs-fixer.cache', + '.php-cs-fixer.dist.php', + '.phpunit.cache', + '.phpunit.result.cache', + 'phpunit.dist.xml', + 'phpunit.xml', + 'CLAUDE.md', + 'deploy.php', + // The Tailwind toolchain is a build-time concern only: the compiled stylesheet ships as + // assets/styles/app.css, the sources and the CLI config do not. + 'package.json', + 'package-lock.json', + 'tailwind.config.js', + 'tailwind/', + // Written on the server by asset-map:compile. + 'public/assets/', + 'tests/', + 'var/', + ], + 'exclude-file' => false, + 'include' => [], + 'include-file' => false, + 'filter' => [], + 'filter-file' => false, + 'filter-perdir' => false, + 'flags' => 'rz', + 'options' => ['delete', 'copy-links', 'chmod=D755,F664'], + 'timeout' => 300, +]; + +host('prod') + ->setHostname('dedi10193.your-server.de') + ->setRemoteUser('ephubsf') + ->setForwardAgent(true) + ->setSshMultiplexing(true) + ->setDeployPath('/usr/home/ephubsf/public_html/prod') + ->set('bin/php', '/usr/bin/php') + ->set('http_user', 'ephubsf') + ->set('rsync_src', __DIR__) + ->set('rsync', $rsyncOptions) + ->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{current_path}}/public/ --web-url=https://hub.ep-reisen.de') + ->add('shared_files', [ + 'public/.htpasswd', + ]) +; + +task('deploy', [ + 'deploy:info', + 'deploy:setup', + 'deploy:lock', + 'deploy:release', + 'deploy:assets', + 'rsync', + 'deploy:shared', + 'deploy:writable', + 'deploy:cache:clear', + 'deploy:assetmap', + 'database:migrate', + 'cachetool:clear:opcache', + 'deploy:publish', + 'deploy:stop-workers', +]); + +/** + * Local build step. Produces the two things rsync has to carry that git does not: + * the compiled Tailwind stylesheet and the downloaded importmap vendor files. + */ +task('deploy:assets', function () { + runLocally('ddev exec npm ci'); + // Writes assets/styles/app.css -- must happen before asset-map:compile, or the stylesheet + // that gets versioned is whatever was lying around. + runLocally('ddev exec npm run tailwind:build'); + // assets/vendor/ is gitignored, so make sure it is actually there before it is shipped. + runLocally('ddev exec php bin/console importmap:install'); +})->once(); + +/** + * Server build step: versioned filenames and the importmap manifest under public/assets/. + * + * Runs after deploy:cache:clear so it works against a clean cache, and before deploy:publish so + * the symlink only ever flips to a release whose assets are already in place. + */ +task('deploy:assetmap', function () { + run('{{bin/console}} asset-map:compile --no-interaction'); +}); + +task('deploy:stop-workers', function () { + run('{{bin/console}} messenger:stop-workers'); +}); + +after('deploy:failed', 'deploy:unlock');