diff --git a/.github/workflows/service_docker-build-and-publish.yml b/.github/workflows/service_docker-build-and-publish.yml index 8a03220..835211e 100644 --- a/.github/workflows/service_docker-build-and-publish.yml +++ b/.github/workflows/service_docker-build-and-publish.yml @@ -96,6 +96,8 @@ jobs: needs: setup-matrix runs-on: ubuntu-24.04 strategy: + # Une combinaison en echec ne doit pas annuler les autres, mais doit rester visible. + fail-fast: false matrix: ${{fromJson(needs.setup-matrix.outputs.php-version-map-json)}} steps: @@ -175,7 +177,6 @@ jobs: - name: Build images uses: docker/build-push-action@v6 - continue-on-error: true with: file: src/variations/${{ matrix.php_variation }}/Dockerfile cache-from: type=gha diff --git a/scripts/conf/php-versions-base-config.yml b/scripts/conf/php-versions-base-config.yml index edb787a..39e36ae 100644 --- a/scripts/conf/php-versions-base-config.yml +++ b/scripts/conf/php-versions-base-config.yml @@ -9,57 +9,43 @@ php_variations: - "8.2" php_versions: - - major: "7" - minor_versions: - - minor: "7.4" - base_os: - - name: alpine3.16 - - name: bullseye - patch_versions: - - 7.4.33 - major: "8" minor_versions: - - minor: "8.0" - base_os: - - name: alpine3.16 - - name: bullseye - patch_versions: - - 8.0.30 - minor: "8.1" base_os: - - name: alpine3.21 + - name: alpine3.22 - name: bookworm - name: trixie patch_versions: # - 8.1.28 # Pull latest from Official PHP source - minor: "8.2" base_os: - - name: alpine3.21 - - name: alpine3.22 + - name: alpine3.23 + - name: alpine3.24 - name: bookworm - name: trixie patch_versions: # - 8.2.18 # Pull latest from Official PHP source - minor: "8.3" base_os: - - name: alpine3.21 - - name: alpine3.22 + - name: alpine3.23 + - name: alpine3.24 - name: bookworm - name: trixie patch_versions: # - 8.3.6 # Pull latest from Official PHP source - minor: "8.4" base_os: - - name: alpine3.21 - - name: alpine3.22 + - name: alpine3.23 + - name: alpine3.24 - name: bookworm - name: trixie patch_versions: # - 8.4.1 # Pull latest from Official PHP source - minor: "8.5" base_os: - - name: alpine3.21 - - name: alpine3.22 + - name: alpine3.23 + - name: alpine3.24 - name: bookworm - name: trixie patch_versions: @@ -89,6 +75,12 @@ operating_systems: - name: "Alpine 3.22" version: alpine3.22 number: 3.22 + - name: "Alpine 3.23" + version: alpine3.23 + number: 3.23 + - name: "Alpine 3.24" + version: alpine3.24 + number: 3.24 - family: debian default: true versions: diff --git a/scripts/conf/sail-versions-base-config.yml b/scripts/conf/sail-versions-base-config.yml index 988813f..4fbb084 100644 --- a/scripts/conf/sail-versions-base-config.yml +++ b/scripts/conf/sail-versions-base-config.yml @@ -48,6 +48,12 @@ operating_systems: - name: "Alpine 3.22" version: alpine3.22 number: 3.22 + - name: "Alpine 3.23" + version: alpine3.23 + number: 3.23 + - name: "Alpine 3.24" + version: alpine3.24 + number: 3.24 - family: debian default: true versions: diff --git a/src/common/etc/entrypoint.d/lib/laravel/test-db-connection.php b/src/common/etc/entrypoint.d/lib/laravel/test-db-connection.php new file mode 100644 index 0000000..e4817fd --- /dev/null +++ b/src/common/etc/entrypoint.d/lib/laravel/test-db-connection.php @@ -0,0 +1,160 @@ + 5) { + fwrite(STDERR, "Usage: php test-db-connection.php /path/to/app/base/dir [migration_mode] [migration_isolation] [database_connection]\n"); + exit(1); +} + +$appBaseDir = $argv[1]; +$migrationMode = $argc >= 3 ? $argv[2] : 'default'; +$migrationIsolation = $argc >= 4 ? $argv[3] : 'false'; +$databaseConnection = $argc >= 5 ? $argv[4] : null; + +// Validate migration mode +$validModes = ['default', 'fresh', 'refresh']; +if (!in_array($migrationMode, $validModes)) { + fwrite(STDERR, "Error: Invalid migration mode '{$migrationMode}'. Must be one of: " . implode(', ', $validModes) . "\n"); + exit(1); +} + +// Validate migration isolation +$validIsolations = ['true', 'false']; +if (!in_array($migrationIsolation, $validIsolations)) { + fwrite(STDERR, "Error: Invalid migration isolation '{$migrationIsolation}'. Must be one of: " . implode(', ', $validIsolations) . "\n"); + exit(1); +} + +// Validate that the app base directory exists +if (!is_dir($appBaseDir)) { + fwrite(STDERR, "Error: App base directory does not exist: {$appBaseDir}\n"); + exit(1); +} + +// Validate that required Laravel files exist +$vendorAutoload = "{$appBaseDir}/vendor/autoload.php"; +$bootstrapApp = "{$appBaseDir}/bootstrap/app.php"; + +if (!file_exists($vendorAutoload)) { + fwrite(STDERR, "Error: Composer autoload file not found: {$vendorAutoload}\n"); + exit(1); +} + +if (!file_exists($bootstrapApp)) { + fwrite(STDERR, "Error: Laravel bootstrap file not found: {$bootstrapApp}\n"); + exit(1); +} + +// Bootstrap Laravel +try { + require $vendorAutoload; + + $app = require_once $bootstrapApp; + $kernel = $app->make(Illuminate\Contracts\Console\Kernel::class); + $kernel->bootstrap(); + +} catch (Exception $e) { + fwrite(STDERR, "Error bootstrapping Laravel: {$e->getMessage()}\n"); + exit(1); +} + +// Test database connection +try { + // Use specific database connection if provided + $connection = $databaseConnection ? DB::connection($databaseConnection) : DB::connection(); + $driver = $connection->getDriverName(); + + // SQLite special handling + if ($driver === 'sqlite') { + $dbPath = $connection->getDatabaseName(); + + // Handle in-memory SQLite databases + if ($dbPath === ':memory:') { + fwrite(STDOUT, "SQLite in-memory database detected - ready\n"); + exit(0); + } + + $dbDirectory = dirname($dbPath); + + // Check if database file already exists + if (file_exists($dbPath)) { + fwrite(STDOUT, "SQLite database file exists: {$dbPath}\n"); + exit(0); + } + + // Database file doesn't exist - check if directory exists and is writable + if (!is_dir($dbDirectory)) { + fwrite(STDERR, "SQLite database directory does not exist: {$dbDirectory}\n"); + fwrite(STDERR, "Please create the directory before running migrations.\n"); + fwrite(STDERR, "Example: mkdir -p {$dbDirectory}\n"); + exit(1); + } + + if (!is_writable($dbDirectory)) { + fwrite(STDERR, "SQLite database directory is not writable: {$dbDirectory}\n"); + fwrite(STDERR, "Please check directory permissions.\n"); + exit(1); + } + + // For 'fresh' and 'refresh' modes, the database file must already exist + if ($migrationMode === 'fresh' || $migrationMode === 'refresh') { + fwrite(STDERR, "SQLite database file does not exist: {$dbPath}\n"); + fwrite(STDERR, "Migration mode '{$migrationMode}' requires the database file to exist.\n"); + fwrite(STDERR, "Either:\n"); + fwrite(STDERR, " 1. Create the database (ensure it has read and write permissions for your user): touch {$dbPath}\n"); + fwrite(STDERR, " 2. Use AUTORUN_LARAVEL_MIGRATION_MODE=default to let Laravel create it\n"); + exit(1); + } + + // For isolated migrations, the database file must exist (even in default mode) + if ($migrationIsolation === 'true') { + fwrite(STDERR, "SQLite database file does not exist: {$dbPath}\n"); + fwrite(STDERR, "Isolated migrations require the database file to exist before running.\n"); + fwrite(STDERR, "Either:\n"); + fwrite(STDERR, " 1. Create the database (ensure it has read and write permissions for your user): touch {$dbPath}\n"); + fwrite(STDERR, " 2. Set AUTORUN_LARAVEL_MIGRATION_ISOLATION=false to let migrations create it\n"); + exit(1); + } + + // Directory exists and is writable - migrations can create the database file (default mode only) + fwrite(STDOUT, "SQLite database directory is ready - migrations will create database\n"); + exit(0); + } + + // Test connection for other database drivers + $connection->getPdo(); + + if ($connection->getDatabaseName()) { + $connectionName = $databaseConnection ? " ({$databaseConnection})" : ''; + fwrite(STDOUT, "Database connection successful ({$driver}){$connectionName}\n"); + exit(0); + } else { + fwrite(STDERR, "Database name not found\n"); + exit(1); + } + +} catch (Exception $e) { + $connectionName = $databaseConnection ? " ({$databaseConnection})" : ''; + fwrite(STDERR, "Database connection error{$connectionName}: {$e->getMessage()}\n"); + exit(1); +} \ No newline at end of file diff --git a/src/variations/cli/Dockerfile b/src/variations/cli/Dockerfile index a3a90a5..354d881 100644 --- a/src/variations/cli/Dockerfile +++ b/src/variations/cli/Dockerfile @@ -3,7 +3,7 @@ ARG PHP_VERSION='8.5' ARG PHP_VARIATION='cli' ARG BASE_REPO='serversideup/php' ARG TAG_PREFIX='' -ARG IMAGE_VERSION='v4.2.1' +ARG IMAGE_VERSION='v5.0.2' ARG BASE_IMAGE="${BASE_REPO}:${TAG_PREFIX}${PHP_VERSION}-${PHP_VARIATION}-${BASE_OS_VERSION}-${IMAGE_VERSION}" ########## diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile index c4f13ec..ab93869 100644 --- a/src/variations/frankenphp/Dockerfile +++ b/src/variations/frankenphp/Dockerfile @@ -4,7 +4,7 @@ ARG PHP_VERSION='8.5' ARG PHP_VARIATION='frankenphp' ARG BASE_REPO='serversideup/php' ARG TAG_PREFIX='' -ARG IMAGE_VERSION='v4.2.1' +ARG IMAGE_VERSION='v5.0.2' ARG BASE_IMAGE="${BASE_REPO}:${TAG_PREFIX}${PHP_VERSION}-${PHP_VARIATION}-${BASE_OS_VERSION}-${IMAGE_VERSION}" ######################## @@ -39,6 +39,9 @@ FROM common AS final ARG REPOSITORY_BUILD_VERSION='dev' +# serversideup v5 passe a CADDY_LOG_FORMAT=auto / CADDY_LOG_OUTPUT=stderr. +# Nos log-level/*.caddyfile font `format {$CADDY_LOG_FORMAT}` : "auto" n'est pas +# un encodeur Caddy valide, on garde donc les valeurs v4. ENV \ PHP_VARIABLES_ORDER="GPCS" \ PHP_OPCACHE_PRELOAD="" \ @@ -51,7 +54,9 @@ ENV \ PHP_OPCACHE_JIT_BUFFER_SIZE="64M" \ FRANKENPHP_THREADS=8 \ FRANKENPHP_MAX_THREADS=32 \ - FRANKENPHP_WORKER_THREADS=4 + FRANKENPHP_WORKER_THREADS=4 \ + CADDY_LOG_FORMAT="console" \ + CADDY_LOG_OUTPUT="stdout" LABEL org.opencontainers.image.title="yieldstudio/php (frankenphp)" \ org.opencontainers.image.description="Supercharge your PHP experience. Based off the official PHP images and serversideup/php, yieldstudio/php includes pre-configured PHP extensions and settings for enhanced performance and security. Optimized for Laravel and WordPress." \