Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/service_docker-build-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
38 changes: 15 additions & 23 deletions scripts/conf/php-versions-base-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
6 changes: 6 additions & 0 deletions scripts/conf/sail-versions-base-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
160 changes: 160 additions & 0 deletions src/common/etc/entrypoint.d/lib/laravel/test-db-connection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php
/**
* Test Laravel Database Connection
*
* This script tests if the Laravel application can connect to its configured database.
* It's designed to be called from shell scripts during container initialization.
*
* Usage: php test-db-connection.php /path/to/app/base/dir [migration_mode] [migration_isolation] [database_connection]
*
* Arguments:
* app_base_dir - Path to Laravel application root
* migration_mode - Migration mode: 'default', 'fresh', or 'refresh' (optional, defaults to 'default')
* migration_isolation - Whether to run migrations in isolation (optional, defaults to 'false')
* database_connection - Name of the database connection to test (optional, defaults to 'default')
*
* Exit codes:
* 0 - Success: Database is ready and accessible
* 1 - Failure: Database connection failed or other error
*
* @package serversideup/php
*/

// Validate arguments
if ($argc < 2 || $argc > 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);
}
2 changes: 1 addition & 1 deletion src/variations/cli/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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}"

##########
Expand Down
9 changes: 7 additions & 2 deletions src/variations/frankenphp/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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}"

########################
Expand Down Expand Up @@ -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="" \
Expand All @@ -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." \
Expand Down
Loading