diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 314d6e4c..744bb91e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,104 +15,17 @@ jobs: strategy: matrix: - laravel: ['^9.0'] + include: + - laravel: 9 + php: "8.0" + - laravel: 10 + php: "8.1" steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install Composer dependencies - run: | - composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update - composer update --prefer-dist --no-interaction - - name: Run tests - run: ./vendor/bin/pest - env: - DB_PASSWORD: password - DB_USERNAME: root - DB_DATABASE: main - TENANCY_TEST_MYSQL_HOST: mysql - TENANCY_TEST_PGSQL_HOST: postgres - TENANCY_TEST_REDIS_HOST: redis - TENANCY_TEST_SQLSRV_HOST: mssql - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 - with: - token: 24382d15-84e7-4a55-bea4-c4df96a24a9b - - services: - postgres: - image: postgres:latest - env: - POSTGRES_PASSWORD: password - POSTGRES_USER: root - POSTGRES_DB: main - ports: - - 5432/tcp - options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 - - mysql: - image: mysql:5.7 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: false - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: main - ports: - - 3306/tcp - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - - mysql2: - image: mysql:5.7 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: false - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: main - ports: - - 3306/tcp - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - - mssql: - image: mcr.microsoft.com/mssql/server:2019-latest - ports: - - 1433/tcp - env: - ACCEPT_EULA: Y - SA_PASSWORD: P@ssword - options: --health-cmd "echo quit | /opt/mssql-tools/bin/sqlcmd -S 127.0.0.1 -l 1 -U sa -P P@ssword" - - redis: - image: redis - ports: - - 6379/tcp - options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 - - php-cs-fixer: - name: Code style (php-cs-fixer) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install php-cs-fixer - run: composer global require friendsofphp/php-cs-fixer - - name: Run php-cs-fixer - run: $HOME/.composer/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php - - name: Commit changes from php-cs-fixer - uses: EndBug/add-and-commit@v5 - with: - author_name: "PHP CS Fixer" - author_email: "phpcsfixer@example.com" - message: Fix code style (php-cs-fixer) - - phpstan: - name: Static analysis (PHPStan) - runs-on: ubuntu-latest - steps: - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.2' - - uses: actions/checkout@v2 - - name: Install composer dependencies - run: composer install - - name: Run phpstan - run: vendor/bin/phpstan analyse + - 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 }}.0" + - name: Run tests + run: ./test diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0095be7e..e2e76c8c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,16 +24,4 @@ To fix this, simply delete the database memory by shutting down containers and s Run `composer docker-m1` to symlink `docker-compose-m1.override.yml` to `docker-compose.override.yml`. This will reconfigure a few services in the docker compose config to be compatible with M1. -### Coverage reports - -To run tests and generate coverage reports, use `composer test-full`. - -To view the coverage reports in your browser, use `composer coverage` (works on macOS; on other operating systems you can manually open `coverage/phpunit/html/index.html` in your browser). - -### Rebuilding containers - -If you need to rebuild the container for any reason (e.g. a change in `Dockerfile`), you can use `composer docker-rebuild`. - -## PHPStan - -Use `composer phpstan` to run our phpstan suite. +to `docker-compose.override.yml` to make `docker-compose up -d` work on M1. diff --git a/assets/config.php b/assets/config.php index bbfa9974..7fc6c928 100644 --- a/assets/config.php +++ b/assets/config.php @@ -258,7 +258,7 @@ return [ ], /** - * Redis tenancy config. Used by RedisTenancyBoostrapper. + * Redis tenancy config. Used by RedisTenancyBootstrapper. * * Note: You need phpredis to use Redis tenancy. * @@ -286,6 +286,7 @@ return [ // Stancl\Tenancy\Features\TelescopeTags::class, // Stancl\Tenancy\Features\TenantConfig::class, // https://tenancyforlaravel.com/docs/v3/features/tenant-config // Stancl\Tenancy\Features\CrossDomainRedirect::class, // https://tenancyforlaravel.com/docs/v3/features/cross-domain-redirect + // Stancl\Tenancy\Features\ViteBundler::class, ], /** diff --git a/src/Database/Models/ImpersonationToken.php b/src/Database/Models/ImpersonationToken.php index 05d17ad4..3d7b595b 100644 --- a/src/Database/Models/ImpersonationToken.php +++ b/src/Database/Models/ImpersonationToken.php @@ -33,9 +33,8 @@ class ImpersonationToken extends Model public $incrementing = false; protected $table = 'tenant_user_impersonation_tokens'; - - protected $dates = [ - 'created_at', + protected $casts = [ + 'created_at' => 'datetime', ]; public static function booted(): void diff --git a/src/Database/Models/Tenant.php b/src/Database/Models/Tenant.php index 37c2af2d..c3574942 100644 --- a/src/Database/Models/Tenant.php +++ b/src/Database/Models/Tenant.php @@ -32,6 +32,8 @@ class Tenant extends Model implements Contracts\Tenant Concerns\InitializationHelpers, Concerns\InvalidatesResolverCache; + protected static $modelsShouldPreventAccessingMissingAttributes = false; + protected $table = 'tenants'; protected $primaryKey = 'id'; protected $guarded = []; diff --git a/src/Database/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php b/src/Database/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php index f7e7440e..80dc6647 100644 --- a/src/Database/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php +++ b/src/Database/TenantDatabaseManagers/PermissionControlledMySQLDatabaseManager.php @@ -41,7 +41,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/Features/ViteBundler.php b/src/Features/ViteBundler.php new file mode 100644 index 00000000..e3fee2fa --- /dev/null +++ b/src/Features/ViteBundler.php @@ -0,0 +1,26 @@ +app = $app; + } + + public function bootstrap(Tenancy $tenancy): void + { + $this->app->singleton(\Illuminate\Foundation\Vite::class, Vite::class); + } +} diff --git a/src/TenancyServiceProvider.php b/src/TenancyServiceProvider.php index 23fb6473..bde37055 100644 --- a/src/TenancyServiceProvider.php +++ b/src/TenancyServiceProvider.php @@ -62,6 +62,7 @@ class TenancyServiceProvider extends ServiceProvider $this->app->singleton(Commands\Rollback::class, function ($app) { return new Commands\Rollback($app['migrator']); }); + $this->app->singleton(Commands\Seed::class, function ($app) { return new Commands\Seed($app['db']); }); diff --git a/src/Vite.php b/src/Vite.php new file mode 100644 index 00000000..1887361a --- /dev/null +++ b/src/Vite.php @@ -0,0 +1,20 @@ +assertFalse($tenant->database()->manager()->databaseExists( $tenant->database()->getName() @@ -171,12 +171,13 @@ test('database is not migrated if creation is disabled', function () { })->toListener() ); - Tenant::create([ + $tenant = Tenant::create([ 'tenancy_create_database' => false, 'tenancy_db_name' => 'already_created', ]); - expect(pest()->hasFailed())->toBeFalse(); + // assert test didn't fail + $this->assertTrue($tenant->exists()); }); class FooListener extends QueueableListener diff --git a/tests/Features/ViteBundlerTest.php b/tests/Features/ViteBundlerTest.php new file mode 100644 index 00000000..23cf164d --- /dev/null +++ b/tests/Features/ViteBundlerTest.php @@ -0,0 +1,34 @@ +assertInstanceOf(\Illuminate\Foundation\Vite::class, $vite); + $this->assertNotInstanceOf(StanclVite::class, $vite); + + config([ + 'tenancy.features' => [ViteBundler::class], + ]); + + $tenant = Tenant::create(); + + tenancy()->initialize($tenant); + + app()->forgetInstance(\Illuminate\Foundation\Vite::class); + + $vite = app(\Illuminate\Foundation\Vite::class); + + $this->assertInstanceOf(StanclVite::class, $vite); + } +} diff --git a/tests/TenantDatabaseManagerTest.php b/tests/TenantDatabaseManagerTest.php index 5d9a15d6..c776d7a1 100644 --- a/tests/TenantDatabaseManagerTest.php +++ b/tests/TenantDatabaseManagerTest.php @@ -302,7 +302,7 @@ test('database credentials can be provided to PermissionControlledMySQLDatabaseM $mysql2DB->statement("CREATE USER `{$username}`@`%` IDENTIFIED BY '{$password}';"); $mysql2DB->statement("GRANT ALL PRIVILEGES ON *.* TO `{$username}`@`%` identified by '{$password}' WITH GRANT OPTION;"); $mysql2DB->statement("FLUSH PRIVILEGES;"); - + DB::purge('mysql2'); // forget the mysql2 connection so that it uses the new credentials the next time config(['database.connections.mysql2.username' => $username]); @@ -347,7 +347,7 @@ test('tenant database can be created by using the username and password from ten $mysqlDB->statement("CREATE USER `{$username}`@`%` IDENTIFIED BY '{$password}';"); $mysqlDB->statement("GRANT ALL PRIVILEGES ON *.* TO `{$username}`@`%` identified by '{$password}' WITH GRANT OPTION;"); $mysqlDB->statement("FLUSH PRIVILEGES;"); - + DB::purge('mysql2'); // forget the mysql2 connection so that it uses the new credentials the next time // Remove `mysql` credentials to make sure we will be using the credentials from the tenant config