diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c5dc2df4..9ab37e216 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: CI on: push: branches: - - master + - main pull_request: jobs: @@ -12,9 +12,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - - run: docker-compose pull + - run: docker compose pull - name: ๐ŸŽป Install dependencies run: make composer-install @@ -35,14 +35,14 @@ jobs: sleep 2 done - - name: ๐Ÿงช Wait for the elasticsearch to get up + - name: ๐Ÿงช Wait for the Elasticsearch to get up run: | while ! make ping-elasticsearch &>/dev/null; do echo "Waiting for elasticsearch connection..." sleep 2 done - - name: ๐Ÿฐ Wait for the message broker to get up + - name: ๐Ÿฐ Wait for RabbitMQ to get up run: | while ! make ping-rabbitmq &>/dev/null; do echo "Waiting for RabbitMQ connection..." diff --git a/Makefile b/Makefile index a3ea006ee..aa5c306bb 100644 --- a/Makefile +++ b/Makefile @@ -1,100 +1,48 @@ current-dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) -.PHONY: build -build: deps start - -.PHONY: deps -deps: composer-install - -# ๐Ÿ˜ Composer -composer-env-file: - @if [ ! -f .env.local ]; then echo '' > .env.local; fi - -.PHONY: composer-install -composer-install: CMD=install - -.PHONY: composer-update -composer-update: CMD=update - -.PHONY: composer-require -composer-require: CMD=require -composer-require: INTERACTIVE=-ti --interactive - -.PHONY: composer-require-module -composer-require-module: CMD=require $(module) -composer-require-module: INTERACTIVE=-ti --interactive - -.PHONY: composer -composer composer-install composer-update composer-require composer-require-module: composer-env-file +composer-install: @docker run --rm $(INTERACTIVE) --volume $(current-dir):/app --user $(id -u):$(id -g) \ - composer:2.3.7 $(CMD) \ + composer:2.6.4 install \ --ignore-platform-reqs \ --no-ansi -.PHONY: reload -reload: composer-env-file - @docker-compose exec php-fpm kill -USR2 1 - @docker-compose exec nginx nginx -s reload - -.PHONY: test -test: composer-env-file +test: docker exec codely-php_ddd_skeleton-mooc_backend-php ./vendor/bin/phpunit --testsuite mooc docker exec codely-php_ddd_skeleton-mooc_backend-php ./vendor/bin/phpunit --testsuite shared docker exec codely-php_ddd_skeleton-mooc_backend-php ./vendor/bin/behat -p mooc_backend --format=progress -v docker exec codely-php_ddd_skeleton-backoffice_backend-php ./vendor/bin/phpunit --testsuite backoffice -.PHONY: static-analysis -static-analysis: composer-env-file +static-analysis: docker exec codely-php_ddd_skeleton-mooc_backend-php ./vendor/bin/psalm -.PHONY: lint lint: docker exec codely-php_ddd_skeleton-mooc_backend-php ./vendor/bin/ecs check -.PHONY: run-tests -run-tests: composer-env-file - mkdir -p build/test_results/phpunit - ./vendor/bin/phpunit --exclude-group='disabled' --log-junit build/test_results/phpunit/junit.xml --testsuite backoffice - ./vendor/bin/phpunit --exclude-group='disabled' --log-junit build/test_results/phpunit/junit.xml --testsuite mooc - ./vendor/bin/phpunit --exclude-group='disabled' --log-junit build/test_results/phpunit/junit.xml --testsuite shared - ./vendor/bin/behat -p mooc_backend --format=progress -v - -# ๐Ÿณ Docker Compose -.PHONY: start -start: CMD=up --build -d - -.PHONY: stop -stop: CMD=stop +start: + @if [ ! -f .env.local ]; then echo '' > .env.local; fi + UID=${shell id -u} GID=${shell id -g} docker compose up --build -d + make clean-cache -.PHONY: destroy -destroy: CMD=down +stop: + UID=${shell id -u} GID=${shell id -g} docker compose stop -# Usage: `make doco CMD="ps --services"` -# Usage: `make doco CMD="build --parallel --pull --force-rm --no-cache"` -.PHONY: doco -doco start stop destroy: composer-env-file - UID=${shell id -u} GID=${shell id -g} docker-compose $(CMD) +destroy: + UID=${shell id -u} GID=${shell id -g} docker compose down -.PHONY: rebuild -rebuild: composer-env-file - docker-compose build --pull --force-rm --no-cache - make deps +rebuild: + docker compose build --pull --force-rm --no-cache + make install make start -.PHONY: ping-mysql ping-mysql: @docker exec codely-php_ddd_skeleton-mooc-mysql mysqladmin --user=root --password= --host "127.0.0.1" ping --silent -.PHONY: ping-elasticsearch ping-elasticsearch: @curl -I -XHEAD localhost:9200 -.PHONY: ping-rabbitmq ping-rabbitmq: @docker exec codely-php_ddd_skeleton-rabbitmq rabbitmqctl ping --silent clean-cache: @rm -rf apps/*/*/var - @docker exec codely-php_ddd_skeleton-backoffice_backend-php ./apps/backoffice/backend/bin/console cache:warmup - @docker exec codely-php_ddd_skeleton-backoffice_frontend-php ./apps/backoffice/frontend/bin/console cache:warmup @docker exec codely-php_ddd_skeleton-mooc_backend-php ./apps/mooc/backend/bin/console cache:warmup diff --git a/apps/backoffice/backend/bin/console b/apps/backoffice/backend/bin/console index ac7f81a9a..29bc8b83f 100755 --- a/apps/backoffice/backend/bin/console +++ b/apps/backoffice/backend/bin/console @@ -12,7 +12,7 @@ if (false === in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { set_time_limit(0); -require dirname(__DIR__) . '../../../vendor/autoload.php'; +require dirname(__DIR__) . '/../../../vendor/autoload.php'; if (!class_exists(Application::class)) { throw new RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.'); diff --git a/apps/backoffice/backend/public/index.php b/apps/backoffice/backend/public/index.php index 977a86d4b..56a52ea14 100644 --- a/apps/backoffice/backend/public/index.php +++ b/apps/backoffice/backend/public/index.php @@ -16,8 +16,8 @@ if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) { Request::setTrustedProxies( - explode(',', (string) $trustedProxies), - Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST + explode(',', $trustedProxies), + Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO ); } diff --git a/apps/backoffice/frontend/bin/console b/apps/backoffice/frontend/bin/console index 5e2d7ebf2..d680ab53c 100755 --- a/apps/backoffice/frontend/bin/console +++ b/apps/backoffice/frontend/bin/console @@ -12,7 +12,7 @@ if (false === in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { set_time_limit(0); -require dirname(__DIR__) . '../../../vendor/autoload.php'; +require dirname(__DIR__) . '/../../../vendor/autoload.php'; if (!class_exists(Application::class)) { throw new RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.'); diff --git a/apps/backoffice/frontend/public/index.php b/apps/backoffice/frontend/public/index.php index c18f536e7..2b5d9b2d3 100644 --- a/apps/backoffice/frontend/public/index.php +++ b/apps/backoffice/frontend/public/index.php @@ -16,8 +16,8 @@ if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) { Request::setTrustedProxies( - explode(',', (string) $trustedProxies), - Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST + explode(',', $trustedProxies), + Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO ); } diff --git a/apps/bootstrap.php b/apps/bootstrap.php index cb93ce7f7..6d66dea9d 100644 --- a/apps/bootstrap.php +++ b/apps/bootstrap.php @@ -8,20 +8,7 @@ require $rootPath . '/vendor/autoload.php'; -// Load cached env vars if the .env.local.php file exists -// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2) -if (is_array($env = @include $rootPath . '/.env.local.php')) { - foreach ($env as $k => $v) { - $_ENV[$k] ??= isset($_SERVER[$k]) && str_starts_with($k, 'HTTP_') ? $_SERVER[$k] : $v; - } -} elseif (!class_exists(Dotenv::class)) { - throw new RuntimeException( - 'Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.' - ); -} else { - // load all the .env files - (new Dotenv())->loadEnv($rootPath . '/.env'); -} +(new Dotenv())->loadEnv($rootPath . '/.env'); $_SERVER += $_ENV; $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; diff --git a/apps/mooc/backend/bin/console b/apps/mooc/backend/bin/console index c794905a3..d013ee7a8 100755 --- a/apps/mooc/backend/bin/console +++ b/apps/mooc/backend/bin/console @@ -12,7 +12,7 @@ if (false === in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { set_time_limit(0); -require dirname(__DIR__) . '../../../vendor/autoload.php'; +require dirname(__DIR__) . '/../../../vendor/autoload.php'; if (!class_exists(Application::class)) { throw new RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.'); diff --git a/apps/mooc/backend/public/index.php b/apps/mooc/backend/public/index.php index 0d1e3eae8..4269b3810 100644 --- a/apps/mooc/backend/public/index.php +++ b/apps/mooc/backend/public/index.php @@ -16,8 +16,8 @@ if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) { Request::setTrustedProxies( - explode(',', (string) $trustedProxies), - Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST + explode(',', $trustedProxies), + Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO ); } diff --git a/ecs.php b/ecs.php index 437848d5d..62c8f5208 100644 --- a/ecs.php +++ b/ecs.php @@ -132,6 +132,10 @@ __DIR__ . '/apps/backoffice/frontend/src/BackofficeFrontendKernel.php', __DIR__ . '/apps/mooc/backend/src/MoocBackendKernel.php', __DIR__ . '/src/Shared/Infrastructure/Bus/Event/InMemory/InMemorySymfonyEventBus.php', - ] + ], + __DIR__ . '/apps/backoffice/backend/var', + __DIR__ . '/apps/backoffice/frontend/var', + __DIR__ . '/apps/mooc/backend/var', + __DIR__ . '/apps/mooc/frontend/var', ]); }; diff --git a/psalm.xml b/psalm.xml index 5eea39ada..123c91c54 100644 --- a/psalm.xml +++ b/psalm.xml @@ -9,13 +9,11 @@ findUnusedCode="false" > - - - - + + diff --git a/src/Shared/Infrastructure/Bus/Event/RabbitMq/RabbitMqDomainEventsConsumer.php b/src/Shared/Infrastructure/Bus/Event/RabbitMq/RabbitMqDomainEventsConsumer.php index bf12fc093..c6afe08e1 100644 --- a/src/Shared/Infrastructure/Bus/Event/RabbitMq/RabbitMqDomainEventsConsumer.php +++ b/src/Shared/Infrastructure/Bus/Event/RabbitMq/RabbitMqDomainEventsConsumer.php @@ -7,6 +7,7 @@ use AMQPEnvelope; use AMQPQueue; use AMQPQueueException; +use CodelyTv\Shared\Domain\Bus\Event\DomainEventSubscriber; use CodelyTv\Shared\Infrastructure\Bus\Event\DomainEventJsonDeserializer; use Throwable; @@ -22,7 +23,7 @@ public function __construct( private int $maxRetries ) {} - public function consume(callable $subscriber, string $queueName): void + public function consume(callable|DomainEventSubscriber $subscriber, string $queueName): void { try { $this->connection->queue($queueName)->consume($this->consumer($subscriber)); diff --git a/src/Shared/Infrastructure/Bus/Query/InMemorySymfonyQueryBus.php b/src/Shared/Infrastructure/Bus/Query/InMemorySymfonyQueryBus.php index d01b9e105..e08643fcd 100644 --- a/src/Shared/Infrastructure/Bus/Query/InMemorySymfonyQueryBus.php +++ b/src/Shared/Infrastructure/Bus/Query/InMemorySymfonyQueryBus.php @@ -14,9 +14,9 @@ use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware; use Symfony\Component\Messenger\Stamp\HandledStamp; -final class InMemorySymfonyQueryBus implements QueryBus +final readonly class InMemorySymfonyQueryBus implements QueryBus { - private readonly MessageBus $bus; + private MessageBus $bus; public function __construct(iterable $queryHandlers) { diff --git a/tests/Shared/Infrastructure/PhpUnit/UnitTestCase.php b/tests/Shared/Infrastructure/PhpUnit/UnitTestCase.php index 54d0e3a45..27bb36193 100644 --- a/tests/Shared/Infrastructure/PhpUnit/UnitTestCase.php +++ b/tests/Shared/Infrastructure/PhpUnit/UnitTestCase.php @@ -15,6 +15,7 @@ use Mockery\Adapter\Phpunit\MockeryTestCase; use Mockery\Matcher\MatcherAbstract; use Mockery\MockInterface; +use Throwable; abstract class UnitTestCase extends MockeryTestCase { @@ -78,6 +79,7 @@ protected function assertAskResponse(Response $expected, Query $query, callable $this->assertEquals($expected, $actual); } + /** @param class-string $expectedErrorClass */ protected function assertAskThrowsException(string $expectedErrorClass, Query $query, callable $queryHandler): void { $this->expectException($expectedErrorClass);