#!/bin/sh set -e # Only the app container runs setup; queue/scheduler use entrypoint-worker.sh instead # and just wait on the migrated marker this script writes below. if [ "$APP_ENV" != "production" ]; then # Dev-only: the app dir is bind-mounted from a fresh checkout, so there's no # image-build step that already installed vendor/ or published assets — this # container has to do it at boot instead. In production the Dockerfile already # runs composer install and asset publishing at IMAGE BUILD time (see # Dockerfile's `production` stage), so repeating them here would be wasteful, # not just redundant-but-safe. echo "[entrypoint] Installing Composer dependencies..." git config --global --add safe.directory /var/www/html 2>/dev/null || true git config --global --add safe.directory /var/www/boboko-core 2>/dev/null || true composer install --no-interaction --prefer-dist # Re-resolve boboko/* on every boot, whether it's a local path-repo checkout # (../boboko-core mounted via docker-compose.core-dev.yml) or a VCS tag. Rewrites # composer.lock, which is committed so prod picks up the resolved version via # `composer install` alone. echo "[entrypoint] Re-resolving boboko/* packages..." composer update "boboko/*" --no-interaction --with-all-dependencies fi mkdir -p storage/app/public storage/framework/cache storage/framework/sessions storage/framework/views storage/logs storage/framework bootstrap/cache chown -R www-data:www-data storage bootstrap/cache chmod -R 775 storage bootstrap/cache # Composer packages (dev) may have just changed above, or (production) this is a # freshly built image — either way, clear any cached config/routes/compiled views # left over from a previous boot before anything below reads them. Production # runs a single app instance that gets replaced on every deploy, not a running # process being told to forget in-memory code — the actual bug this fixes is # stale artifacts still sitting in bootstrap/cache or storage/framework/views on # a fresh boot (e.g. after the Lunar 1.5/Filament v4 upgrade, a leftover compiled # view referenced a class that upgrade removed). echo "[entrypoint] Clearing cached config/routes/views..." php artisan optimize:clear --quiet echo "[entrypoint] Caches cleared" php artisan storage:link --quiet 2>/dev/null || true if [ "$APP_ENV" != "production" ]; then # Dev-only for the same reason as the composer step above — production's # image already has these published at build time. php artisan vendor:publish --tag=core-assets --force --ansi --quiet php artisan vendor:publish --tag=public --force --ansi --quiet php artisan filament:assets --ansi --quiet # No --force: core-views publishes editable Blade templates (order # notification emails), meant to be hand-customized per app — unlike # core-assets above, republishing must not silently wipe local edits. # Only fills in the vendor/core views directory if it doesn't exist yet. php artisan vendor:publish --tag=core-views --ansi --quiet fi # Everything below is universal, in both dev and production: application STATE # that must be current on every boot, not a build-time concern composer/assets # are. Safe to run unconditionally on every boot because production runs a # single app instance — no concurrent replicas that would race each other # running `migrate --force` at the same time. echo "[entrypoint] Running migrations..." rm -f storage/framework/migrated php artisan migrate --force echo "[entrypoint] Touching migrated file" touch storage/framework/migrated echo "[entrypoint] Touched migrated file" # boboko/core overrides lunar:install to skip the interactive prompts (migrate # confirm, admin creation, GitHub star) and just seed the idempotent store # defaults: countries, channel, language, currency, tax zone, attributes, # product type. queue/scheduler wait on the marker above rather than running # this themselves, since the country import's check-then-insert isn't safe to # run concurrently. A fresh production install needs this seeding the same as # a fresh dev one does — and re-running it against an already-seeded store is # a no-op per key (see InstallLunarCommand's idempotent upserts). echo "[entrypoint] Trying Lunar install" php artisan lunar:install --quiet || true # Upserts by primary key (no --refresh), so this stays cheap and idempotent on # every boot rather than flushing and rebuilding the whole index each time. Runs # in production too — a deploy that changed an indexer's field list needs this # to keep Meilisearch's index settings and documents in sync with the code that # just shipped, same reasoning as optimize:clear above. echo "[entrypoint] Syncing search indexes..." php artisan lunar:meilisearch:setup php artisan lunar:meilisearch:tune-product-search --quiet || true php artisan lunar:search:index --quiet || true if [ "$APP_ENV" = "production" ]; then # The counterpart to optimize:clear above: config/routes/views/events get # compiled once here, at the end of boot, after everything that could # change them (migrations, lunar:install, index sync) has already run — # so production actually gets the request-time performance win caching is # for, rather than staying permanently uncached. Dev deliberately never # does this: caching config here would mean .env/config edits stop taking # effect until the next optimize:clear, which is the opposite of what dev # needs on every iteration. echo "[entrypoint] Caching config/routes/views for production..." php artisan optimize --quiet echo "[entrypoint] Production caches built" fi exec "$@"