diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..dc5a8752 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,34 @@ +**/*.log +**/*.md +**/*.php~ +**/*.dist.php +**/*.dist +**/*.cache +**/._* +**/.dockerignore +**/.DS_Store +**/.git/ +**/.gitattributes +**/.gitignore +**/.gitmodules +**/compose.*.yaml +**/compose.*.yml +**/compose.yaml +**/compose.yml +**/docker-compose.*.yaml +**/docker-compose.*.yml +**/docker-compose.yaml +**/docker-compose.yml +**/Dockerfile +**/Thumbs.db +.github/ +docs/ +public/bundles/ +tests/ +var/ +vendor/ +.editorconfig +.env.*.local +.env.local +.env.local.php +.env.test diff --git a/.env b/.env index 476df852..745bff94 100644 --- a/.env +++ b/.env @@ -9,13 +9,14 @@ # Real environment variables win over .env files. # # DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. +# https://symfony.com/doc/current/configuration/secrets.html # # Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). # https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration ###> symfony/framework-bundle ### APP_ENV=dev -APP_SECRET=6feff92fb5278f215ddca9545d19fcd3 +APP_SECRET=421f03e82270a0883f2db17c436d6b81 ###< symfony/framework-bundle ### ###> doctrine/doctrine-bundle ### @@ -23,14 +24,13 @@ APP_SECRET=6feff92fb5278f215ddca9545d19fcd3 # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml # # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" -DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" +DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.35&charset=utf8mb4" # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" # DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=15&charset=utf8" ###< doctrine/doctrine-bundle ### ###> symfony/mailer ### # MAILER_DSN=smtp://user:pass@smtp.example.com -# MAILER_DSN=gmail://USERNAME:PASSWORD@default MAILER_DSN=null://localhost ###< symfony/mailer ### @@ -41,9 +41,6 @@ MAILER_DSN=null://localhost MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 ###< symfony/messenger ### -# Select default language (en, ru, bg, nl) -LANGUAGE_CODE=en - ###> symfony/google-mailer ### # Gmail SHOULD NOT be used on production, use it in development only. # MAILER_DSN=gmail://USERNAME:PASSWORD@default @@ -54,3 +51,6 @@ LANGUAGE_CODE=en # postgresql+advisory://db_user:db_password@localhost/db_name LOCK_DSN=flock ###< symfony/lock ### + +# Select default language (en, ru, bg, nl) +LANGUAGE_CODE=en diff --git a/.env.test b/.env.test index 0812ddfb..4362c7ed 100644 --- a/.env.test +++ b/.env.test @@ -4,4 +4,7 @@ APP_SECRET='$ecretf0rt3st' SYMFONY_DEPRECATIONS_HELPER=999999 PANTHER_APP_ENV=test PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots -DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name +DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.35&charset=utf8mb4" + +PANTHER_CHROME_ARGUMENTS="--disable-dev-shm-usage" +PANTHER_NO_SANDBOX="1" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..642c91f2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +* text=auto eol=lf + +*.conf text eol=lf +*.html text eol=lf +*.ini text eol=lf +*.js text eol=lf +*.json text eol=lf +*.md text eol=lf +*.php text eol=lf +*.sh text eol=lf +*.yaml text eol=lf +*.yml text eol=lf +bin/console text eol=lf +composer.lock text eol=lf merge=ours + +*.ico binary +*.png binary diff --git a/.github/workflows/frankenphp.yml b/.github/workflows/frankenphp.yml new file mode 100644 index 00000000..0de5daea --- /dev/null +++ b/.github/workflows/frankenphp.yml @@ -0,0 +1,57 @@ +name: FrankenPHP + +on: + push: + branches: + - master + - 2.x + - docker + pull_request: ~ + workflow_dispatch: ~ + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v4 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - + name: Build Docker images + uses: docker/bake-action@v4 + with: + pull: true + load: true + files: | + compose.yaml + compose.override.yaml + set: | + *.cache-from=type=gha,scope=${{github.ref}} + *.cache-from=type=gha,scope=refs/heads/main + *.cache-to=type=gha,scope=${{github.ref}},mode=max + - + name: Start services + run: docker compose up --wait --no-build + - + name: Check HTTP reachability + run: curl -v -o /dev/null http://localhost + - + name: Check HTTPS reachability + run: curl -vk -o /dev/null https://localhost + - + name: Install the app + run: docker compose exec -T php bin/console -e test app:install + - + name: Run PHPUnit + run: docker compose exec -T php bin/phpunit + - + name: Doctrine Schema Validator + run: docker compose exec -T php bin/console -e test doctrine:schema:validate diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..c49a3920 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,113 @@ +#syntax=docker/dockerfile:1.4 + +# Versions +FROM dunglas/frankenphp:1-alpine AS frankenphp_upstream +FROM composer/composer:2-bin AS composer_upstream + + +# The different stages of this Dockerfile are meant to be built into separate images +# https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage +# https://docs.docker.com/compose/compose-file/#target + + +# Base FrankenPHP image +FROM frankenphp_upstream AS frankenphp_base + +WORKDIR /app + +# persistent / runtime deps +# hadolint ignore=DL3018 +RUN apk add --no-cache \ + acl \ + file \ + gettext \ + git \ + ; + +RUN set -eux; \ + install-php-extensions \ + apcu \ + gd \ + intl \ + opcache \ + zip \ + ; + +###> recipes ### +###> symfony/panther ### +# Chromium and ChromeDriver +ENV PANTHER_NO_SANDBOX 1 +# Not mandatory, but recommended +ENV PANTHER_CHROME_ARGUMENTS='--disable-dev-shm-usage' +RUN apk add --no-cache chromium chromium-chromedriver + +# Firefox and geckodriver +#ARG GECKODRIVER_VERSION=0.29.0 +#RUN apk add --no-cache firefox +#RUN wget -q https://github.com/mozilla/geckodriver/releases/download/v$GECKODRIVER_VERSION/geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz; \ +# tar -zxf geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz -C /usr/bin; \ +# rm geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz +###< symfony/panther ### +###> doctrine/doctrine-bundle ### +RUN install-php-extensions pdo_mysql +###< doctrine/doctrine-bundle ### +###< recipes ### + +COPY --link frankenphp/conf.d/app.ini $PHP_INI_DIR/conf.d/ +COPY --link --chmod=755 frankenphp/docker-entrypoint.sh /usr/local/bin/docker-entrypoint +COPY --link frankenphp/Caddyfile /etc/caddy/Caddyfile + +ENTRYPOINT ["docker-entrypoint"] + +# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser +ENV COMPOSER_ALLOW_SUPERUSER=1 +ENV PATH="${PATH}:/root/.composer/vendor/bin" + +COPY --from=composer_upstream --link /composer /usr/bin/composer + +HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1 +CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile" ] + +# Dev FrankenPHP image +FROM frankenphp_base AS frankenphp_dev + +ENV APP_ENV=dev XDEBUG_MODE=off +VOLUME /app/var/ + +RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" + +RUN set -eux; \ + install-php-extensions \ + xdebug \ + ; + +COPY --link frankenphp/conf.d/app.dev.ini $PHP_INI_DIR/conf.d/ + +CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile", "--watch" ] + +# Prod FrankenPHP image +FROM frankenphp_base AS frankenphp_prod + +ENV APP_ENV=prod +ENV FRANKENPHP_CONFIG="import worker.Caddyfile" + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" + +COPY --link frankenphp/conf.d/app.prod.ini $PHP_INI_DIR/conf.d/ +COPY --link frankenphp/worker.Caddyfile /etc/caddy/worker.Caddyfile + +# prevent the reinstallation of vendors at every changes in the source code +COPY --link composer.* symfony.* ./ +RUN set -eux; \ + composer install --no-cache --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress + +# copy sources +COPY --link . ./ +RUN rm -Rf frankenphp/ + +RUN set -eux; \ + mkdir -p var/cache var/log; \ + composer dump-autoload --classmap-authoritative --no-dev; \ + composer dump-env prod; \ + composer run-script --no-dev post-install-cmd; \ + chmod +x bin/console; sync; diff --git a/babel.config.js b/babel.config.js index b14943fe..d7dd5f85 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,19 +1,19 @@ -module.exports = { - presets: [ - [ - '@babel/preset-env', - { - modules: 'auto', - targets: { node: 'current' } - } - ] - ], - plugins: [ - [ - '@babel/plugin-proposal-class-properties', - { - loose: true - } - ] - ] -}; +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + modules: 'auto', + targets: { node: 'current' } + } + ] + ], + plugins: [ + [ + '@babel/plugin-proposal-class-properties', + { + loose: true + } + ] + ] +}; diff --git a/compose.override.yaml b/compose.override.yaml new file mode 100644 index 00000000..5317a972 --- /dev/null +++ b/compose.override.yaml @@ -0,0 +1,38 @@ +# Development environment override +services: + php: + build: + context: . + target: frankenphp_dev + volumes: + - ./:/app + - ./frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro + - ./frankenphp/conf.d/app.dev.ini:/usr/local/etc/php/conf.d/app.dev.ini:ro + # If you develop on Mac or Windows you can remove the vendor/ directory + # from the bind-mount for better performance by enabling the next line: + #- /app/vendor + environment: + MERCURE_EXTRA_DIRECTIVES: demo + # See https://xdebug.org/docs/all_settings#mode + XDEBUG_MODE: "${XDEBUG_MODE:-off}" + extra_hosts: + # Ensure that host.docker.internal is correctly defined on Linux + - host.docker.internal:host-gateway + tty: true + +###> symfony/mercure-bundle ### +###< symfony/mercure-bundle ### + +###> doctrine/doctrine-bundle ### + mysql: + ports: + - "3306" +###< doctrine/doctrine-bundle ### + +###> symfony/mailer ### + mailhog: + image: mailhog/mailhog + ports: + - "1025:1025" + - "8025:8025" +###< symfony/mailer ### diff --git a/compose.prod.yaml b/compose.prod.yaml new file mode 100644 index 00000000..f0db05da --- /dev/null +++ b/compose.prod.yaml @@ -0,0 +1,10 @@ +# Production environment override +services: + php: + build: + context: . + target: frankenphp_prod + environment: + APP_SECRET: ${APP_SECRET} + MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET} + MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET} diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 00000000..e7543115 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,68 @@ +services: + php: + image: ${IMAGES_PREFIX:-}app-php + restart: unless-stopped + environment: + SERVER_NAME: ${SERVER_NAME:-localhost}, php:80 + MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} + MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} + TRUSTED_PROXIES: ${TRUSTED_PROXIES:-127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16} + TRUSTED_HOSTS: ^${SERVER_NAME:-example\.com|localhost}|php$$ + # Run "composer require symfony/orm-pack" to install and configure Doctrine ORM + DATABASE_URL: mysql://${MYSQL_USER:-app}:${MYSQL_PASSWORD:-!ChangeMe!}@mysql:3306/${MYSQL_DATABASE:-app}?serverVersion=${MYSQL_VERSION:-8.0.35}&charset=utf8mb4 + # Run "composer require symfony/mercure-bundle" to install and configure the Mercure integration + MERCURE_URL: ${CADDY_MERCURE_URL:-http://php/.well-known/mercure} + MERCURE_PUBLIC_URL: https://${SERVER_NAME:-localhost}/.well-known/mercure + MERCURE_JWT_SECRET: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} + # The two next lines can be removed after initial installation + SYMFONY_VERSION: ${SYMFONY_VERSION:-} + STABILITY: ${STABILITY:-stable} + volumes: + - caddy_data:/data + - caddy_config:/config + ports: + # HTTP + - target: 80 + published: ${HTTP_PORT:-80} + protocol: tcp + # HTTPS + - target: 443 + published: ${HTTPS_PORT:-443} + protocol: tcp + # HTTP/3 + - target: 443 + published: ${HTTP3_PORT:-443} + protocol: udp + +# Mercure is installed as a Caddy module, prevent the Flex recipe from installing another service +###> symfony/mercure-bundle ### +###< symfony/mercure-bundle ### + +###> doctrine/doctrine-bundle ### + mysql: + image: mysql:${MYSQL_VERSION:-8.0.35} + environment: + MYSQL_DATABASE: ${MYSQL_DATABASE:-app} + # You should definitely change the password in production + MYSQL_PASSWORD: ${MYSQL_PASSWORD:-!ChangeMe!} + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root} + MYSQL_USER: ${MYSQL_USER:-app} + volumes: + - db_data:/var/lib/mysql + ports: + - 3306:3306 +###< doctrine/doctrine-bundle ### + + phpmyadmin: + image: phpmyadmin/phpmyadmin + restart: always + environment: + PMA_HOST: mysql + PMA_PORT: 3306 + ports: + - 8081:80 + +volumes: + caddy_data: + caddy_config: + db_data: diff --git a/composer.json b/composer.json index af2f8895..5f441f96 100644 --- a/composer.json +++ b/composer.json @@ -125,7 +125,8 @@ "extra": { "symfony": { "allow-contrib": true, - "require": "6.4.*" + "require": "6.4.*", + "docker": true } } } diff --git a/config/routes/scheb_2fa.yaml b/config/routes/scheb_2fa.yaml new file mode 100644 index 00000000..17f89595 --- /dev/null +++ b/config/routes/scheb_2fa.yaml @@ -0,0 +1,7 @@ +2fa_login: + path: /{_locale}/2fa + defaults: + _controller: "scheb_two_factor.form_controller::form" + +2fa_login_check: + path: /{_locale}/2fa_check diff --git a/config/routes/sched_2fa.yaml b/config/routes/sched_2fa.yaml deleted file mode 100644 index 33020f10..00000000 --- a/config/routes/sched_2fa.yaml +++ /dev/null @@ -1,7 +0,0 @@ -2fa_login: - path: /{_locale}/2fa - defaults: - _controller: "scheb_two_factor.form_controller::form" - -2fa_login_check: - path: /{_locale}/2fa_check diff --git a/config/routes/security.yaml b/config/routes/security.yaml new file mode 100644 index 00000000..f853be15 --- /dev/null +++ b/config/routes/security.yaml @@ -0,0 +1,3 @@ +_security_logout: + resource: security.route_loader.logout + type: service diff --git a/docs/docker.md b/docs/docker.md index 7201b034..7c2e615a 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -1,43 +1,36 @@ ## How to run Residence CMS in Docker Containers ## -1. Clone repositories -``` -$ git clone https://github.com/eko/docker-symfony.git -$ cd docker-symfony -$ git checkout 62c9592 -$ git clone https://github.com/Coderberg/ResidenceCMS.git symfony +1. Clone repository +```shell +git clone https://github.com/Coderberg/ResidenceCMS.git +cd ResidenceCMS ``` -2. Create ```.env``` files +2. Create a `.env.local` file and update the `MAILER_DSN` variable to use MailHog +```shell +cp .env .env.local +sed -i 's/MAILER_DSN=.*/MAILER_DSN=smtp:\/\/mailhog:1025/' .env.local ``` -$ echo -e ' -DATABASE_URL=mysql://symfony:symfony@db/symfony?serverVersion=5.7\r -LOCK_DSN=flock\r -LANGUAGE_CODE=en' > ./symfony/.env.local - -$ echo -e "\ -KERNEL_CLASS='App\Kernel'\r\ -APP_SECRET=34c32c8b0a7cc951fd105659f77ec1b6\r\ -SYMFONY_DEPRECATIONS_HELPER=999999\r\ -PANTHER_APP_ENV=panther\r\ -DATABASE_URL=mysql://symfony:symfony@db/symfony\r\ -" > ./symfony/.env.test.local +3. Build and run containers +```shell +docker compose build --no-cache +docker compose up --pull always -d --wait ``` -3. Run containers +4. Install the app ``` -$ docker-compose up -d -$ docker exec -it docker-symfony-php-1 /bin/sh +docker compose exec -T php bin/console app:install +docker compose exec -T php bin/phpunit ``` -4. Install app -``` -# composer install -# php bin/console app:install -# find ./public/uploads -type d -print | xargs chmod 777 +5. Open `https://localhost` in your favorite web browser and [accept the auto-generated TLS certificate](https://stackoverflow.com/a/15076602/1352334) -# php bin/phpunit --testsuite=main -``` +--- + +Additional services: + +- PhpMyAdmin http://localhost:8081 +- MailHog http://localhost:8025 -5. Go to http://symfony.localhost +See more detailed documentation here https://github.com/dunglas/symfony-docker diff --git a/frankenphp/Caddyfile b/frankenphp/Caddyfile new file mode 100644 index 00000000..3056acdf --- /dev/null +++ b/frankenphp/Caddyfile @@ -0,0 +1,55 @@ +{ + {$CADDY_GLOBAL_OPTIONS} + + frankenphp { + {$FRANKENPHP_CONFIG} + } + + # https://caddyserver.com/docs/caddyfile/directives#sorting-algorithm + order mercure after encode + order vulcain after reverse_proxy + order php_server before file_server +} + +{$CADDY_EXTRA_CONFIG} + +{$SERVER_NAME:localhost} { + log { + # Redact the authorization query parameter that can be set by Mercure + format filter { + wrap console + fields { + uri query { + replace authorization REDACTED + } + } + } + } + + root * /app/public + encode zstd gzip + + mercure { + # Transport to use (default to Bolt) + transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db} + # Publisher JWT key + publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG} + # Subscriber JWT key + subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG} + # Allow anonymous subscribers (double-check that it's what you want) + anonymous + # Enable the subscription API (double-check that it's what you want) + subscriptions + # Extra directives + {$MERCURE_EXTRA_DIRECTIVES} + } + + vulcain + + {$CADDY_SERVER_EXTRA_DIRECTIVES} + + # Disable Topics tracking if not enabled explicitly: https://github.com/jkarlin/topics + header ?Permissions-Policy "browsing-topics=()" + + php_server +} diff --git a/frankenphp/conf.d/app.dev.ini b/frankenphp/conf.d/app.dev.ini new file mode 100644 index 00000000..e50f43d0 --- /dev/null +++ b/frankenphp/conf.d/app.dev.ini @@ -0,0 +1,5 @@ +; See https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host +; See https://github.com/docker/for-linux/issues/264 +; The `client_host` below may optionally be replaced with `discover_client_host=yes` +; Add `start_with_request=yes` to start debug session on each request +xdebug.client_host = host.docker.internal diff --git a/frankenphp/conf.d/app.ini b/frankenphp/conf.d/app.ini new file mode 100644 index 00000000..501fa84f --- /dev/null +++ b/frankenphp/conf.d/app.ini @@ -0,0 +1,14 @@ +variables_order = EGPCS +expose_php = 0 +date.timezone = UTC +apc.enable_cli = 1 +session.use_strict_mode = 1 +zend.detect_unicode = 0 + +; https://symfony.com/doc/current/performance.html +realpath_cache_size = 4096K +realpath_cache_ttl = 600 +opcache.interned_strings_buffer = 16 +opcache.max_accelerated_files = 20000 +opcache.memory_consumption = 256 +opcache.enable_file_override = 1 diff --git a/frankenphp/conf.d/app.prod.ini b/frankenphp/conf.d/app.prod.ini new file mode 100644 index 00000000..3bcaa71e --- /dev/null +++ b/frankenphp/conf.d/app.prod.ini @@ -0,0 +1,2 @@ +opcache.preload_user = root +opcache.preload = /app/config/preload.php diff --git a/frankenphp/docker-entrypoint.sh b/frankenphp/docker-entrypoint.sh new file mode 100644 index 00000000..bdddc3ac --- /dev/null +++ b/frankenphp/docker-entrypoint.sh @@ -0,0 +1,60 @@ +#!/bin/sh +set -e + +if [ "$1" = 'frankenphp' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then + # Install the project the first time PHP is started + # After the installation, the following block can be deleted + if [ ! -f composer.json ]; then + rm -Rf tmp/ + composer create-project "symfony/skeleton $SYMFONY_VERSION" tmp --stability="$STABILITY" --prefer-dist --no-progress --no-interaction --no-install + + cd tmp + cp -Rp . .. + cd - + rm -Rf tmp/ + + composer require "php:>=$PHP_VERSION" runtime/frankenphp-symfony + composer config --json extra.symfony.docker 'true' + + if grep -q ^DATABASE_URL= .env; then + echo "To finish the installation please press Ctrl+C to stop Docker Compose and run: docker compose up --build -d --wait" + sleep infinity + fi + fi + + if [ -z "$(ls -A 'vendor/' 2>/dev/null)" ]; then + composer install --prefer-dist --no-progress --no-interaction + fi + + if grep -q ^DATABASE_URL= .env; then + echo "Waiting for database to be ready..." + ATTEMPTS_LEFT_TO_REACH_DATABASE=60 + until [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ] || DATABASE_ERROR=$(php bin/console dbal:run-sql -q "SELECT 1" 2>&1); do + if [ $? -eq 255 ]; then + # If the Doctrine command exits with 255, an unrecoverable error occurred + ATTEMPTS_LEFT_TO_REACH_DATABASE=0 + break + fi + sleep 1 + ATTEMPTS_LEFT_TO_REACH_DATABASE=$((ATTEMPTS_LEFT_TO_REACH_DATABASE - 1)) + echo "Still waiting for database to be ready... Or maybe the database is not reachable. $ATTEMPTS_LEFT_TO_REACH_DATABASE attempts left." + done + + if [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ]; then + echo "The database is not up or not reachable:" + echo "$DATABASE_ERROR" + exit 1 + else + echo "The database is now ready and reachable" + fi + + if [ "$( find ./migrations -iname '*.php' -print -quit )" ]; then + php bin/console doctrine:migrations:migrate --no-interaction + fi + fi + + setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var + setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var +fi + +exec docker-php-entrypoint "$@" diff --git a/frankenphp/worker.Caddyfile b/frankenphp/worker.Caddyfile new file mode 100644 index 00000000..d384ae4c --- /dev/null +++ b/frankenphp/worker.Caddyfile @@ -0,0 +1,4 @@ +worker { + file ./public/index.php + env APP_RUNTIME Runtime\FrankenPhpSymfony\Runtime +} diff --git a/phpstan.neon b/phpstan.dist.neon similarity index 100% rename from phpstan.neon rename to phpstan.dist.neon diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 890644a1..7b2293f8 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,6 +16,7 @@ + diff --git a/symfony.lock b/symfony.lock index 894b1484..6fffb4ce 100644 --- a/symfony.lock +++ b/symfony.lock @@ -1,6 +1,6 @@ { "doctrine/annotations": { - "version": "1.13", + "version": "2.0", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -9,12 +9,12 @@ } }, "doctrine/doctrine-bundle": { - "version": "2.10", + "version": "2.11", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", "version": "2.10", - "ref": "0db4b12b5df45f5122213b4ecd18733ab7fa7d53" + "ref": "0b4a11ee7e60b36227502ed26874edd7e8b66353" }, "files": [ "config/packages/doctrine.yaml", @@ -23,7 +23,7 @@ ] }, "doctrine/doctrine-fixtures-bundle": { - "version": "3.4", + "version": "3.5", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -35,7 +35,7 @@ ] }, "doctrine/doctrine-migrations-bundle": { - "version": "3.2", + "version": "3.3", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -48,7 +48,7 @@ ] }, "friendsofphp/php-cs-fixer": { - "version": "3.13", + "version": "3.40", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -60,7 +60,7 @@ ] }, "knplabs/knp-paginator-bundle": { - "version": "v5.9.0" + "version": "v6.3.0" }, "phpstan/phpstan": { "version": "1.10", @@ -68,10 +68,10 @@ "repo": "github.com/symfony/recipes-contrib", "branch": "main", "version": "1.0", - "ref": "d74d4d719d5f53856c9c13544aa22d44144b1819" + "ref": "5e490cc197fb6bb1ae22e5abbc531ddc633b6767" }, "files": [ - "phpstan.neon" + "phpstan.dist.neon" ] }, "phpunit/phpunit": { @@ -89,7 +89,7 @@ ] }, "scheb/2fa-bundle": { - "version": "6.8", + "version": "6.12", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -102,7 +102,7 @@ ] }, "symfony/console": { - "version": "6.2", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -114,7 +114,7 @@ ] }, "symfony/debug-bundle": { - "version": "6.2", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -126,7 +126,7 @@ ] }, "symfony/flex": { - "version": "2.2", + "version": "2.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -157,7 +157,7 @@ ] }, "symfony/google-mailer": { - "version": "6.2", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -166,7 +166,7 @@ } }, "symfony/lock": { - "version": "6.1", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -178,7 +178,7 @@ ] }, "symfony/mailer": { - "version": "6.3", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -190,7 +190,7 @@ ] }, "symfony/maker-bundle": { - "version": "1.48", + "version": "1.52", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -199,7 +199,7 @@ } }, "symfony/messenger": { - "version": "6.3", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -211,7 +211,7 @@ ] }, "symfony/monolog-bundle": { - "version": "3.8", + "version": "3.10", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -223,12 +223,12 @@ ] }, "symfony/notifier": { - "version": "6.2", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", "version": "5.0", - "ref": "c31585e252b32fe0e1f30b1f256af553f4a06eb9" + "ref": "178877daf79d2dbd62129dd03612cb1a2cb407cc" }, "files": [ "config/packages/notifier.yaml" @@ -244,12 +244,12 @@ } }, "symfony/phpunit-bridge": { - "version": "6.3", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", - "version": "5.3", - "ref": "819d3d2ffa4590eba0b8f4f3e5e89415ee4e45c3" + "version": "6.3", + "ref": "1f5830c331065b6e4c9d5fa2105e322d29fcd573" }, "files": [ ".env.test", @@ -259,7 +259,7 @@ ] }, "symfony/routing": { - "version": "6.2", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -272,24 +272,25 @@ ] }, "symfony/security-bundle": { - "version": "6.2", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", - "version": "6.0", - "ref": "8a5b112826f7d3d5b07027f93786ae11a1c7de48" + "version": "6.4", + "ref": "2ae08430db28c8eb4476605894296c82a642028f" }, "files": [ - "config/packages/security.yaml" + "config/packages/security.yaml", + "config/routes/security.yaml" ] }, "symfony/translation": { - "version": "6.2", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", - "version": "5.3", - "ref": "da64f5a2b6d96f5dc24914517c0350a5f91dee43" + "version": "6.3", + "ref": "64fe617084223633e1dedf9112935d8c95410d3e" }, "files": [ "config/packages/translation.yaml", @@ -297,7 +298,7 @@ ] }, "symfony/twig-bundle": { - "version": "6.3", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -310,7 +311,7 @@ ] }, "symfony/validator": { - "version": "6.2", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -322,7 +323,7 @@ ] }, "symfony/web-profiler-bundle": { - "version": "6.2", + "version": "6.4", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", @@ -335,12 +336,12 @@ ] }, "symfony/webpack-encore-bundle": { - "version": "2.0", + "version": "2.1", "recipe": { "repo": "github.com/symfony/recipes", "branch": "main", "version": "2.0", - "ref": "13ebe04e25085e2ff0bcb0f9218b561d8b5089f3" + "ref": "082d754b3bd54b3fc669f278f1eea955cfd23cf5" }, "files": [ "assets/app.js", @@ -351,9 +352,9 @@ ] }, "symfonycasts/verify-email-bundle": { - "version": "v1.12.0" + "version": "v1.15.0" }, "twig/extra-bundle": { - "version": "v3.4.0" + "version": "v3.8.0" } }