From 10796f8916abb6536e81cc7f9c02f4caca1a42f5 Mon Sep 17 00:00:00 2001 From: Boy132 Date: Tue, 11 Jun 2024 21:01:14 +0200 Subject: [PATCH] Dedicated MariaDB driver (#365) * dedicated tests for mariadb * fix migrations * update database config * update database setup command --- .github/workflows/ci.yaml | 74 ++++++++++++- .../Environment/DatabaseSettingsCommand.php | 104 +++++++++++++----- config/database.php | 34 ++++-- ...5_28_135717_create_activity_logs_table.php | 2 +- 4 files changed, 177 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b02b9c3c5..43a644a99 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,7 +16,7 @@ jobs: fail-fast: false matrix: php: [8.2, 8.3] - database: ["mariadb:10.3", "mysql:8"] + database: ["mysql:8"] services: database: image: ${{ matrix.database }} @@ -81,6 +81,78 @@ jobs: DB_PORT: ${{ job.services.database.ports[3306] }} DB_USERNAME: root + mariadb: + name: MariaDB + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: [8.2, 8.3] + database: ["mariadb:10.3", "mariadb:10.11", "mariadb:11.4"] + services: + database: + image: ${{ matrix.database }} + env: + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_DATABASE: testing + ports: + - 3306 + options: --health-cmd="mariadb-admin ping || mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + env: + APP_ENV: testing + APP_DEBUG: "false" + APP_KEY: ThisIsARandomStringForTests12345 + APP_TIMEZONE: UTC + APP_URL: http://localhost/ + APP_ENVIRONMENT_ONLY: "true" + CACHE_DRIVER: array + MAIL_MAILER: array + SESSION_DRIVER: array + QUEUE_CONNECTION: sync + DB_CONNECTION: mariadb + DB_HOST: 127.0.0.1 + DB_DATABASE: testing + DB_USERNAME: root + steps: + - name: Code Checkout + uses: actions/checkout@v4 + + - name: Get cache directory + id: composer-cache + run: | + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Cache + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer-${{ matrix.php }}- + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip + tools: composer:v2 + coverage: none + + - name: Install dependencies + run: composer install --no-interaction --no-suggest --prefer-dist + + - name: Unit tests + run: vendor/bin/phpunit tests/Unit + env: + DB_HOST: UNIT_NO_DB + SKIP_MIGRATIONS: true + + - name: Integration tests + run: vendor/bin/phpunit tests/Integration + env: + DB_PORT: ${{ job.services.database.ports[3306] }} + DB_USERNAME: root + sqlite: name: SQLite runs-on: ubuntu-latest diff --git a/app/Console/Commands/Environment/DatabaseSettingsCommand.php b/app/Console/Commands/Environment/DatabaseSettingsCommand.php index bc71a3419..f05f9bbc4 100644 --- a/app/Console/Commands/Environment/DatabaseSettingsCommand.php +++ b/app/Console/Commands/Environment/DatabaseSettingsCommand.php @@ -13,6 +13,7 @@ class DatabaseSettingsCommand extends Command public const DATABASE_DRIVERS = [ 'sqlite' => 'SQLite (recommended)', + 'mariadb' => 'MariaDB', 'mysql' => 'MySQL', ]; @@ -21,10 +22,10 @@ class DatabaseSettingsCommand extends Command protected $signature = 'p:environment:database {--driver= : The database driver backend to use.} {--database= : The database to use.} - {--host= : The connection address for the MySQL server.} - {--port= : The connection port for the MySQL server.} - {--username= : Username to use when connecting to the MySQL server.} - {--password= : Password to use for the MySQL database.}'; + {--host= : The connection address for the MySQL/ MariaDB server.} + {--port= : The connection port for the MySQL/ MariaDB server.} + {--username= : Username to use when connecting to the MySQL/ MariaDB server.} + {--password= : Password to use for the MySQL/ MariaDB database.}'; protected array $variables = []; @@ -82,7 +83,20 @@ class DatabaseSettingsCommand extends Command } try { - $this->testMySQLConnection(); + // Test connection + config()->set('database.connections._panel_command_test', [ + 'driver' => 'mysql', + 'host' => $this->variables['DB_HOST'], + 'port' => $this->variables['DB_PORT'], + 'database' => $this->variables['DB_DATABASE'], + 'username' => $this->variables['DB_USERNAME'], + 'password' => $this->variables['DB_PASSWORD'], + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'strict' => true, + ]); + + $this->database->connection('_panel_command_test')->getPdo(); } catch (\PDOException $exception) { $this->output->error(sprintf('Unable to connect to the MySQL server using the provided credentials. The error returned was "%s".', $exception->getMessage())); $this->output->error(__('commands.database_settings.DB_error_2')); @@ -93,6 +107,66 @@ class DatabaseSettingsCommand extends Command return $this->handle(); } + return 1; + } + } elseif ($this->variables['DB_CONNECTION'] === 'mariadb') { + $this->output->note(__('commands.database_settings.DB_HOST_note')); + $this->variables['DB_HOST'] = $this->option('host') ?? $this->ask( + 'Database Host', + config('database.connections.mariadb.host', '127.0.0.1') + ); + + $this->variables['DB_PORT'] = $this->option('port') ?? $this->ask( + 'Database Port', + config('database.connections.mariadb.port', 3306) + ); + + $this->variables['DB_DATABASE'] = $this->option('database') ?? $this->ask( + 'Database Name', + config('database.connections.mariadb.database', 'panel') + ); + + $this->output->note(__('commands.database_settings.DB_USERNAME_note')); + $this->variables['DB_USERNAME'] = $this->option('username') ?? $this->ask( + 'Database Username', + config('database.connections.mariadb.username', 'pelican') + ); + + $askForMariaDBPassword = true; + if (!empty(config('database.connections.mariadb.password')) && $this->input->isInteractive()) { + $this->variables['DB_PASSWORD'] = config('database.connections.mariadb.password'); + $askForMariaDBPassword = $this->confirm(__('commands.database_settings.DB_PASSWORD_note')); + } + + if ($askForMariaDBPassword) { + $this->variables['DB_PASSWORD'] = $this->option('password') ?? $this->secret('Database Password'); + } + + try { + // Test connection + config()->set('database.connections._panel_command_test', [ + 'driver' => 'mariadb', + 'host' => $this->variables['DB_HOST'], + 'port' => $this->variables['DB_PORT'], + 'database' => $this->variables['DB_DATABASE'], + 'username' => $this->variables['DB_USERNAME'], + 'password' => $this->variables['DB_PASSWORD'], + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'strict' => true, + ]); + + $this->database->connection('_panel_command_test')->getPdo(); + } catch (\PDOException $exception) { + $this->output->error(sprintf('Unable to connect to the MariaDB server using the provided credentials. The error returned was "%s".', $exception->getMessage())); + $this->output->error(__('commands.database_settings.DB_error_2')); + + if ($this->confirm(__('commands.database_settings.go_back'))) { + $this->database->disconnect('_panel_command_test'); + + return $this->handle(); + } + return 1; } } elseif ($this->variables['DB_CONNECTION'] === 'sqlite') { @@ -108,24 +182,4 @@ class DatabaseSettingsCommand extends Command return 0; } - - /** - * Test that we can connect to the provided MySQL instance and perform a selection. - */ - private function testMySQLConnection() - { - config()->set('database.connections._panel_command_test', [ - 'driver' => 'mysql', - 'host' => $this->variables['DB_HOST'], - 'port' => $this->variables['DB_PORT'], - 'database' => $this->variables['DB_DATABASE'], - 'username' => $this->variables['DB_USERNAME'], - 'password' => $this->variables['DB_PASSWORD'], - 'charset' => 'utf8mb4', - 'collation' => 'utf8mb4_unicode_ci', - 'strict' => true, - ]); - - $this->database->connection('_panel_command_test')->getPdo(); - } } diff --git a/config/database.php b/config/database.php index 79f581bf9..016d1a926 100644 --- a/config/database.php +++ b/config/database.php @@ -1,7 +1,5 @@ env('DB_CONNECTION', 'sqlite'), @@ -17,25 +15,41 @@ return [ 'mysql' => [ 'driver' => 'mysql', - 'url' => env('DB_URL', env('DATABASE_URL')), + 'url' => env('DB_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'panel'), 'username' => env('DB_USERNAME', 'pelican'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), - 'charset' => 'utf8mb4', - 'collation' => 'utf8mb4_unicode_ci', + 'charset' => env('DB_CHARSET', 'utf8mb4'), + 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), 'prefix' => env('DB_PREFIX', ''), 'prefix_indexes' => true, 'strict' => env('DB_STRICT_MODE', false), - 'timezone' => env('DB_TIMEZONE', Time::getMySQLTimezoneOffset(env('APP_TIMEZONE', 'UTC'))), - 'sslmode' => env('DB_SSLMODE', 'prefer'), + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'mariadb' => [ + 'driver' => 'mariadb', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'panel'), + 'username' => env('DB_USERNAME', 'pelican'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => env('DB_CHARSET', 'utf8mb4'), + 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), + 'prefix' => env('DB_PREFIX', ''), + 'prefix_indexes' => true, + 'strict' => env('DB_STRICT_MODE', false), + 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), - PDO::MYSQL_ATTR_SSL_CERT => env('MYSQL_ATTR_SSL_CERT'), - PDO::MYSQL_ATTR_SSL_KEY => env('MYSQL_ATTR_SSL_KEY'), - PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('MYSQL_ATTR_SSL_VERIFY_SERVER_CERT', true), ]) : [], ], ], diff --git a/database/migrations/2022_05_28_135717_create_activity_logs_table.php b/database/migrations/2022_05_28_135717_create_activity_logs_table.php index 066b2a85c..186125aa3 100644 --- a/database/migrations/2022_05_28_135717_create_activity_logs_table.php +++ b/database/migrations/2022_05_28_135717_create_activity_logs_table.php @@ -13,7 +13,7 @@ return new class extends Migration { Schema::create('activity_logs', function (Blueprint $table) { $table->id(); - $table->uuid('batch')->nullable(); + $table->char('batch', 36)->nullable(); $table->string('event')->index(); $table->string('ip'); $table->text('description')->nullable();