Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
925cd3a
Refactor Laravel migration script to improve isolation handling and d…
jaydrogers Dec 5, 2025
0645221
Remove debug log from Laravel migration script to streamline output d…
jaydrogers Dec 5, 2025
9d3f0a4
Update Laravel migration script to change error message from error to…
jaydrogers Jan 14, 2026
9c2d689
Update PHP base opertating systems. Add Alpine 3.23 support (#638)
alloylab Jan 14, 2026
0260542
Update PHP extension installer version to 2.9.27
jaydrogers Jan 14, 2026
7f2836a
Update NGINX version to 1.28.1
jaydrogers Jan 14, 2026
4c4a436
Merge branch 'release/bugfixes-and-dependency-updates' into fix/larav…
jaydrogers Jan 14, 2026
7a1b6b9
Refactor and improve security headers, file blocks, etc (#631)
marns93 Jan 15, 2026
2829cf2
Update GitHub Actions to use actions/checkout@v6 in multiple workflows
jaydrogers Jan 15, 2026
f0e5dc9
Update GitHub Actions to use actions/upload-artifact@v6 for improved …
jaydrogers Jan 15, 2026
b8259a1
Update GitHub Actions to use actions/download-artifact@v7 for improve…
jaydrogers Jan 15, 2026
245e23f
Upgrade FrankenPHP to v1.11.1
jaydrogers Jan 15, 2026
ca9136d
Increase size of GitHub Actions Runners because of memory segmentatio…
jaydrogers Jan 15, 2026
0c7b634
Merge branch 'main' into release/bugfixes-and-dependency-updates
jaydrogers Jan 15, 2026
919fd47
Add security measures to block PHP execution in storage directory (#641)
jaydrogers Jan 16, 2026
3a70f32
Merge branch 'release/bugfixes-and-dependency-updates' into fix/larav…
jaydrogers Jan 16, 2026
e6681ce
Refactor Laravel version check and isolation mode handling in automat…
jaydrogers Jan 16, 2026
375839a
Update container info script to include automation status
jaydrogers Jan 17, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/action_update-dockerhub-readme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
name: Push README to Docker Hub
steps:
- name: git checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
ref: main

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scheduled-task_update-sponsors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout 🛎️
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Generate Sponsors 💖
uses: JamesIves/github-sponsors-readme-action@v1
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/service_docker-build-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
php-version-map-json: ${{ steps.get-php-versions.outputs.php-version-map-json }}
steps:
- name: Check out code
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref }}

Expand Down Expand Up @@ -67,25 +67,25 @@ jobs:
echo "${MATRIX_JSON}" | jq '.'

- name: Upload the php-versions.yml file
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: php-versions.yml
path: ${{ inputs.php-versions-file }}

docker-publish:
needs: setup-matrix
runs-on: depot-ubuntu-24.04-4
runs-on: depot-ubuntu-24.04-8
strategy:
matrix: ${{fromJson(needs.setup-matrix.outputs.php-version-map-json)}}

steps:
- name: Check out code.
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref }}

- name: Download PHP Versions file
uses: actions/download-artifact@v5
uses: actions/download-artifact@v7
with:
name: php-versions.yml
path: ./artifacts
Expand Down
35 changes: 20 additions & 15 deletions scripts/conf/php-versions-base-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,42 +35,43 @@ php_versions:
- 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
# - 8.1.34 # Pull latest from Official PHP source
- minor: "8.2"
base_os:
- name: alpine3.21
- name: alpine3.22
- name: alpine3.23
- name: bookworm
- name: trixie
patch_versions:
# - 8.2.18 # Pull latest from Official PHP source
# - 8.2.30 # Pull latest from Official PHP source
- minor: "8.3"
base_os:
- name: alpine3.21
- name: alpine3.22
- name: alpine3.23
- name: bookworm
- name: trixie
patch_versions:
# - 8.3.6 # Pull latest from Official PHP source
# - 8.3.29 # Pull latest from Official PHP source
- minor: "8.4"
base_os:
- name: alpine3.21
- name: alpine3.22
- name: alpine3.23
- name: bookworm
- name: trixie
patch_versions:
# - 8.4.1 # Pull latest from Official PHP source
# - 8.4.16 # Pull latest from Official PHP source
- minor: "8.5"
base_os:
- name: alpine3.21
- name: alpine3.22
- name: alpine3.23
- name: bookworm
- name: trixie
patch_versions:
# - 8.5.0 # Pull latest from Official PHP source
# - 8.5.1 # Pull latest from Official PHP source

operating_systems:
- family: alpine
Expand All @@ -94,27 +95,31 @@ operating_systems:
- name: "Alpine 3.20"
version: alpine3.20
number: 3.20
nginx_version: 1.28.0-r1
nginx_version: 1.28.1-r1
- name: "Alpine 3.21"
version: alpine3.21
number: 3.21
nginx_version: 1.28.0-r1
nginx_version: 1.28.1-r1
- name: "Alpine 3.22"
version: alpine3.22
number: 3.22
nginx_version: 1.28.0-r1
nginx_version: 1.28.1-r1
- name: "Alpine 3.23"
version: alpine3.23
number: 3.23
nginx_version: 1.28.1-r1
- family: debian
default: true
versions:
- name: "Debian Bullseye"
version: bullseye
number: 11
nginx_version: 1.28.0-1~bullseye
nginx_version: 1.28.1-1~bullseye
- name: "Debian Bookworm"
version: bookworm
number: 12
nginx_version: 1.28.0-1~bookworm
nginx_version: 1.28.1-1~bookworm
- name: "Debian Trixie"
version: trixie
number: 13
nginx_version: 1.28.0-1~trixie
nginx_version: 1.28.1-1~trixie
3 changes: 2 additions & 1 deletion src/common/etc/entrypoint.d/0-container-info.sh
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ Brought to you by serversideup.net
• Upload Limit: '"$UPLOAD_LIMIT"'

🔄 Runtime
• Docker CMD: '"$DOCKER_CMD"'
• Automations: '"$AUTORUN_ENABLED"'
• Docker CMD: '"$DOCKER_CMD"'
'

if [ "$PHP_OPCACHE_STATUS" = "0" ]; then
Expand Down
145 changes: 96 additions & 49 deletions src/common/etc/entrypoint.d/50-laravel-automations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ fi
############################################################################

artisan_migrate() {
migrate_flags=""

debug_log "Starting migrations (isolation: $AUTORUN_LARAVEL_MIGRATION_ISOLATION)"

echo "🚀 Clearing Laravel cache before attempting migrations..."
php "$APP_BASE_DIR/artisan" config:clear

Expand All @@ -73,7 +69,8 @@ artisan_migrate() {
;;
esac

# Build migration flags (used for all databases)
# Determine if isolation is intended to be used
isolation_enabled="false"
if [ "$AUTORUN_LARAVEL_MIGRATION_ISOLATION" = "true" ]; then
# Isolation only works in default mode
if [ "$AUTORUN_LARAVEL_MIGRATION_MODE" != "default" ]; then
Expand All @@ -82,14 +79,18 @@ artisan_migrate() {
fi

# Isolation requires Laravel 9.38.0+
if ! laravel_version_is_at_least "9.38.0"; then
echo "❌ $script_name: Isolated migrations require Laravel v9.38.0 or above. Detected version: $(get_laravel_version)"
return 1
if laravel_version_is_at_least "9.38.0"; then
isolation_enabled="true"
debug_log "Isolation mode enabled (Laravel version check passed)"
else
echo "⚠️ $script_name: Isolated migrations require Laravel v9.38.0 or above. Detected version: $(get_laravel_version)"
echo " Continuing without isolation mode..."
fi

migrate_flags="$migrate_flags --isolated"
fi

# Start assembling migration flags
migrate_flags=""

if [ "$AUTORUN_LARAVEL_MIGRATION_FORCE" = "true" ]; then
migrate_flags="$migrate_flags --force"
fi
Expand All @@ -98,30 +99,55 @@ artisan_migrate() {
migrate_flags="$migrate_flags --seed"
fi

# Determine if multiple databases are specified
# Helper function to run migrations for a specific database
run_migration_for_db() {
db_name="${1:-}"

# Build display name and database flag for messages/commands
if [ -n "$db_name" ]; then
db_display_name="'$db_name'"
db_flag="--database=$db_name"
else
db_display_name="default database"
db_flag=""
fi

# Wait for database connection
if ! wait_for_database_connection $db_name; then
echo "❌ $script_name: Failed to connect to $db_display_name"
return 1
fi

# Determine if --isolated can be used for this database
db_migrate_flags="$migrate_flags"
if [ "$isolation_enabled" = "true" ]; then
if db_has_migrations_table $db_name; then
db_migrate_flags="$db_migrate_flags --isolated"
debug_log "Using --isolated flag for $db_display_name"
else
echo "ℹ️ Skipping --isolated flag for $db_display_name: migrations table not ready (normal for first deployment)"
echo " The --isolated flag will be used on subsequent deployments."
fi
fi

echo "🚀 Running migrations for $db_display_name"
php "$APP_BASE_DIR/artisan" $migration_command $db_flag $db_migrate_flags
}

# Run migrations for specified database(s)
if [ -n "$AUTORUN_LARAVEL_MIGRATION_DATABASE" ]; then
databases=$(convert_comma_delimited_to_space_separated "$AUTORUN_LARAVEL_MIGRATION_DATABASE")
database_list=$(echo "$databases" | tr ',' ' ')

for db in $database_list; do
# Wait for this specific database to be ready
if ! wait_for_database_connection "$db"; then
echo "❌ $script_name: Failed to connect to database: $db"
if ! run_migration_for_db "$db"; then
return 1
fi

echo "🚀 Running migrations for database: $db"
php "$APP_BASE_DIR/artisan" $migration_command --database=$db $migrate_flags
done
else
# Wait for default database connection
if ! wait_for_database_connection; then
echo "❌ $script_name: Failed to connect to default database"
if ! run_migration_for_db; then
return 1
fi

# Run migration with default database connection
php "$APP_BASE_DIR/artisan" $migration_command $migrate_flags
fi
}

Expand Down Expand Up @@ -241,17 +267,16 @@ get_laravel_version() {
fi

debug_log "Detecting Laravel version..."
# Use 2>/dev/null to handle potential PHP warnings
artisan_version_output=$(php "$APP_BASE_DIR/artisan" --version 2>/dev/null)

# Check if command was successful
if [ $? -ne 0 ]; then
# Capture artisan output
if ! artisan_version_output=$(php "$APP_BASE_DIR/artisan" --version 2>/dev/null); then
echo "❌ $script_name: Failed to execute artisan command" >&2
return 1
fi

debug_log "Raw artisan output: $artisan_version_output"

# Extract version number using sed (POSIX compliant)
# Using a more strict pattern that matches "Laravel Framework X.Y.Z"
laravel_version=$(echo "$artisan_version_output" | sed -e 's/^Laravel Framework \([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*$/\1/')

# Validate that we got a version number (POSIX compliant regex)
Expand All @@ -261,7 +286,7 @@ get_laravel_version() {
echo "$laravel_version"
return 0
else
echo "❌ $script_name: Failed to determine Laravel version" >&2
echo "❌ $script_name: Failed to determine Laravel version from: $artisan_version_output" >&2
return 1
fi
}
Expand All @@ -286,33 +311,55 @@ laravel_version_is_at_least() {
return 1
fi

# Validate required version format
if ! echo "$required_version" | grep -Eq '^[0-9]+\.[0-9]+(\.[0-9]+)?$'; then
echo "❌ $script_name - Invalid version requirement format: $required_version" >&2
return 1
fi

current_version=$(get_laravel_version)
if [ $? -ne 0 ]; then
echo "❌ $script_name: Failed to get Laravel version" >&2
return 1
fi

# normalize_version() takes a version string and ensures it has 3 parts
normalize_version() {
echo "$1" | awk -F. '{ print $1"."$2"."(NF>2?$3:0) }'
}
# Extract version components using cut (POSIX compliant)
cur_major=$(echo "$current_version" | cut -d. -f1)
cur_minor=$(echo "$current_version" | cut -d. -f2)
cur_patch=$(echo "$current_version" | cut -d. -f3)

req_major=$(echo "$required_version" | cut -d. -f1)
req_minor=$(echo "$required_version" | cut -d. -f2)
req_patch=$(echo "$required_version" | cut -d. -f3)

normalized_current=$(normalize_version "$current_version")
normalized_required=$(normalize_version "$required_version")
# Default patch to 0 if not specified
: "${cur_patch:=0}"
: "${req_patch:=0}"

# Use sort -V to get the lower version, then compare it with required version
# This works in BusyBox because we only need to check the first line of output
lowest_version=$(printf '%s\n%s\n' "$normalized_required" "$normalized_current" | sort -V | head -n1)
if [ "$lowest_version" = "$normalized_required" ]; then
return 0 # Success: current version is >= required version
# Numeric comparison (POSIX arithmetic expansion handles this correctly)
# Compare major version
if [ "$cur_major" -gt "$req_major" ]; then
return 0
elif [ "$cur_major" -lt "$req_major" ]; then
return 1
fi

# Major versions equal, compare minor
if [ "$cur_minor" -gt "$req_minor" ]; then
return 0
elif [ "$cur_minor" -lt "$req_minor" ]; then
return 1
fi

# Minor versions equal, compare patch
if [ "$cur_patch" -ge "$req_patch" ]; then
return 0
fi

return 1
}

db_has_migrations_table() {
database_arg="${1:-}"

if [ -n "$database_arg" ]; then
php "$APP_BASE_DIR/artisan" migrate:status --database="$database_arg" > /dev/null 2>&1
else
return 1 # Failure: current version is < required version
php "$APP_BASE_DIR/artisan" migrate:status > /dev/null 2>&1
fi
}

Expand All @@ -324,9 +371,9 @@ test_db_connection() {
# Pass database connection name only if specified (not empty)
database_arg="${1:-}"
if [ -n "$database_arg" ]; then
php "$AUTORUN_LIB_DIR/laravel/test-db-connection.php" "$APP_BASE_DIR" "$AUTORUN_LARAVEL_MIGRATION_MODE" "$AUTORUN_LARAVEL_MIGRATION_ISOLATION" "$database_arg"
php "$AUTORUN_LIB_DIR/laravel/test-db-connection.php" "$APP_BASE_DIR" "$AUTORUN_LARAVEL_MIGRATION_MODE" "$database_arg"
else
php "$AUTORUN_LIB_DIR/laravel/test-db-connection.php" "$APP_BASE_DIR" "$AUTORUN_LARAVEL_MIGRATION_MODE" "$AUTORUN_LARAVEL_MIGRATION_ISOLATION"
php "$AUTORUN_LIB_DIR/laravel/test-db-connection.php" "$APP_BASE_DIR" "$AUTORUN_LARAVEL_MIGRATION_MODE"
fi
}

Expand Down
Loading