From d4a99011e602cde65e708b67046d4c4cb13749b6 Mon Sep 17 00:00:00 2001 From: Guilherme Saade Date: Thu, 16 Feb 2023 13:21:06 -0300 Subject: [PATCH] [3.x] L10 compatibility (#1065) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump dependencies for Laravel 10 * Update GitHub Actions for Laravel 10 * ci: do not test L10 using PHP 7.3 * drop < L9 support * use `dispatch_sync` instead of `dispatch_now` * migrate phpunit configuration * Update ci.yml * drop laravel < 9 support * misc L10 fixes, new docker image * specify odbc version * wip * properly list php versions as strings * minor changes * Add `getValue($queryGrammar)` to raw query * Clean up `isVersion8` code * rewrite hasFailed assertion * phpunit schema update * Upgrade `doctrine/dbal` --------- Co-authored-by: Samuel Štancl Co-authored-by: Samuel Štancl Co-authored-by: lukinovec --- .github/workflows/ci.yml | 16 ++--- Dockerfile | 68 ++++++++----------- composer.json | 28 +++++--- docker-compose-m1.override.yml | 7 ++ phpunit.xml | 67 ++++++++---------- .../QueueTenancyBootstrapper.php | 11 ++- src/Database/Models/ImpersonationToken.php | 4 +- ...rmissionControlledMySQLDatabaseManager.php | 3 +- .../PostgreSQLSchemaManager.php | 6 +- test | 1 + tests/BootstrapperTest.php | 4 -- tests/EventListenerTest.php | 7 +- tests/Features/ViteBundlerTest.php | 4 -- tests/QueueTest.php | 4 -- tests/TenantDatabaseManagerTest.php | 6 +- 15 files changed, 108 insertions(+), 128 deletions(-) create mode 100644 docker-compose-m1.override.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed8ff9ac..0272d86c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,9 +5,9 @@ env: on: push: - branches: [ 3.x, 2.x ] + branches: [ 3.x ] pull_request: - branches: [ 3.x, 2.x ] + branches: [ 3.x ] jobs: tests: @@ -15,17 +15,17 @@ jobs: strategy: matrix: - php: ["7.3", "8.0"] - laravel: ["^6.0", "^8.0", "^9.0"] - exclude: - - laravel: "^9.0" - php: "7.3" + include: + - laravel: 9 + php: "8.0" + - laravel: 10 + php: "8.1" steps: - uses: actions/checkout@v2 - name: Start docker containers run: PHP_VERSION=${{ matrix.php }} docker-compose up -d - name: Install dependencies - run: docker-compose exec -T test composer require --no-interaction "laravel/framework:${{ matrix.laravel }}" + run: docker-compose exec -T test composer require --no-interaction "laravel/framework:^${{ matrix.laravel }}.0" - name: Run tests run: ./test diff --git a/Dockerfile b/Dockerfile index 36f52d6a..6a66bde2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,50 +1,42 @@ -ARG PHP_VERSION=7.4 -ARG PHP_TARGET=php:${PHP_VERSION}-cli +# add amd64 platform to support Mac M1 +FROM --platform=linux/amd64 shivammathur/node:latest-amd64 -FROM ${PHP_TARGET} - -ARG COMPOSER_TARGET=2.0.3 +ARG PHP_VERSION=8.1 WORKDIR /var/www/html -LABEL org.opencontainers.image.source=https://github.com/stancl/tenancy \ - org.opencontainers.image.vendor="Samuel Štancl" \ - org.opencontainers.image.licenses="MIT" \ - org.opencontainers.image.title="PHP ${PHP_VERSION} with modules for laravel support" \ - org.opencontainers.image.description="PHP ${PHP_VERSION} with a set of php/os packages suitable for running Laravel apps" - # our default timezone and langauge ENV TZ=Europe/London ENV LANG=en_GB.UTF-8 -# Note: we only install reliable/core 1st-party php extensions here. -# If your app needs custom ones install them in the apps own -# Dockerfile _and pin the versions_! Eg: -# RUN pecl install memcached-2.2.0 && docker-php-ext-enable memcached +# install MYSSQL ODBC Driver +RUN apt-get update \ + && apt-get install -y gnupg2 \ + && curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - \ + && curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list \ + && apt-get update \ + && ACCEPT_EULA=Y apt-get install -y unixodbc-dev=2.3.7 unixodbc=2.3.7 odbcinst1debian2=2.3.7 odbcinst=2.3.7 msodbcsql17 + +# set PHP version +RUN update-alternatives --set php /usr/bin/php$PHP_VERSION \ + && update-alternatives --set phar /usr/bin/phar$PHP_VERSION \ + && update-alternatives --set phar.phar /usr/bin/phar.phar$PHP_VERSION \ + && update-alternatives --set phpize /usr/bin/phpize$PHP_VERSION \ + && update-alternatives --set php-config /usr/bin/php-config$PHP_VERSION + +RUN apt-get update \ + && apt-get install -y --no-install-recommends libhiredis0.14 libjemalloc2 liblua5.1-0 lua-bitop lua-cjson redis redis-server redis-tools + +RUN pecl install redis-5.3.7 sqlsrv pdo_sqlsrv pcov \ + && printf "; priority=20\nextension=redis.so\n" > /etc/php/$PHP_VERSION/mods-available/redis.ini \ + && printf "; priority=20\nextension=sqlsrv.so\n" > /etc/php/$PHP_VERSION/mods-available/sqlsrv.ini \ + && printf "; priority=30\nextension=pdo_sqlsrv.so\n" > /etc/php/$PHP_VERSION/mods-available/pdo_sqlsrv.ini \ + && printf "; priority=40\nextension=pcov.so\n" > /etc/php/$PHP_VERSION/mods-available/pcov.ini \ + && phpenmod -v $PHP_VERSION redis sqlsrv pdo_sqlsrv pcov + +# install composer +COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -# install some OS packages we need -RUN apt-get update -RUN apt-get install -y --no-install-recommends libfreetype6-dev libjpeg62-turbo-dev libpng-dev libgmp-dev libldap2-dev netcat curl sqlite3 libsqlite3-dev libpq-dev libzip-dev unzip vim-tiny gosu git - # install php extensions -RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ - # && if [ "${PHP_VERSION}" = "7.4" ]; then docker-php-ext-configure gd --with-freetype --with-jpeg; else docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/; fi \ - && docker-php-ext-install -j$(nproc) gd pdo pdo_mysql pdo_pgsql pdo_sqlite pgsql zip gmp bcmath pcntl ldap sysvmsg exif \ - # install the redis php extension - && pecl install redis-5.3.7 \ - && docker-php-ext-enable redis \ - # install the pcov extention - && pecl install pcov \ - && docker-php-ext-enable pcov \ - && echo "pcov.enabled = 1" > /usr/local/etc/php/conf.d/pcov.ini -# clear the apt cache -RUN rm -rf /var/lib/apt/lists/* \ - && rm -rf /var/lib/apt/lists/* \ - # install composer - && curl -o /tmp/composer-setup.php https://getcomposer.org/installer \ - && curl -o /tmp/composer-setup.sig https://composer.github.io/installer.sig \ - && php -r "if (hash('SHA384', file_get_contents('/tmp/composer-setup.php')) !== trim(file_get_contents('/tmp/composer-setup.sig'))) { unlink('/tmp/composer-setup.php'); echo 'Invalid installer' . PHP_EOL; exit(1); }" \ - && php /tmp/composer-setup.php --version=${COMPOSER_TARGET} --no-ansi --install-dir=/usr/local/bin --filename=composer --snapshot \ - && rm -f /tmp/composer-setup.* # set the system timezone RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \ && echo $TZ > /etc/timezone diff --git a/composer.json b/composer.json index 88bfea29..66dceafe 100644 --- a/composer.json +++ b/composer.json @@ -10,19 +10,20 @@ } ], "require": { + "php": "^8.0", "ext-json": "*", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0", - "facade/ignition-contracts": "^1.0", - "ramsey/uuid": "^3.7|^4.0", - "stancl/jobpipeline": "^1.0", - "stancl/virtualcolumn": "^1.0" + "illuminate/support": "^9.0|^10.0", + "facade/ignition-contracts": "^1.0.2", + "ramsey/uuid": "^4.7.3", + "stancl/jobpipeline": "^1.6.2", + "stancl/virtualcolumn": "^1.3.1" }, "require-dev": { - "laravel/framework": "^6.0|^7.0|^8.0|^9.0", - "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0", - "league/flysystem-aws-s3-v3": "^1.0|^3.0", - "doctrine/dbal": "^2.10", - "spatie/valuestore": "^1.2.5" + "laravel/framework": "^9.0|^10.0", + "orchestra/testbench": "^7.0|^8.0", + "league/flysystem-aws-s3-v3": "^3.12.2", + "doctrine/dbal": "^3.6.0", + "spatie/valuestore": "^1.3.2" }, "autoload": { "psr-4": { @@ -49,5 +50,10 @@ } }, "minimum-stability": "dev", - "prefer-stable": true + "prefer-stable": true, + "config": { + "allow-plugins": { + "pestphp/pest-plugin": true + } + } } diff --git a/docker-compose-m1.override.yml b/docker-compose-m1.override.yml new file mode 100644 index 00000000..32e163e6 --- /dev/null +++ b/docker-compose-m1.override.yml @@ -0,0 +1,7 @@ +services: + mysql: + platform: linux/amd64 + mysql2: + platform: linux/amd64 + mssql: + image: mcr.microsoft.com/azure-sql-edge diff --git a/phpunit.xml b/phpunit.xml index 934fd431..19989e03 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,39 +1,32 @@ - - - - ./tests - - - - - ./src - - ./src/routes.php - ./src/Vite.php - - - - - - - - - - - - - - - - - + + + + ./src + + + ./src/routes.php + ./src/Vite.php + + + + + + + + + ./tests + + + + + + + + + + + + + diff --git a/src/Bootstrappers/QueueTenancyBootstrapper.php b/src/Bootstrappers/QueueTenancyBootstrapper.php index 790e1344..f747faea 100644 --- a/src/Bootstrappers/QueueTenancyBootstrapper.php +++ b/src/Bootstrappers/QueueTenancyBootstrapper.php @@ -63,14 +63,11 @@ class QueueTenancyBootstrapper implements TenancyBootstrapper static::initializeTenancyForQueue($event->job->payload()['tenant_id'] ?? null); }); - if (version_compare(app()->version(), '8.64', '>=')) { - // JobRetryRequested only exists since Laravel 8.64 - $dispatcher->listen(JobRetryRequested::class, function ($event) use (&$previousTenant) { - $previousTenant = tenant(); + $dispatcher->listen(JobRetryRequested::class, function ($event) use (&$previousTenant) { + $previousTenant = tenant(); - static::initializeTenancyForQueue($event->payload()['tenant_id'] ?? null); - }); - } + static::initializeTenancyForQueue($event->payload()['tenant_id'] ?? null); + }); // If we're running tests, we make sure to clean up after any artisan('queue:work') calls $revertToPreviousState = function ($event) use (&$previousTenant, $runningTests) { diff --git a/src/Database/Models/ImpersonationToken.php b/src/Database/Models/ImpersonationToken.php index 4aa63252..0de48060 100644 --- a/src/Database/Models/ImpersonationToken.php +++ b/src/Database/Models/ImpersonationToken.php @@ -26,8 +26,8 @@ class ImpersonationToken extends Model protected $primaryKey = 'token'; public $incrementing = false; protected $table = 'tenant_user_impersonation_tokens'; - protected $dates = [ - 'created_at', + protected $casts = [ + 'created_at' => 'datetime', ]; public static function boot() diff --git a/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php b/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php index 918601a8..df23ed1f 100644 --- a/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php +++ b/src/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php @@ -40,7 +40,8 @@ class PermissionControlledMySQLDatabaseManager extends MySQLDatabaseManager impl protected function isVersion8(): bool { - $version = $this->database()->select($this->database()->raw('select version()'))[0]->{'version()'}; + $versionSelect = $this->database()->raw('select version()')->getValue($this->database()->getQueryGrammar()); + $version = $this->database()->select($versionSelect)[0]->{'version()'}; return version_compare($version, '8.0.0') >= 0; } diff --git a/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php b/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php index 55f049d0..53607bdb 100644 --- a/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php +++ b/src/TenantDatabaseManagers/PostgreSQLSchemaManager.php @@ -46,11 +46,7 @@ class PostgreSQLSchemaManager implements TenantDatabaseManager public function makeConnectionConfig(array $baseConfig, string $databaseName): array { - if (version_compare(app()->version(), '9.0', '>=')) { - $baseConfig['search_path'] = $databaseName; - } else { - $baseConfig['schema'] = $databaseName; - } + $baseConfig['search_path'] = $databaseName; return $baseConfig; } diff --git a/test b/test index 49535a7a..e064bbfe 100755 --- a/test +++ b/test @@ -1,3 +1,4 @@ #!/bin/bash +cat vendor/laravel/framework/src/Illuminate/Foundation/Application.php | grep 'const VERSION' docker-compose exec -T test vendor/bin/phpunit "$@" diff --git a/tests/BootstrapperTest.php b/tests/BootstrapperTest.php index 588fadd8..6f9cc493 100644 --- a/tests/BootstrapperTest.php +++ b/tests/BootstrapperTest.php @@ -207,10 +207,6 @@ class BootstrapperTest extends TestCase $disk = Storage::disk($disk); $adapter = $disk->getAdapter(); - if (! Str::startsWith(app()->version(), '9.')) { - return $adapter->getPathPrefix(); - } - $prefixer = (new ReflectionObject($adapter))->getProperty('prefixer'); $prefixer->setAccessible(true); diff --git a/tests/EventListenerTest.php b/tests/EventListenerTest.php index 4a45205c..759e330c 100644 --- a/tests/EventListenerTest.php +++ b/tests/EventListenerTest.php @@ -94,7 +94,7 @@ class EventListenerTest extends TestCase }); $tenant = Tenant::create(); - dispatch_now(new CreateDatabase($tenant)); + dispatch_sync(new CreateDatabase($tenant)); $this->assertFalse($tenant->database()->manager()->databaseExists( $tenant->database()->getName() @@ -192,12 +192,13 @@ class EventListenerTest extends TestCase })->toListener() ); - Tenant::create([ + $tenant = Tenant::create([ 'tenancy_create_database' => false, 'tenancy_db_name' => 'already_created', ]); - $this->assertFalse($this->hasFailed()); + // assert test didn't fail + $this->assertTrue($tenant->exists()); } } diff --git a/tests/Features/ViteBundlerTest.php b/tests/Features/ViteBundlerTest.php index b544bcac..23cf164d 100644 --- a/tests/Features/ViteBundlerTest.php +++ b/tests/Features/ViteBundlerTest.php @@ -12,10 +12,6 @@ class ViteBundlerTest extends TestCase /** @test */ public function the_vite_helper_uses_our_custom_class() { - if (version_compare(app()->version(), '9.0', '<')) { - $this->markTestSkipped('Vite is only used in Laravel 9+'); - } - $vite = app(\Illuminate\Foundation\Vite::class); $this->assertInstanceOf(\Illuminate\Foundation\Vite::class, $vite); diff --git a/tests/QueueTest.php b/tests/QueueTest.php index a3df9cd7..373e54a4 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -197,10 +197,6 @@ class QueueTest extends TestCase */ public function tenancy_is_initialized_when_retrying_jobs(bool $shouldEndTenancy) { - if (! Str::startsWith(app()->version(), '8')) { - $this->markTestSkipped('queue:retry tenancy is only supported in Laravel 8'); - } - $this->withFailedJobs(); $this->withTenantDatabases(); diff --git a/tests/TenantDatabaseManagerTest.php b/tests/TenantDatabaseManagerTest.php index 3d45d96f..6051ee12 100644 --- a/tests/TenantDatabaseManagerTest.php +++ b/tests/TenantDatabaseManagerTest.php @@ -95,7 +95,7 @@ class TenantDatabaseManagerTest extends TestCase $this->assertTrue($postgresManager->databaseExists($database)); } - public function database_manager_provider() + public static function database_manager_provider() { return [ ['mysql', MySQLDatabaseManager::class], @@ -194,9 +194,7 @@ class TenantDatabaseManagerTest extends TestCase ]); tenancy()->initialize($tenant); - $schemaConfig = version_compare(app()->version(), '9.0', '>=') ? - config('database.connections.' . config('database.default') . '.search_path') : - config('database.connections.' . config('database.default') . '.schema'); + $schemaConfig = config('database.connections.' . config('database.default') . '.search_path'); $this->assertSame($tenant->database()->getName(), $schemaConfig); $this->assertSame($originalDatabaseName, config(['database.connections.pgsql.database']));