diff --git a/.devilbox/www/config.php b/.devilbox/www/config.php
index e04cbd1af..4f8dcddd9 100644
--- a/.devilbox/www/config.php
+++ b/.devilbox/www/config.php
@@ -13,8 +13,8 @@
putenv('RES_OPTIONS=retrans:1 retry:1 timeout:1 attempts:1');
-$DEVILBOX_VERSION = 'v3.0.0-beta-0.6';
-$DEVILBOX_DATE = '2024-11-5';
+$DEVILBOX_VERSION = 'v3.0.0';
+$DEVILBOX_DATE = '2025-03-27';
$DEVILBOX_API_PAGE = 'devilbox-api/status.json';
//
diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
index ea54f7194..6f443f5e5 100644
--- a/.github/workflows/documentation.yml
+++ b/.github/workflows/documentation.yml
@@ -15,13 +15,13 @@ on:
paths:
- 'docs/**'
- '!**.md'
- # Runs on master Branch and Tags
+ # Runs on mainline Branch and Tags
push:
paths:
- 'docs/**'
- '!**.md'
branches:
- - master
+ - mainline
# -------------------------------------------------------------------------------------------------
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 47e630bcb..3ade261c9 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -13,10 +13,10 @@ on:
# Runs on Pull Requests
pull_request:
- # Runs on master Branch and Tags
+ # Runs on mainline Branch and Tags
push:
branches:
- - master
+ - mainline
# -------------------------------------------------------------------------------------------------
diff --git a/.github/workflows/params-mongo.yml b/.github/workflows/params-mongo.yml
index 9d509315e..38c4a322a 100644
--- a/.github/workflows/params-mongo.yml
+++ b/.github/workflows/params-mongo.yml
@@ -16,7 +16,6 @@ env:
# CI for Mongo 3.2 and 3.4 removed due to non-reproducible error in CI
MATRIX: >-
[
- {"MONGO_SERVER": "Mongo 3.6"},
{"MONGO_SERVER": "Mongo 4.0"},
{"MONGO_SERVER": "Mongo 4.2"},
{"MONGO_SERVER": "Mongo 4.4"},
diff --git a/.github/workflows/params-php.yml b/.github/workflows/params-php.yml
index e563c72aa..326351804 100644
--- a/.github/workflows/params-php.yml
+++ b/.github/workflows/params-php.yml
@@ -14,38 +14,26 @@ env:
# PgSQL server versions. That's why we need to tell those combinations to use an old PgSQL server
MATRIX: >-
[
- {"PHP_SERVER": "PHP 5.6", "HTTPD_SERVER": "apache-2.4", "PGSQL_SERVER": "PgSQL 12", "MONGO_SERVER": "Mongo 5.0"},
- {"PHP_SERVER": "PHP 7.0", "HTTPD_SERVER": "apache-2.4", "PGSQL_SERVER": "PgSQL 12", "MONGO_SERVER": "Mongo 5.0"},
- {"PHP_SERVER": "PHP 7.1", "HTTPD_SERVER": "apache-2.4", "PGSQL_SERVER": "PgSQL 12"},
- {"PHP_SERVER": "PHP 7.2", "HTTPD_SERVER": "apache-2.4"},
- {"PHP_SERVER": "PHP 7.3", "HTTPD_SERVER": "apache-2.4"},
{"PHP_SERVER": "PHP 7.4", "HTTPD_SERVER": "apache-2.4"},
{"PHP_SERVER": "PHP 8.0", "HTTPD_SERVER": "apache-2.4"},
{"PHP_SERVER": "PHP 8.1", "HTTPD_SERVER": "apache-2.4"},
{"PHP_SERVER": "PHP 8.2", "HTTPD_SERVER": "apache-2.4"},
{"PHP_SERVER": "PHP 8.3", "HTTPD_SERVER": "apache-2.4"},
+ {"PHP_SERVER": "PHP 8.4", "HTTPD_SERVER": "apache-2.4"},
- {"PHP_SERVER": "PHP 5.6", "HTTPD_SERVER": "nginx-stable", "PGSQL_SERVER": "PgSQL 12", "MONGO_SERVER": "Mongo 5.0"},
- {"PHP_SERVER": "PHP 7.0", "HTTPD_SERVER": "nginx-stable", "PGSQL_SERVER": "PgSQL 12", "MONGO_SERVER": "Mongo 5.0"},
- {"PHP_SERVER": "PHP 7.1", "HTTPD_SERVER": "nginx-stable", "PGSQL_SERVER": "PgSQL 12"},
- {"PHP_SERVER": "PHP 7.2", "HTTPD_SERVER": "nginx-stable"},
- {"PHP_SERVER": "PHP 7.3", "HTTPD_SERVER": "nginx-stable"},
{"PHP_SERVER": "PHP 7.4", "HTTPD_SERVER": "nginx-stable"},
{"PHP_SERVER": "PHP 8.0", "HTTPD_SERVER": "nginx-stable"},
{"PHP_SERVER": "PHP 8.1", "HTTPD_SERVER": "nginx-stable"},
{"PHP_SERVER": "PHP 8.2", "HTTPD_SERVER": "nginx-stable"},
{"PHP_SERVER": "PHP 8.3", "HTTPD_SERVER": "nginx-stable"},
+ {"PHP_SERVER": "PHP 8.4", "HTTPD_SERVER": "nginx-stable"},
- {"PHP_SERVER": "PHP 5.6", "HTTPD_SERVER": "nginx-mainline", "PGSQL_SERVER": "PgSQL 12", "MONGO_SERVER": "Mongo 5.0"},
- {"PHP_SERVER": "PHP 7.0", "HTTPD_SERVER": "nginx-mainline", "PGSQL_SERVER": "PgSQL 12", "MONGO_SERVER": "Mongo 5.0"},
- {"PHP_SERVER": "PHP 7.1", "HTTPD_SERVER": "nginx-mainline", "PGSQL_SERVER": "PgSQL 12"},
- {"PHP_SERVER": "PHP 7.2", "HTTPD_SERVER": "nginx-mainline"},
- {"PHP_SERVER": "PHP 7.3", "HTTPD_SERVER": "nginx-mainline"},
{"PHP_SERVER": "PHP 7.4", "HTTPD_SERVER": "nginx-mainline"},
{"PHP_SERVER": "PHP 8.0", "HTTPD_SERVER": "nginx-mainline"},
{"PHP_SERVER": "PHP 8.1", "HTTPD_SERVER": "nginx-mainline"},
{"PHP_SERVER": "PHP 8.2", "HTTPD_SERVER": "nginx-mainline"},
- {"PHP_SERVER": "PHP 8.3", "HTTPD_SERVER": "nginx-mainline"}
+ {"PHP_SERVER": "PHP 8.3", "HTTPD_SERVER": "nginx-mainline"},
+ {"PHP_SERVER": "PHP 8.4", "HTTPD_SERVER": "nginx-mainline"}
]
diff --git a/.github/workflows/test-httpd.yml b/.github/workflows/test-httpd.yml
index 8f6c598a6..1d7add513 100644
--- a/.github/workflows/test-httpd.yml
+++ b/.github/workflows/test-httpd.yml
@@ -24,7 +24,7 @@ on:
- 'docker-compose.yml'
- 'env-example'
- '!**.md'
- # Runs on master Branch and Tags
+ # Runs on mainline Branch and Tags
push:
paths:
- '.devilbox/**'
@@ -39,7 +39,7 @@ on:
- 'env-example'
- '!**.md'
branches:
- - master
+ - mainline
tags:
- '[0-9]+.[0-9]+*'
diff --git a/.github/workflows/test-memcd.yml b/.github/workflows/test-memcd.yml
index 4e3318a07..b27ac1ecf 100644
--- a/.github/workflows/test-memcd.yml
+++ b/.github/workflows/test-memcd.yml
@@ -24,7 +24,7 @@ on:
- 'docker-compose.yml'
- 'env-example'
- '!**.md'
- # Runs on master Branch and Tags
+ # Runs on mainline Branch and Tags
push:
paths:
- '.devilbox/**'
@@ -39,7 +39,7 @@ on:
- 'env-example'
- '!**.md'
branches:
- - master
+ - mainline
tags:
- '[0-9]+.[0-9]+*'
diff --git a/.github/workflows/test-mongo.yml b/.github/workflows/test-mongo.yml
index 899bdf174..295c57026 100644
--- a/.github/workflows/test-mongo.yml
+++ b/.github/workflows/test-mongo.yml
@@ -24,7 +24,7 @@ on:
- 'docker-compose.yml'
- 'env-example'
- '!**.md'
- # Runs on master Branch and Tags
+ # Runs on mainline Branch and Tags
push:
paths:
- '.devilbox/**'
@@ -39,7 +39,7 @@ on:
- 'env-example'
- '!**.md'
branches:
- - master
+ - mainline
tags:
- '[0-9]+.[0-9]+*'
diff --git a/.github/workflows/test-mysql.yml b/.github/workflows/test-mysql.yml
index 5b924f7c4..5d237fd0f 100644
--- a/.github/workflows/test-mysql.yml
+++ b/.github/workflows/test-mysql.yml
@@ -24,7 +24,7 @@ on:
- 'docker-compose.yml'
- 'env-example'
- '!**.md'
- # Runs on master Branch and Tags
+ # Runs on mainline Branch and Tags
push:
paths:
- '.devilbox/**'
@@ -39,7 +39,7 @@ on:
- 'env-example'
- '!**.md'
branches:
- - master
+ - mainline
tags:
- '[0-9]+.[0-9]+*'
diff --git a/.github/workflows/test-pgsql.yml b/.github/workflows/test-pgsql.yml
index 04690535d..88f1f1a49 100644
--- a/.github/workflows/test-pgsql.yml
+++ b/.github/workflows/test-pgsql.yml
@@ -24,7 +24,7 @@ on:
- 'docker-compose.yml'
- 'env-example'
- '!**.md'
- # Runs on master Branch and Tags
+ # Runs on mainline Branch and Tags
push:
paths:
- '.devilbox/**'
@@ -39,7 +39,7 @@ on:
- 'env-example'
- '!**.md'
branches:
- - master
+ - mainline
tags:
- '[0-9]+.[0-9]+*'
diff --git a/.github/workflows/test-php.yml b/.github/workflows/test-php.yml
index a014bea88..20a2ca3ec 100644
--- a/.github/workflows/test-php.yml
+++ b/.github/workflows/test-php.yml
@@ -24,7 +24,7 @@ on:
- 'docker-compose.yml'
- 'env-example'
- '!**.md'
- # Runs on master Branch and Tags
+ # Runs on mainline Branch and Tags
push:
paths:
- '.devilbox/**'
@@ -39,7 +39,7 @@ on:
- 'env-example'
- '!**.md'
branches:
- - master
+ - mainline
tags:
- '[0-9]+.[0-9]+*'
diff --git a/.github/workflows/test-redis.yml b/.github/workflows/test-redis.yml
index 20fa98e23..89d81b0d5 100644
--- a/.github/workflows/test-redis.yml
+++ b/.github/workflows/test-redis.yml
@@ -24,7 +24,7 @@ on:
- 'docker-compose.yml'
- 'env-example'
- '!**.md'
- # Runs on master Branch and Tags
+ # Runs on mainline Branch and Tags
push:
paths:
- '.devilbox/**'
@@ -39,7 +39,7 @@ on:
- 'env-example'
- '!**.md'
branches:
- - master
+ - mainline
tags:
- '[0-9]+.[0-9]+*'
diff --git a/.github/workflows/zzz-reuse-tests.yml b/.github/workflows/zzz-reuse-tests.yml
index f0a9f7772..b3e411eff 100644
--- a/.github/workflows/zzz-reuse-tests.yml
+++ b/.github/workflows/zzz-reuse-tests.yml
@@ -65,7 +65,18 @@ jobs:
- name: "[DEBUG] Show Docker Compose version"
shell: bash
run: |
- docker-compose version
+ # Try both the old hyphenated and new space-separated commands
+ docker-compose version || docker compose version || echo "Docker Compose not available via standard commands"
+
+ - name: "[SETUP] Ensure docker-compose compatibility"
+ shell: bash
+ run: |
+ if ! command -v docker-compose &> /dev/null && command -v docker &> /dev/null; then
+ echo "Creating docker-compose compatibility wrapper"
+ echo '#!/bin/bash
+ docker compose "$@"' | sudo tee /usr/local/bin/docker-compose
+ sudo chmod +x /usr/local/bin/docker-compose
+ fi
# ------------------------------------------------------------
# Configure
diff --git a/.tests/Makefile b/.tests/Makefile
index 2e9ff81e4..4947b330a 100644
--- a/.tests/Makefile
+++ b/.tests/Makefile
@@ -55,10 +55,10 @@ endif
### Pull currently setup images
###
pull: ../.env
- cat "../docker-compose.yml" \
- | perl -0 -pe "s/# version: '2.3'/version: '2.3'/g" \
- > "../docker-compose.yml.tmp"
- yes | mv -f "../docker-compose.yml.tmp" "../docker-compose.yml"
+ #cat "../docker-compose.yml" \
+ # | perl -0 -pe "s/# version: '2.3'/version: '2.3'/g" \
+ # > "../docker-compose.yml.tmp"
+ #yes | mv -f "../docker-compose.yml.tmp" "../docker-compose.yml"
@$(PWD)/scripts/compose-pull.sh
diff --git a/.tests/devilbox-template-config.yaml b/.tests/devilbox-template-config.yaml
index 85786a304..92ceade12 100644
--- a/.tests/devilbox-template-config.yaml
+++ b/.tests/devilbox-template-config.yaml
@@ -1,5 +1,7 @@
---
# .devilbox.yaml
+# This file is used to automate the initialization of webapps for the Devilbox.
+# Repository: https://github.com/devilbox-community/devilbox
#
#:-version: v1
diff --git a/.tests/scripts/.lib.sh b/.tests/scripts/.lib.sh
index f320266ae..789a98f7f 100644
--- a/.tests/scripts/.lib.sh
+++ b/.tests/scripts/.lib.sh
@@ -48,7 +48,7 @@ get_php_version() {
# Check php -v
>&2 printf "Fetching PHP version from php -v: "
- if ! cli_version="$( run "docker-compose exec -T php php -v \
+ if ! cli_version="$( run "docker compose exec -T php php -v \
| grep -Eo '^PHP[[:space:]]+[0-9]+\\.[0-9]+' \
| grep -Eo '[0-9]+\\.[0-9]+'" \
"${retries}" "${root_path}" "0" )"; then
@@ -285,17 +285,17 @@ create_vhost_dir() {
# Clean vhost dir
cd "${DVLBOX_PATH}"
- while docker-compose exec --user devilbox -T php curl -sS --fail "http://php/vhosts.php" | grep ">${vhost}<" >/dev/null; do
+ while docker compose exec --user devilbox -T php curl -sS --fail "http://php/vhosts.php" | grep ">${vhost}<" >/dev/null; do
echo "Deleting vhost: ${vhost}"
- run "docker-compose exec --user devilbox -T php bash -c 'rm -rf /shared/httpd/${vhost} && sleep 5;'" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php bash -c 'rm -rf /shared/httpd/${vhost} && sleep 5;'" "1" "${DVLBOX_PATH}"
done
# Create vhost dir
cd "${DVLBOX_PATH}"
- while ! docker-compose exec --user devilbox -T php curl -sS --fail "http://php/vhosts.php" | grep ">${vhost}<" >/dev/null; do
+ while ! docker compose exec --user devilbox -T php curl -sS --fail "http://php/vhosts.php" | grep ">${vhost}<" >/dev/null; do
echo "Recreating vhost: ${vhost}"
- run "docker-compose exec --user devilbox -T php bash -c 'rm -rf /shared/httpd/${vhost} && sleep 5;'" "1" "${DVLBOX_PATH}"
- run "docker-compose exec --user devilbox -T php bash -c 'mkdir -p /shared/httpd/${vhost} && sleep 5;'" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php bash -c 'rm -rf /shared/httpd/${vhost} && sleep 5;'" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php bash -c 'mkdir -p /shared/httpd/${vhost} && sleep 5;'" "1" "${DVLBOX_PATH}"
done
echo "Vhost is present: ${vhost}"
}
@@ -327,7 +327,9 @@ sed_command() {
term_spinner() {
local pid=$!
local delay=0.1
+ # shellcheck disable=SC1003
local spinstr='|/-\'
+ # shellcheck disable=SC2143
while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
local temp=${spinstr#?}
printf " [%c] " "$spinstr"
@@ -341,7 +343,9 @@ term_spinner() {
no_term_spinner() {
local pid=$!
local delay=0.1
+ # shellcheck disable=SC1003
local spinstr='|/-\'
+ # shellcheck disable=SC2143
while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
printf "."
sleep 2
diff --git a/.tests/scripts/compose-logs.sh b/.tests/scripts/compose-logs.sh
index b4ead2187..03d16625a 100755
--- a/.tests/scripts/compose-logs.sh
+++ b/.tests/scripts/compose-logs.sh
@@ -14,7 +14,7 @@ DVLBOX_PATH="$( cd "${SCRIPT_PATH}/../.." && pwd -P )"
# Pre-check
# -------------------------------------------------------------------------------------------------
-if ! command -v docker-compose >/dev/null 2>&1; then
+if ! command -v docker compose >/dev/null 2>&1; then
>&2 echo "Error 'docker-compose' binary not found, but required."
exit 1
fi
@@ -26,15 +26,15 @@ fi
echo
echo "# --------------------------------------------------------------------------------"
-echo "# docker-compose logs"
+echo "# docker compose logs"
echo "# --------------------------------------------------------------------------------"
-run "docker-compose logs || true" "1" "${DVLBOX_PATH}"
+run "docker compose logs || true" "1" "${DVLBOX_PATH}"
echo
echo "# --------------------------------------------------------------------------------"
-echo "# docker-compose ps"
+echo "# docker compose ps"
echo "# --------------------------------------------------------------------------------"
-run "docker-compose ps || true" "1" "${DVLBOX_PATH}"
+run "docker compose ps || true" "1" "${DVLBOX_PATH}"
echo
@@ -59,11 +59,11 @@ echo
echo "# --------------------------------------------------------------------------------"
echo "# mounts httpd"
echo "# --------------------------------------------------------------------------------"
-run "docker-compose exec -T httpd ls -lap /shared/httpd/ || true" "1" "${DVLBOX_PATH}"
+run "docker compose exec -T httpd ls -lap /shared/httpd/ || true" "1" "${DVLBOX_PATH}"
echo
echo "# --------------------------------------------------------------------------------"
echo "# mounts php"
echo "# --------------------------------------------------------------------------------"
-run "docker-compose exec -T php ls -lap /shared/httpd/ || true" "1" "${DVLBOX_PATH}"
+run "docker compose exec -T php ls -lap /shared/httpd/ || true" "1" "${DVLBOX_PATH}"
diff --git a/.tests/scripts/compose-pull.sh b/.tests/scripts/compose-pull.sh
index 75c311045..e64be1ee0 100755
--- a/.tests/scripts/compose-pull.sh
+++ b/.tests/scripts/compose-pull.sh
@@ -24,4 +24,4 @@ fi
# ENTRYPOINT
# -------------------------------------------------------------------------------------------------
-run "docker-compose pull" "60" "${DVLBOX_PATH}"
+run "docker compose pull" "60" "${DVLBOX_PATH}"
diff --git a/.tests/scripts/compose-start.sh b/.tests/scripts/compose-start.sh
index 4af2a2a43..47d8ae0c1 100755
--- a/.tests/scripts/compose-start.sh
+++ b/.tests/scripts/compose-start.sh
@@ -19,7 +19,7 @@ if ! command -v curl >/dev/null 2>&1; then
exit 1
fi
-if ! command -v docker-compose >/dev/null 2>&1; then
+if ! command -v docker compose >/dev/null 2>&1; then
>&2 echo "Error 'docker-compose' binary not found, but required."
exit 1
fi
@@ -41,7 +41,7 @@ HTTPD_SERVER="$( "${SCRIPT_PATH}/env-getvar.sh" "HTTPD_SERVER" )"
###
### Startup
###
-run "docker-compose up -d" "1" "${DVLBOX_PATH}"
+run "docker compose up -d" "1" "${DVLBOX_PATH}"
###
@@ -61,10 +61,10 @@ until curl -sS -I --fail -o /dev/null -w "%{http_code}" "http://localhost:${HOST
curl -sS -I -o /dev/null -w "%{http_code}" "http://localhost:${HOST_PORT_HTTPD}" || true
echo
echo "---- curl From PHP container ----"
- run "docker-compose exec -T --user devilbox php curl -sS -v 'http://localhost/'" "1" "${DVLBOX_PATH}" || true
- run "docker-compose exec -T --user devilbox php curl -sS -I 'http://localhost/'" "1" "${DVLBOX_PATH}" || true
- run "docker-compose exec -T --user devilbox php curl -sS -I -o /dev/null -w '%{http_code}' 'http://localhost/'" "1" "${DVLBOX_PATH}" || true
- run "cd ${DVLBOX_PATH} && docker-compose logs" || true
+ run "docker compose exec -T --user devilbox php curl -sS -v 'http://localhost/'" "1" "${DVLBOX_PATH}" || true
+ run "docker compose exec -T --user devilbox php curl -sS -I 'http://localhost/'" "1" "${DVLBOX_PATH}" || true
+ run "docker compose exec -T --user devilbox php curl -sS -I -o /dev/null -w '%{http_code}' 'http://localhost/'" "1" "${DVLBOX_PATH}" || true
+ run "cd ${DVLBOX_PATH} && docker compose logs" || true
run "cat ${DVLBOX_PATH}/log/php-fpm-${PHP_SERVER}/php-fpm.error" || true
run "cat ${DVLBOX_PATH}/log/${HTTPD_SERVER}/defaultlocalhost-error.log" || true
exit 1
@@ -88,7 +88,7 @@ until curl -sS --fail "http://localhost:${HOST_PORT_HTTPD}" 2>/dev/null | grep '
printf "[FAIL]\\n"
curl -sS -v "http://localhost:${HOST_PORT_HTTPD}"
curl -sS -I "http://localhost:${HOST_PORT_HTTPD}"
- run "cd ${DVLBOX_PATH} && docker-compose logs" || true
+ run "cd ${DVLBOX_PATH} && docker compose logs" || true
run "cat ${DVLBOX_PATH}/log/php-fpm-${PHP_SERVER}/php-fpm.error" || true
run "cat ${DVLBOX_PATH}/log/${HTTPD_SERVER}/defaultlocalhost-error.log" || true
exit 1
@@ -116,14 +116,14 @@ printf "[OK]\\n"
###
printf "Waiting for MongoDB connection to be ready "
i=0
-until cd "${DVLBOX_PATH}" && docker-compose exec -T php mongofiles --host=mongo list >/dev/null 2>&1; do
+until cd "${DVLBOX_PATH}" && docker compose exec -T php mongofiles --host=mongo list >/dev/null 2>&1; do
printf "."
i=$(( i + 1 ))
if [ "${i}" -eq "120" ]; then
printf "[FAIL]\\n"
- run "cd ${DVLBOX_PATH} && docker-compose exec -T php mongofiles --host=mongo list" || true
- run "cd ${DVLBOX_PATH} && docker-compose logs" || true
+ run "cd ${DVLBOX_PATH} && docker compose exec -T php mongofiles --host=mongo list" || true
+ run "cd ${DVLBOX_PATH} && docker compose logs" || true
run "cat ${DVLBOX_PATH}/log/php-fpm-${PHP_SERVER}/php-fpm.error" || true
run "cat ${DVLBOX_PATH}/log/${HTTPD_SERVER}/defaultlocalhost-error.log" || true
exit 1
@@ -139,14 +139,14 @@ printf "[OK]\\n"
###
printf "Waiting for MySQL connection to be ready ";
i=0
-until cd "${DVLBOX_PATH}" && docker-compose exec -T php mysql --user=root --password="${MYSQL_ROOT_PASSWORD}" --host=mysql -e 'show databases;' 2>&1 | grep mysql >/dev/null; do
+until cd "${DVLBOX_PATH}" && docker compose exec -T php mysql --user=root --password="${MYSQL_ROOT_PASSWORD}" --host=mysql -e 'show databases;' 2>&1 | grep mysql >/dev/null; do
printf "."
i=$(( i + 1 ))
if [ "${i}" -eq "120" ]; then
printf "[FAIL]\\n"
- run "cd ${DVLBOX_PATH} && docker-compose exec -T php mysql --user=root --password=\"${MYSQL_ROOT_PASSWORD}\" --host=mysql -e 'show databases;'" || true
- run "cd ${DVLBOX_PATH} && docker-compose logs" || true
+ run "cd ${DVLBOX_PATH} && docker compose exec -T php mysql --user=root --password=\"${MYSQL_ROOT_PASSWORD}\" --host=mysql -e 'show databases;'" || true
+ run "cd ${DVLBOX_PATH} && docker compose logs" || true
run "cat ${DVLBOX_PATH}/log/php-fpm-${PHP_SERVER}/php-fpm.error" || true
run "cat ${DVLBOX_PATH}/log/${HTTPD_SERVER}/defaultlocalhost-error.log" || true
exit 1
@@ -162,14 +162,14 @@ printf "[OK]\\n"
###
printf "Waiting for PostgreSQL connection to be ready ";
i=0
-until cd "${DVLBOX_PATH}" && docker-compose exec -T php pg_isready --host=pgsql >/dev/null 2>&1; do
+until cd "${DVLBOX_PATH}" && docker compose exec -T php pg_isready --host=pgsql >/dev/null 2>&1; do
printf "."
i=$(( i + 1 ))
if [ "${i}" -eq "120" ]; then
printf "[FAIL]\\n"
- run "cd ${DVLBOX_PATH} && docker-compose exec -T php pg_isready --host=pgsql" || true
- run "cd ${DVLBOX_PATH} && docker-compose logs" || true
+ run "cd ${DVLBOX_PATH} && docker compose exec -T php pg_isready --host=pgsql" || true
+ run "cd ${DVLBOX_PATH} && docker compose logs" || true
run "cat ${DVLBOX_PATH}/log/php-fpm-${PHP_SERVER}/php-fpm.error" || true
run "cat ${DVLBOX_PATH}/log/${HTTPD_SERVER}/defaultlocalhost-error.log" || true
exit 1
diff --git a/.tests/scripts/compose-stop.sh b/.tests/scripts/compose-stop.sh
index 823cc0ff9..29c0a81f1 100755
--- a/.tests/scripts/compose-stop.sh
+++ b/.tests/scripts/compose-stop.sh
@@ -14,7 +14,7 @@ DVLBOX_PATH="$( cd "${SCRIPT_PATH}/../.." && pwd -P )"
# Pre-check
# -------------------------------------------------------------------------------------------------
-if ! command -v docker-compose >/dev/null 2>&1; then
+if ! command -v docker compose >/dev/null 2>&1; then
>&2 echo "Error 'docker-compose' binary not found, but required."
exit 1
fi
@@ -29,19 +29,19 @@ fi
###
# Remove emails
-run "docker-compose exec php truncate -s0 /var/mail/devilbox || true" "1" "${DVLBOX_PATH}"
+run "docker compose exec php truncate -s0 /var/mail/devilbox || true" "1" "${DVLBOX_PATH}"
# Remove PHP logs
-run "docker-compose exec php sh -c \"find /var/log -name 'php-fpm*' -print0 | xargs -n1 -0 rm -f\" || true" "1" "${DVLBOX_PATH}"
+run "docker compose exec php sh -c \"find /var/log -name 'php-fpm*' -print0 | xargs -n1 -0 rm -f\" || true" "1" "${DVLBOX_PATH}"
# Remove HTTP logs
-run "docker-compose exec httpd sh -c \"find /var/log/ -name '*.log' -print0 | xargs -n1 -0 rm -f\" || true" "1" "${DVLBOX_PATH}"
+run "docker compose exec httpd sh -c \"find /var/log/ -name '*.log' -print0 | xargs -n1 -0 rm -f\" || true" "1" "${DVLBOX_PATH}"
###
### Stop and remove container
###
-run "docker-compose stop" "1" "${DVLBOX_PATH}"
-run "docker-compose kill" "1" "${DVLBOX_PATH}"
-run "docker-compose rm -f" "1" "${DVLBOX_PATH}"
+run "docker compose stop" "1" "${DVLBOX_PATH}"
+run "docker compose kill" "1" "${DVLBOX_PATH}"
+run "docker compose rm -f" "1" "${DVLBOX_PATH}"
diff --git a/.tests/scripts/get-modules.sh b/.tests/scripts/get-modules.sh
index 3cef6f536..b997ff91e 100755
--- a/.tests/scripts/get-modules.sh
+++ b/.tests/scripts/get-modules.sh
@@ -14,12 +14,16 @@ DVLBOX_PATH="$( cd "${SCRIPT_PATH}/../.." && pwd -P )"
RETRIES=10
+TEST_REPO="https://github.com/devilbox-community/docker-php-fpm"
# -------------------------------------------------------------------------------------------------
# FUNCTIONS
# -------------------------------------------------------------------------------------------------
-PHP_TAG="$( grep 'devilboxcommunity/php' "${DVLBOX_PATH}/docker-compose.yml" | sed_command 's/^.*-work-//g' )"
+PHP_TAG="$( grep 'devilboxcommunity/php' "${DVLBOX_PATH}/docker-compose.yml" | sed_command -E 's/^.*-work[-]?//g')"
+if [ -z "${PHP_TAG}" ]; then
+ PHP_TAG="$( run "git ls-remote --symref ${TEST_REPO} | head -1 | cut -f1 | sed_command 's!^ref: refs/heads/!!'" "${RETRIES}" )";
+fi
PHP_MOD="$( run "curl -sS 'https://raw.githubusercontent.com/devilbox-community/docker-php-fpm/${PHP_TAG}/doc/php-modules.md'" "${RETRIES}" )";
@@ -52,15 +56,11 @@ get_modules() {
names="$( echo "${names}" | grep -v '^$' )"
# Output comma separated
- echo "${names}" | paste -s -d, -
+ #echo "${names}" | paste -s -d, -
+ echo "${names}" | awk 'ORS=","' | sed 's/,$//' | paste -d, - -
}
-PHP56_BASE="$( get_modules "5.6" "base" )"
-PHP70_BASE="$( get_modules "7.0" "base" )"
-PHP71_BASE="$( get_modules "7.1" "base" )"
-PHP72_BASE="$( get_modules "7.2" "base" )"
-PHP73_BASE="$( get_modules "7.3" "base" )"
PHP74_BASE="$( get_modules "7.4" "base" )"
PHP80_BASE="$( get_modules "8.0" "base" )"
PHP81_BASE="$( get_modules "8.1" "base" )"
@@ -68,11 +68,6 @@ PHP82_BASE="$( get_modules "8.2" "base" )"
PHP83_BASE="$( get_modules "8.3" "base" )"
PHP84_BASE="$( get_modules "8.4" "base" )"
-PHP56_MODS="$( get_modules "5.6" "mods" )"
-PHP70_MODS="$( get_modules "7.0" "mods" )"
-PHP71_MODS="$( get_modules "7.1" "mods" )"
-PHP72_MODS="$( get_modules "7.2" "mods" )"
-PHP73_MODS="$( get_modules "7.3" "mods" )"
PHP74_MODS="$( get_modules "7.4" "mods" )"
PHP80_MODS="$( get_modules "8.0" "mods" )"
PHP81_MODS="$( get_modules "8.1" "mods" )"
@@ -84,21 +79,23 @@ PHP84_MODS="$( get_modules "8.4" "mods" )"
###
### Todo: add ioncube
###
-MODS="$( echo "${PHP56_MODS}, ${PHP70_MODS}, ${PHP71_MODS}, ${PHP72_MODS}, ${PHP73_MODS}, ${PHP74_MODS}, ${PHP80_MODS}, ${PHP81_MODS}, ${PHP82_MODS}, ${PHP83_MODS}, ${PHP84_MODS}" | sed 's/,/\n/g' | sed_command -e 's/^\s*//g' -e 's/\s*$//g' | sort -uf )"
+#MODS="$( echo "${PHP74_MODS}, ${PHP80_MODS}, ${PHP81_MODS}, ${PHP82_MODS}, ${PHP83_MODS}, ${PHP84_MODS}" | sed_command 's/,/\n/g' | sed_command -e 's/^\s*//g' -e 's/\s*$//g' | sort -uf )"
+MODS_RAW="${PHP74_MODS},${PHP80_MODS},${PHP81_MODS},${PHP82_MODS},${PHP83_MODS},${PHP84_MODS}"
+MODS="$(echo "$MODS_RAW" | tr ',' '\n' | grep -v '^$' | sort -uf)"
###
### Get disabled modules
###
-DISABLED=",blackfire,ioncube,phalcon,psr,xhprof,$( grep -E '^PHP_MODULES_DISABLE=' "${DVLBOX_PATH}/env-example" | sed 's/.*=//g' ),"
+DISABLED=",blackfire,ioncube,sourceguardian,phalcon,psr,xhprof,$( grep -E '^PHP_MODULES_DISABLE=' "${DVLBOX_PATH}/env-example" | sed_command 's/.*=//g' ),"
#echo $DISABLED
B="✔" # Enabled base modules (cannot be disabled)
E="🗸" # Enabled mods modules (can be disabled)
D="d" # Disabled modules (can be enabled)
U=" " # Unavailable
-echo "| Modules | PHP 5.6 | PHP 7.0 | PHP 7.1 | PHP 7.2 | PHP 7.3 | PHP 7.4 | PHP 8.0 | PHP 8.1 | PHP 8.2 | PHP 8.3 | PHP 8.4 |"
-echo "|-------------------------------|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|"
+echo "| Modules | PHP 7.4 | PHP 8.0 | PHP 8.1 | PHP 8.2 | PHP 8.3 | PHP 8.4 |"
+echo "|-------------------------------|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|"
echo "${MODS}" | while read -r line; do
# Ignore modules
if [ "${line}" = "Core" ]; then
@@ -108,87 +105,12 @@ echo "${MODS}" | while read -r line; do
# Print current module
printf "| %-30s%s" "${line}" "|"
- # ---------- PHP 5.6 ----------#
- if echo ",${PHP56_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- if echo "${DISABLED}" | grep -Eq ",${line},"; then
- printf " %s |" "${D}" # Currently disabled
- else
- if echo ",${PHP56_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- printf " %s |" "${B}" # Enabled, but cannot be disabled
- else
- printf " %s |" "${E}" # Enabled, can be disabled
- fi
- fi
- else
- printf " %s |" "${U}" # Not available
- fi
-
- # ---------- PHP 7.0 ----------#
- if echo ",${PHP70_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- if echo "${DISABLED}" | grep -Eq ",${line},"; then
- printf " %s |" "${D}" # Currently disabled
- else
- if echo ",${PHP70_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- printf " %s |" "${B}" # Enabled, but cannot be disabled
- else
- printf " %s |" "${E}" # Enabled, can be disabled
- fi
- fi
- else
- printf " %s |" "${U}" # Not available
- fi
-
- # ---------- PHP 7.1 ----------#
- if echo ",${PHP71_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- if echo "${DISABLED}" | grep -Eq ",${line},"; then
- printf " %s |" "${D}" # Currently disabled
- else
- if echo ",${PHP71_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- printf " %s |" "${B}" # Enabled, but cannot be disabled
- else
- printf " %s |" "${E}" # Enabled, can be disabled
- fi
- fi
- else
- printf " %s |" "${U}" # Not available
- fi
-
- # ---------- PHP 7.2 ----------#
- if echo ",${PHP72_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- if echo "${DISABLED}" | grep -Eq ",${line},"; then
- printf " %s |" "${D}" # Currently disabled
- else
- if echo ",${PHP72_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- printf " %s |" "${B}" # Enabled, but cannot be disabled
- else
- printf " %s |" "${E}" # Enabled, can be disabled
- fi
- fi
- else
- printf " %s |" "${U}" # Not available
- fi
-
- # ---------- PHP 7.3 ----------#
- if echo ",${PHP73_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- if echo "${DISABLED}" | grep -Eq ",${line},"; then
- printf " %s |" "${D}" # Currently disabled
- else
- if echo ",${PHP73_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
- printf " %s |" "${B}" # Enabled, but cannot be disabled
- else
- printf " %s |" "${E}" # Enabled, can be disabled
- fi
- fi
- else
- printf " %s |" "${U}" # Not available
- fi
-
# ---------- PHP 7.4 ----------#
- if echo ",${PHP74_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP74_MODS}," | grep -Eq ",${line},"; then
if echo "${DISABLED}" | grep -Eq ",${line},"; then
printf " %s |" "${D}" # Currently disabled
else
- if echo ",${PHP74_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP74_BASE}," | grep -Eq ",${line},"; then
printf " %s |" "${B}" # Enabled, but cannot be disabled
else
printf " %s |" "${E}" # Enabled, can be disabled
@@ -199,11 +121,11 @@ echo "${MODS}" | while read -r line; do
fi
# ---------- PHP 8.0 ----------#
- if echo ",${PHP80_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP80_MODS}," | grep -Eq ",${line},"; then
if echo "${DISABLED}" | grep -Eq ",${line},"; then
printf " %s |" "${D}" # Currently disabled
else
- if echo ",${PHP80_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP80_BASE}," | grep -Eq ",${line},"; then
printf " %s |" "${B}" # Enabled, but cannot be disabled
else
printf " %s |" "${E}" # Enabled, can be disabled
@@ -214,11 +136,11 @@ echo "${MODS}" | while read -r line; do
fi
# ---------- PHP 8.1 ----------#
- if echo ",${PHP81_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP81_MODS}," | grep -Eq ",${line},"; then
if echo "${DISABLED}" | grep -Eq ",${line},"; then
printf " %s |" "${D}" # Currently disabled
else
- if echo ",${PHP81_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP81_BASE}," | grep -Eq ",${line},"; then
printf " %s |" "${B}" # Enabled, but cannot be disabled
else
printf " %s |" "${E}" # Enabled, can be disabled
@@ -229,11 +151,11 @@ echo "${MODS}" | while read -r line; do
fi
# ---------- PHP 8.2 ----------#
- if echo ",${PHP82_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP82_MODS}," | grep -Eq ",${line},"; then
if echo "${DISABLED}" | grep -Eq ",${line},"; then
printf " %s |" "${D}" # Currently disabled
else
- if echo ",${PHP82_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP82_BASE}," | grep -Eq ",${line},"; then
printf " %s |" "${B}" # Enabled, but cannot be disabled
else
printf " %s |" "${E}" # Enabled, can be disabled
@@ -244,11 +166,11 @@ echo "${MODS}" | while read -r line; do
fi
# ---------- PHP 8.3 ----------#
- if echo ",${PHP83_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP83_MODS}," | grep -Eq ",${line},"; then
if echo "${DISABLED}" | grep -Eq ",${line},"; then
printf " %s |" "${D}" # Currently disabled
else
- if echo ",${PHP83_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP83_BASE}," | grep -Eq ",${line},"; then
printf " %s |" "${B}" # Enabled, but cannot be disabled
else
printf " %s |" "${E}" # Enabled, can be disabled
@@ -259,11 +181,11 @@ echo "${MODS}" | while read -r line; do
fi
# ---------- PHP 8.4 ----------#
- if echo ",${PHP84_MODS}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP84_MODS}," | grep -Eq ",${line},"; then
if echo "${DISABLED}" | grep -Eq ",${line},"; then
printf " %s |" "${D}" # Currently disabled
else
- if echo ",${PHP84_BASE}," | sed_command 's/,\s/,/g' | grep -Eq ",${line},"; then
+ if echo ",${PHP84_BASE}," | grep -Eq ",${line},"; then
printf " %s |" "${B}" # Enabled, but cannot be disabled
else
printf " %s |" "${E}" # Enabled, can be disabled
diff --git a/.tests/tests/autostart-examples.sh b/.tests/tests/autostart-examples.sh
index bee761665..1d2ab086d 100755
--- a/.tests/tests/autostart-examples.sh
+++ b/.tests/tests/autostart-examples.sh
@@ -41,7 +41,7 @@ fi
###
### Get autostart files
###
-FILES="$( run "docker-compose exec -T --user devilbox php bash -c 'find /startup.1.d/ -name \"*.sh-example\"'" "${RETRIES}" "${DVLBOX_PATH}" "0" )"
+FILES="$( run "docker compose exec -T --user devilbox php bash -c 'find /startup.1.d/ -name \"*.sh-example\"'" "${RETRIES}" "${DVLBOX_PATH}" "0" )"
echo
echo "#--------------------------------------------------------------------------------"
@@ -50,14 +50,14 @@ echo "#-------------------------------------------------------------------------
echo
for file in ${FILES}; do
- run "docker-compose exec -T php bash ${file} 'ACCEPT_EULA=1'" "${RETRIES}" "${DVLBOX_PATH}"
+ run "docker compose exec -T php bash ${file} 'ACCEPT_EULA=1'" "${RETRIES}" "${DVLBOX_PATH}"
done
###
### Get autostart files
###
-FILES="$( run "docker-compose exec -T --user devilbox php bash -c 'find /startup.2.d/ -name \"*.sh-example\"'" "${RETRIES}" "${DVLBOX_PATH}" "0" )"
+FILES="$( run "docker compose exec -T --user devilbox php bash -c 'find /startup.2.d/ -name \"*.sh-example\"'" "${RETRIES}" "${DVLBOX_PATH}" "0" )"
echo
echo "#--------------------------------------------------------------------------------"
@@ -66,5 +66,5 @@ echo "#-------------------------------------------------------------------------
echo
for file in ${FILES}; do
- run "docker-compose exec -T php bash ${file}" "${RETRIES}" "${DVLBOX_PATH}"
+ run "docker compose exec -T php bash ${file}" "${RETRIES}" "${DVLBOX_PATH}"
done
diff --git a/.tests/tests/container-mysql.sh b/.tests/tests/container-mysql.sh
index 72b802e6c..3302a6f95 100755
--- a/.tests/tests/container-mysql.sh
+++ b/.tests/tests/container-mysql.sh
@@ -52,16 +52,16 @@ DATALEN=200 # Length of the data per value
# Install pipe viewer
-run "docker-compose exec --user root -T php bash -c 'apt update && apt install -y pv'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user root -T php bash -c 'apt update && apt install -y pv'" "${RETRIES}" "${DVLBOX_PATH}"
# Drop database
-run "docker-compose exec --user devilbox -T php bash -c 'mysql --host=mysql --user=root --password='\\''${MYSQL_ROOT_PASSWORD}'\\'' -e '\\''DROP DATABASE IF EXISTS ${DB_NAME};'\\'''" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'mysql --host=mysql --user=root --password='\\''${MYSQL_ROOT_PASSWORD}'\\'' -e '\\''DROP DATABASE IF EXISTS ${DB_NAME};'\\'''" "${RETRIES}" "${DVLBOX_PATH}"
# Delete mysql.sql file
-run "docker-compose exec --user devilbox -T php bash -c 'rm -f /home/devilbox/mysql.sql'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'rm -f /home/devilbox/mysql.sql'" "${RETRIES}" "${DVLBOX_PATH}"
# Create SQL File
-run "docker-compose exec --user devilbox -T php bash -c '
+run "docker compose exec --user devilbox -T php bash -c '
(
echo \"CREATE DATABASE ${DB_NAME} COLLATE '\\''utf8mb4_bin'\\'';\";
echo \"USE ${DB_NAME};\";
@@ -87,13 +87,13 @@ run "docker-compose exec --user devilbox -T php bash -c '
) > /home/devilbox/mysql.sql
'" "${RETRIES}" "${DVLBOX_PATH}"
printf "\\n"
-run "docker-compose exec --user devilbox -T php bash -c 'ls -lap /home/devilbox/mysql.sql'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'ls -lap /home/devilbox/mysql.sql'" "${RETRIES}" "${DVLBOX_PATH}"
# Import SQL file
-run "docker-compose exec --user devilbox -T php bash -c 'pv -f -i 1 -p -t -e /home/devilbox/mysql.sql | mysql --host=mysql --user=root --password='\\''${MYSQL_ROOT_PASSWORD}'\\'''" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'pv -f -i 1 -p -t -e /home/devilbox/mysql.sql | mysql --host=mysql --user=root --password='\\''${MYSQL_ROOT_PASSWORD}'\\'''" "${RETRIES}" "${DVLBOX_PATH}"
# Compare inserted rows
-COUNT="$( run "docker-compose exec --user devilbox -T php bash -c 'mysql --host=mysql --user=root --password='\\''${MYSQL_ROOT_PASSWORD}'\\'' -e '\\''SELECT COUNT(*) AS cnt FROM ${DB_NAME}.${TBL_NAME};'\\''' | grep -Ei '[0-9]+'" "1" "${DVLBOX_PATH}" )"
+COUNT="$( run "docker compose exec --user devilbox -T php bash -c 'mysql --host=mysql --user=root --password='\\''${MYSQL_ROOT_PASSWORD}'\\'' -e '\\''SELECT COUNT(*) AS cnt FROM ${DB_NAME}.${TBL_NAME};'\\''' | grep -Ei '[0-9]+'" "1" "${DVLBOX_PATH}" )"
COUNT="$( echo "${COUNT}" | grep -Eo '[0-9]+' )"
if [ "${COUNT}" -ne "$(( ROWS * GROUPED ))" ]; then
diff --git a/.tests/tests/framework-cakephp-php8.sh b/.tests/tests/framework-cakephp-php8.sh
index d26ad4725..6951f5b0e 100755
--- a/.tests/tests/framework-cakephp-php8.sh
+++ b/.tests/tests/framework-cakephp-php8.sh
@@ -14,7 +14,7 @@ DVLBOX_PATH="$( cd "${SCRIPT_PATH}/../.." && pwd -P )"
RETRIES=10
# see framework-cakephp.sh for PHP <8 tests
-DISABLED_VERSIONS=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4")
+DISABLED_VERSIONS=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.4")
PHP_VERSION="$( get_php_version "${DVLBOX_PATH}" )"
@@ -58,38 +58,38 @@ create_vhost_dir "${VHOST}"
# Setup CakePHP project
-run "docker-compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; composer create-project --no-interaction --prefer-dist cakephp/app:~${CAKE_PHP_VERSION} cakephp'" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; ln -sf cakephp/webroot htdocs'" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php mysql -u root -h mysql --password=\"${MYSQL_ROOT_PASSWORD}\" -e \"DROP DATABASE IF EXISTS my_cake; CREATE DATABASE my_cake;\"" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; composer create-project --no-interaction --prefer-dist cakephp/app:~${CAKE_PHP_VERSION} cakephp'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; ln -sf cakephp/webroot htdocs'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mysql -u root -h mysql --password=\"${MYSQL_ROOT_PASSWORD}\" -e \"DROP DATABASE IF EXISTS my_cake; CREATE DATABASE my_cake;\"" "${RETRIES}" "${DVLBOX_PATH}"
# Configure CakePHP database settings
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/'host' =>.*/'host' => 'mysql',/g\" /shared/httpd/${VHOST}/cakephp/config/app_local.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/'username' =>.*/'username' => 'root',/g\" /shared/httpd/${VHOST}/cakephp/config/app_local.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/'password' =>.*/'password' => '${MYSQL_ROOT_PASSWORD}',/g\" /shared/httpd/${VHOST}/cakephp/config/app_local.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/'database' =>.*/'database' => 'my_cake',/g\" /shared/httpd/${VHOST}/cakephp/config/app_local.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/'host' =>.*/'host' => 'mysql',/g\" /shared/httpd/${VHOST}/cakephp/config/app_local.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/'username' =>.*/'username' => 'root',/g\" /shared/httpd/${VHOST}/cakephp/config/app_local.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/'password' =>.*/'password' => '${MYSQL_ROOT_PASSWORD}',/g\" /shared/httpd/${VHOST}/cakephp/config/app_local.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/'database' =>.*/'database' => 'my_cake',/g\" /shared/httpd/${VHOST}/cakephp/config/app_local.php" "${RETRIES}" "${DVLBOX_PATH}"
# Test CakePHP
ERROR=0
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'mbstring'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'mbstring'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'openssl'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'openssl'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'intl'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'intl'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'tmp directory'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'tmp directory'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'logs directory'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'logs directory'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'connect to the database'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'connect to the database'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
if [ "${ERROR}" = "1" ]; then
- run "docker-compose exec --user devilbox -T php curl 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
exit 1
fi
diff --git a/.tests/tests/framework-cakephp.sh b/.tests/tests/framework-cakephp.sh
index 34b2e66e2..f8a451640 100755
--- a/.tests/tests/framework-cakephp.sh
+++ b/.tests/tests/framework-cakephp.sh
@@ -14,7 +14,7 @@ DVLBOX_PATH="$( cd "${SCRIPT_PATH}/../.." && pwd -P )"
RETRIES=10
# see framework-cakephp-php8.sh for PHP 8+ tests
-DISABLED_VERSIONS=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0" "8.1" "8.2" "8.3", "8.4")
+DISABLED_VERSIONS=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0" "8.1" "8.2" "8.3" "8.4")
PHP_VERSION="$( get_php_version "${DVLBOX_PATH}" )"
@@ -61,38 +61,38 @@ create_vhost_dir "${VHOST}"
# Setup CakePHP project
-run "docker-compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; composer create-project --no-interaction --prefer-dist cakephp/app cakephp ${CAKE_PHP_VERSION}'" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; ln -sf cakephp/webroot htdocs'" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php mysql -u root -h mysql --password=\"${MYSQL_ROOT_PASSWORD}\" -e \"DROP DATABASE IF EXISTS my_cake; CREATE DATABASE my_cake;\"" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; composer create-project --no-interaction --prefer-dist cakephp/app cakephp ${CAKE_PHP_VERSION}'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; ln -sf cakephp/webroot htdocs'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mysql -u root -h mysql --password=\"${MYSQL_ROOT_PASSWORD}\" -e \"DROP DATABASE IF EXISTS my_cake; CREATE DATABASE my_cake;\"" "${RETRIES}" "${DVLBOX_PATH}"
# Configure CakePHP database settings
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/'host' =>.*/'host' => 'mysql',/g\" /shared/httpd/${VHOST}/cakephp/config/app.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/'username' =>.*/'username' => 'root',/g\" /shared/httpd/${VHOST}/cakephp/config/app.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/'password' =>.*/'password' => '${MYSQL_ROOT_PASSWORD}',/g\" /shared/httpd/${VHOST}/cakephp/config/app.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/'database' =>.*/'database' => 'my_cake',/g\" /shared/httpd/${VHOST}/cakephp/config/app.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/'host' =>.*/'host' => 'mysql',/g\" /shared/httpd/${VHOST}/cakephp/config/app.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/'username' =>.*/'username' => 'root',/g\" /shared/httpd/${VHOST}/cakephp/config/app.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/'password' =>.*/'password' => '${MYSQL_ROOT_PASSWORD}',/g\" /shared/httpd/${VHOST}/cakephp/config/app.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/'database' =>.*/'database' => 'my_cake',/g\" /shared/httpd/${VHOST}/cakephp/config/app.php" "${RETRIES}" "${DVLBOX_PATH}"
# Test CakePHP
ERROR=0
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'mbstring'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'mbstring'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'openssl'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'openssl'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'intl'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'intl'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'tmp directory'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'tmp directory'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'logs directory'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'logs directory'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'connect to the database'" "${RETRIES}" "${DVLBOX_PATH}"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep '\"bullet success\"' | grep 'connect to the database'" "${RETRIES}" "${DVLBOX_PATH}"; then
ERROR=1
fi
if [ "${ERROR}" = "1" ]; then
- run "docker-compose exec --user devilbox -T php curl 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
exit 1
fi
diff --git a/.tests/tests/framework-drupal.sh b/.tests/tests/framework-drupal.sh
index 42ed264e4..363cfdab2 100755
--- a/.tests/tests/framework-drupal.sh
+++ b/.tests/tests/framework-drupal.sh
@@ -13,7 +13,7 @@ DVLBOX_PATH="$( cd "${SCRIPT_PATH}/../.." && pwd -P )"
. "${SCRIPT_PATH}/../scripts/.lib.sh"
RETRIES=10
-DISABLED_VERSIONS=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0" "8.1" "8.2" "8.3")
+DISABLED_VERSIONS=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0" "8.1" "8.2" "8.3" "8.4")
DISABLED_MYSQL_VERSIONS=("mysql-8.0" "percona-8.0")
@@ -41,15 +41,15 @@ if [[ ${DISABLED_MYSQL_VERSIONS[*]} =~ ${MYSQL_VERSION} ]]; then
fi
DRUSH=
-if run "docker-compose exec --user devilbox -T php bash -c 'command -v drush'" "1" "${DVLBOX_PATH}"; then
+if run "docker compose exec --user devilbox -T php bash -c 'command -v drush'" "1" "${DVLBOX_PATH}"; then
DRUSH=drush
-elif run "docker-compose exec --user devilbox -T php bash -c 'command -v drush10'" "1" "${DVLBOX_PATH}"; then
+elif run "docker compose exec --user devilbox -T php bash -c 'command -v drush10'" "1" "${DVLBOX_PATH}"; then
DRUSH=drush10
-elif run "docker-compose exec --user devilbox -T php bash -c 'command -v drush9'" "1" "${DVLBOX_PATH}"; then
+elif run "docker compose exec --user devilbox -T php bash -c 'command -v drush9'" "1" "${DVLBOX_PATH}"; then
DRUSH=drush9
-elif run "docker-compose exec --user devilbox -T php bash -c 'command -v drush8'" "1" "${DVLBOX_PATH}"; then
+elif run "docker compose exec --user devilbox -T php bash -c 'command -v drush8'" "1" "${DVLBOX_PATH}"; then
DRUSH=drush8
-elif run "docker-compose exec --user devilbox -T php bash -c 'command -v drush7'" "1" "${DVLBOX_PATH}"; then
+elif run "docker compose exec --user devilbox -T php bash -c 'command -v drush7'" "1" "${DVLBOX_PATH}"; then
DRUSH=drush7
fi
if [ -z "${DRUSH}" ]; then
@@ -74,15 +74,15 @@ create_vhost_dir "${VHOST}"
# Setup Drupal project
-run "docker-compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; composer-1 create-project --no-interaction --prefer-dist drupal-composer/drupal-project drupal 8.x-dev'" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; ln -sf drupal/web htdocs'" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php mysql -u root -h mysql --password=\"${MYSQL_ROOT_PASSWORD}\" -e \"DROP DATABASE IF EXISTS my_drupal; CREATE DATABASE my_drupal;\"" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; composer-1 create-project --no-interaction --prefer-dist drupal-composer/drupal-project drupal 8.x-dev'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}; ln -sf drupal/web htdocs'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mysql -u root -h mysql --password=\"${MYSQL_ROOT_PASSWORD}\" -e \"DROP DATABASE IF EXISTS my_drupal; CREATE DATABASE my_drupal;\"" "${RETRIES}" "${DVLBOX_PATH}"
# Configure Drupal
-run "docker-compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}/htdocs/; ${DRUSH} site-install standard --db-url='mysql://root:${MYSQL_ROOT_PASSWORD}@mysql/my_drupal' --site-name=Example -y'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${VHOST}/htdocs/; ${DRUSH} site-install standard --db-url='mysql://root:${MYSQL_ROOT_PASSWORD}@mysql/my_drupal' --site-name=Example -y'" "${RETRIES}" "${DVLBOX_PATH}"
# Test Drupal
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep 'Welcome to Example'" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec --user devilbox -T php curl 'http://${VHOST}.${TLD_SUFFIX}' || true"
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep 'Welcome to Example'" "${RETRIES}" "${DVLBOX_PATH}"; then
+ run "docker compose exec --user devilbox -T php curl 'http://${VHOST}.${TLD_SUFFIX}' || true"
exit 1
fi
diff --git a/.tests/tests/framework-wordpress.sh b/.tests/tests/framework-wordpress.sh
index b1ae63f98..572cf858e 100755
--- a/.tests/tests/framework-wordpress.sh
+++ b/.tests/tests/framework-wordpress.sh
@@ -63,54 +63,54 @@ else
WP_BRANCH="$(git ls-remote --tags https://github.com/WordPress/WordPress | sed 's/^.*tags\///g' | grep -E '^[.0-9]+$' | tr '-' '~' | sort -V | tail -1)"
fi
# Download Wordpress
-run "docker-compose exec --user devilbox -T php bash -c ' \
+run "docker compose exec --user devilbox -T php bash -c ' \
git clone --depth=1 --single-branch --branch=${WP_BRANCH} https://github.com/WordPress/WordPress /shared/httpd/${VHOST}/wordpress \
&& ln -sf wordpress /shared/httpd/${VHOST}/htdocs'" \
"${RETRIES}" "${DVLBOX_PATH}"
# Switch to an earlier Wordpress version for older PHP versions
if [ "${PHP_VERSION}" = "5.6" ]; then
- run "docker-compose exec --user devilbox -T php bash -c ' \
+ run "docker compose exec --user devilbox -T php bash -c ' \
cd /shared/httpd/${VHOST}/wordpress \
&& git checkout 6.2.4'" \
"${RETRIES}" "${DVLBOX_PATH}"
# Checkout latest git tag
else
- run "docker-compose exec --user devilbox -T php bash -c ' \
+ run "docker compose exec --user devilbox -T php bash -c ' \
cd /shared/httpd/${VHOST}/wordpress \
&& git checkout \"\$(git tag | sort -V | tail -1)\"'" \
"${RETRIES}" "${DVLBOX_PATH}"
fi
# Setup Database
-run "docker-compose exec --user devilbox -T php mysql -u root -h mysql --password=\"${MYSQL_ROOT_PASSWORD}\" -e \"DROP DATABASE IF EXISTS ${DB_NAME}; CREATE DATABASE ${DB_NAME};\"" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mysql -u root -h mysql --password=\"${MYSQL_ROOT_PASSWORD}\" -e \"DROP DATABASE IF EXISTS ${DB_NAME}; CREATE DATABASE ${DB_NAME};\"" "${RETRIES}" "${DVLBOX_PATH}"
# Configure Wordpress database settings
-run "docker-compose exec --user devilbox -T php bash -c \"perl -pe 's/\\r$//' < /shared/httpd/${VHOST}/wordpress/wp-config-sample.php > /shared/httpd/${VHOST}/wordpress/wp-config.php\"" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'DB_NAME.*/define('DB_NAME', '${DB_NAME}');/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'DB_USER.*/define('DB_USER', 'root');/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'DB_PASSWORD.*/define('DB_PASSWORD', '${MYSQL_ROOT_PASSWORD}');/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'DB_HOST.*/define('DB_HOST', 'mysql');/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'WP_DEBUG.*/define('WP_DEBUG', true);/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php php -l /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c \"perl -pe 's/\\r$//' < /shared/httpd/${VHOST}/wordpress/wp-config-sample.php > /shared/httpd/${VHOST}/wordpress/wp-config.php\"" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'DB_NAME.*/define('DB_NAME', '${DB_NAME}');/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'DB_USER.*/define('DB_USER', 'root');/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'DB_PASSWORD.*/define('DB_PASSWORD', '${MYSQL_ROOT_PASSWORD}');/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'DB_HOST.*/define('DB_HOST', 'mysql');/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php sed -i\"\" \"s/define(\\s*'WP_DEBUG.*/define('WP_DEBUG', true);/g\" /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php php -l /shared/httpd/${VHOST}/wordpress/wp-config.php" "${RETRIES}" "${DVLBOX_PATH}"
# Install Wordpress
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail -L -XPOST -c cookie.txt -b cookie.txt \
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail -L -XPOST -c cookie.txt -b cookie.txt \
'http://${VHOST}.${TLD_SUFFIX}/wp-admin/install.php?step=1'\
--data 'language=1' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec --user devilbox -T php curl -sS --fail -L -XPOST -c cookie.txt -b cookie.txt \
+ run "docker compose exec --user devilbox -T php curl -sS --fail -L -XPOST -c cookie.txt -b cookie.txt \
'http://${VHOST}.${TLD_SUFFIX}/wp-admin/install.php?step=1'\
--data 'language=1' >/dev/null" "1" "${DVLBOX_PATH}" || true
- run "docker-compose exec --user devilbox -T php curl -sS --fail -L -I \
+ run "docker compose exec --user devilbox -T php curl -sS --fail -L -I \
'http://${VHOST}.${TLD_SUFFIX}/wp-admin/install.php?step=1'" "1" "${DVLBOX_PATH}" || true
- run "docker-compose exec --user devilbox -T php curl -sS --fail -L \
+ run "docker compose exec --user devilbox -T php curl -sS --fail -L \
'http://${VHOST}.${TLD_SUFFIX}/'" "1" "${DVLBOX_PATH}" || true
- run "docker-compose logs php" || true
- run "docker-compose logs httpd" || true
+ run "docker compose logs php" || true
+ run "docker compose logs httpd" || true
exit 1
fi
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail -L -XPOST -c cookie.txt -b cookie.txt \
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail -L -XPOST -c cookie.txt -b cookie.txt \
'http://${VHOST}.${TLD_SUFFIX}/wp-admin/install.php?step=2' \
--data 'weblog_title=${PROJECT_NAME}' \
--data 'user_name=admin' \
@@ -120,7 +120,7 @@ if ! run "docker-compose exec --user devilbox -T php curl -sS --fail -L -XPOST -
--data 'admin_email=test%40test.com' \
--data 'blog_public=0' \
--data 'Submit=Install+WordPress&language=' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec --user devilbox -T php curl -sS --fail -L -XPOST -c cookie.txt -b cookie.txt \
+ run "docker compose exec --user devilbox -T php curl -sS --fail -L -XPOST -c cookie.txt -b cookie.txt \
'http://${VHOST}.${TLD_SUFFIX}/wp-admin/install.php?step=2' \
--data 'weblog_title=${PROJECT_NAME}' \
--data 'user_name=admin' \
@@ -131,14 +131,14 @@ if ! run "docker-compose exec --user devilbox -T php curl -sS --fail -L -XPOST -
--data 'blog_public=0' \
--data 'Submit=Install+WordPress' \
--data 'language='" "1" "${DVLBOX_PATH}" || true
- run "docker-compose logs php" || true
- run "docker-compose logs httpd" || true
+ run "docker compose logs php" || true
+ run "docker compose logs httpd" || true
exit 1
fi
# Test Wordpress
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail -L 'http://${VHOST}.${TLD_SUFFIX}/' | grep '${PROJECT_NAME}' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec --user devilbox -T php curl -sS -L 'http://${VHOST}.${TLD_SUFFIX}/'" "1" "${DVLBOX_PATH}" || true
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail -L 'http://${VHOST}.${TLD_SUFFIX}/' | grep '${PROJECT_NAME}' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
+ run "docker compose exec --user devilbox -T php curl -sS -L 'http://${VHOST}.${TLD_SUFFIX}/'" "1" "${DVLBOX_PATH}" || true
exit 1
fi
if ! run "curl -sS --fail -L --header 'host: ${VHOST}.${TLD_SUFFIX}' 'http://localhost:${HOST_PORT_HTTPD}/' | grep '${PROJECT_NAME}' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
@@ -146,7 +146,7 @@ if ! run "curl -sS --fail -L --header 'host: ${VHOST}.${TLD_SUFFIX}' 'http://loc
exit 1
fi
# Check for Exceptions, Errors or Warnings
-if ! run_fail "docker-compose exec --user devilbox -T php curl -sS --fail -L 'http://${VHOST}.${TLD_SUFFIX}/' | grep -Ei 'fatal|error|warn' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec --user devilbox -T php curl -sS -L 'http://${VHOST}.${TLD_SUFFIX}/' | grep -Ei 'fatal|error|warn'" "1" "${DVLBOX_PATH}"
+if ! run_fail "docker compose exec --user devilbox -T php curl -sS --fail -L 'http://${VHOST}.${TLD_SUFFIX}/' | grep -Ei 'fatal|error|warn' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
+ run "docker compose exec --user devilbox -T php curl -sS -L 'http://${VHOST}.${TLD_SUFFIX}/' | grep -Ei 'fatal|error|warn'" "1" "${DVLBOX_PATH}"
exit 1
fi
diff --git a/.tests/tests/intranet-email.sh b/.tests/tests/intranet-email.sh
index f03613ca9..6f1ddbf94 100755
--- a/.tests/tests/intranet-email.sh
+++ b/.tests/tests/intranet-email.sh
@@ -63,7 +63,7 @@ MY_MESS="testing-ci-message"
# Empty mails first
-run "docker-compose exec --user devilbox -T php bash -c '> /var/mail/devilbox'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c '> /var/mail/devilbox'" "${RETRIES}" "${DVLBOX_PATH}"
# Send a new mail
run "curl -sS --fail -XPOST 'http://localhost:${HOST_PORT_HTTPD}/mail.php' -d 'email=${MY_MAIL}&subject=${MY_SUBJ}&message=${MY_MESS}'" "${RETRIES}"
diff --git a/.tests/tests/intranet-vhost.sh b/.tests/tests/intranet-vhost.sh
index 0bedc95f3..86c5c90b3 100755
--- a/.tests/tests/intranet-vhost.sh
+++ b/.tests/tests/intranet-vhost.sh
@@ -66,9 +66,9 @@ VHOST=test-intranet-vhost
###
### Create vhost directory
###
-run "docker-compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
-run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
@@ -101,7 +101,7 @@ fi
###
### Vhost shows success with htdocs/ dir created
###
-run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
printf "[TEST] vhost shows no htdocs dir error if dir is present"
if run "curl -sS --fail 'http://localhost:${HOST_PORT_HTTPD}/_ajax_callback.php?vhost=${VHOST}' | tac | tac | grep -E 'error|${VHOST}' >/dev/null" "1" "" "0"; then
printf "\\r[FAIL] vhost shows no htdocs dir error if dir is present\\n"
@@ -154,7 +154,7 @@ fi
###
### vhost-gen config link should appear
###
-#run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
+#run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
#run "cp ${DVLBOX_PATH}/cfg/vhost-gen/apache24.yml-example-vhost ${SCRIPT_PATH}/../www/${VHOST}/${HTTPD_TEMPLATE_DIR}/apache24.yml" "${RETRIES}"
#run "cp ${DVLBOX_PATH}/cfg/vhost-gen/nginx.yml-example-vhost ${SCRIPT_PATH}/../www/${VHOST}/${HTTPD_TEMPLATE_DIR}/nginx.yml" "${RETRIES}"
#
@@ -200,7 +200,7 @@ fi
###
### Vhost disappears after removing its dir
###
-#run "docker-compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
+#run "docker compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
#run "sleep 4"
#
#printf "[TEST] vhost disappears after removing its dir"
diff --git a/.tests/tests/modules-curl-vhosts.sh b/.tests/tests/modules-curl-vhosts.sh
index 4260fcd80..417aad50d 100755
--- a/.tests/tests/modules-curl-vhosts.sh
+++ b/.tests/tests/modules-curl-vhosts.sh
@@ -116,16 +116,16 @@ echo
for file in ${FILES}; do
name="${file#./}"
- if ! run "docker-compose exec -T php curl -sS --fail -o /dev/null -I -w '%{http_code}' 'http://${VHOST}.${TLD_SUFFIX}/${name}' | tac | tac | grep -E '200'" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec -T php curl -sS -o /dev/null -I -w '%{http_code}' 'http://${VHOST}.${TLD_SUFFIX}/${name}'" "1" "${DVLBOX_PATH}"
+ if ! run "docker compose exec -T php curl -sS --fail -o /dev/null -I -w '%{http_code}' 'http://${VHOST}.${TLD_SUFFIX}/${name}' | tac | tac | grep -E '200'" "${RETRIES}" "${DVLBOX_PATH}"; then
+ run "docker compose exec -T php curl -sS -o /dev/null -I -w '%{http_code}' 'http://${VHOST}.${TLD_SUFFIX}/${name}'" "1" "${DVLBOX_PATH}"
ERROR=1
fi
- if ! run "docker-compose exec -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/${name}' | tac | tac | grep -E '^(OK|SKIP)$'" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/${name}'" "1" "${DVLBOX_PATH}"
+ if ! run "docker compose exec -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/${name}' | tac | tac | grep -E '^(OK|SKIP)$'" "${RETRIES}" "${DVLBOX_PATH}"; then
+ run "docker compose exec -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/${name}'" "1" "${DVLBOX_PATH}"
ERROR=1
fi
- if ! run_fail "docker-compose exec -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/${name}' 2>&1 | tac | tac | grep -Ei 'fatal|except|err|war|notice' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/${name}'" "1" "${DVLBOX_PATH}"
+ if ! run_fail "docker compose exec -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/${name}' 2>&1 | tac | tac | grep -Ei 'fatal|except|err|war|notice' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
+ run "docker compose exec -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/${name}'" "1" "${DVLBOX_PATH}"
ERROR=1
fi
done
diff --git a/.tests/tests/modules-php-vhosts.sh b/.tests/tests/modules-php-vhosts.sh
index 8642faaeb..0ea7eedb5 100755
--- a/.tests/tests/modules-php-vhosts.sh
+++ b/.tests/tests/modules-php-vhosts.sh
@@ -73,12 +73,12 @@ FILES="$( cd "${TESTS}" && find . -name '*.php' | sort )"
for file in ${FILES}; do
name="${file#./}"
- if ! run "docker-compose exec -T --user devilbox php php /shared/httpd/${VHOST}/htdocs/${name} | grep -E '^(OK|SKIP)$'" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec -T --user devilbox php php /shared/httpd/${VHOST}/htdocs/${name} || true" "1" "${DVLBOX_PATH}"
+ if ! run "docker compose exec -T --user devilbox php php /shared/httpd/${VHOST}/htdocs/${name} | grep -E '^(OK|SKIP)$'" "${RETRIES}" "${DVLBOX_PATH}"; then
+ run "docker compose exec -T --user devilbox php php /shared/httpd/${VHOST}/htdocs/${name} || true" "1" "${DVLBOX_PATH}"
ERROR=1
fi
- if ! run_fail "docker-compose exec -T --user devilbox php php /shared/httpd/${VHOST}/htdocs/${name} 2>&1 | grep -Ei 'fatal|except|err|warn|notice' > /dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
- run "docker-compose exec -T --user devilbox php php /shared/httpd/${VHOST}/htdocs/${name} || true" "1" "${DVLBOX_PATH}"
+ if ! run_fail "docker compose exec -T --user devilbox php php /shared/httpd/${VHOST}/htdocs/${name} 2>&1 | grep -Ei 'fatal|except|err|warn|notice' > /dev/null" "${RETRIES}" "${DVLBOX_PATH}"; then
+ run "docker compose exec -T --user devilbox php php /shared/httpd/${VHOST}/htdocs/${name} || true" "1" "${DVLBOX_PATH}"
ERROR=1
fi
done
diff --git a/.tests/tests/rproxy-javascript.sh b/.tests/tests/rproxy-javascript.sh
index ac36a7220..a522149cb 100755
--- a/.tests/tests/rproxy-javascript.sh
+++ b/.tests/tests/rproxy-javascript.sh
@@ -63,15 +63,15 @@ OUTPUT="OK-RPROXY-JAVASCRIPT"
###
### Create vhost-gen config directory
###
-run "docker-compose exec --user devilbox -T php rm -rf /shared/httpd/${RPROXY_NAME}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${RPROXY_NAME}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php rm -rf /shared/httpd/${RPROXY_NAME}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${RPROXY_NAME}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
###
### Apply default vhost-gen reverse proxy configurations
###
run "cp ${DVLBOX_PATH}/cfg/vhost-gen/apache24.yml-example-rproxy ${SCRIPT_PATH}/../www/${RPROXY_NAME}/${HTTPD_TEMPLATE_DIR}/apache24.yml" "${RETRIES}"
-run "cp ${DVLBOX_PATH}/cfg/vhost-gen/nginx.yml-example-rproxy ${SCRIPT_PATH}/../www/${RPROXY_NAME}/${HTTPD_TEMPLATE_DIR}/nginx.yml" "${RETRIES}"
+run "cp ${DVLBOX_PATH}/cfg/vhost-gen/nginx.yml-example-rproxy-default ${SCRIPT_PATH}/../www/${RPROXY_NAME}/${HTTPD_TEMPLATE_DIR}/nginx.yml" "${RETRIES}"
###
@@ -84,25 +84,25 @@ replace ":${VHOSTGEN_TPL_DEFAULT_PORT}" ":${RPROXY_PORT}" "${SCRIPT_PATH}/../www
###
### Ensure webserver reloads configuration
###
-run "docker-compose exec --user devilbox -T php mv /shared/httpd/${RPROXY_NAME} /shared/httpd/${RPROXY_NAME}.tmp" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mv /shared/httpd/${RPROXY_NAME} /shared/httpd/${RPROXY_NAME}.tmp" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
-run "docker-compose exec --user devilbox -T php mv /shared/httpd/${RPROXY_NAME}.tmp /shared/httpd/${RPROXY_NAME}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mv /shared/httpd/${RPROXY_NAME}.tmp /shared/httpd/${RPROXY_NAME}" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
###
### Start rproxy application
###
-run "docker-compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${RPROXY_NAME}/js && pm2 start index.js -f'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'cd /shared/httpd/${RPROXY_NAME}/js && pm2 start index.js -f'" "${RETRIES}" "${DVLBOX_PATH}"
###
### Test rhost
###
printf "[TEST] rproxy javascript"
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${RPROXY_NAME}.${TLD_SUFFIX}' | tac | tac | grep -E '^${OUTPUT}$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${RPROXY_NAME}.${TLD_SUFFIX}' | tac | tac | grep -E '^${OUTPUT}$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] rproxy javascript\\n"
- run "docker-compose exec --user devilbox -T php curl -v 'http://${RPROXY_NAME}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl -v 'http://${RPROXY_NAME}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
exit 1
else
printf "\\r[OK] rproxy javascript\\n"
diff --git a/.tests/tests/ssl-intranet.sh b/.tests/tests/ssl-intranet.sh
index b843750e1..7b3f0e76d 100755
--- a/.tests/tests/ssl-intranet.sh
+++ b/.tests/tests/ssl-intranet.sh
@@ -77,9 +77,9 @@ fi
### Intranet / from container
###
printf "[TEST] https Intranet / from container"
-if ! run "docker-compose exec -T php curl -sS --fail 'https://httpd' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec -T php curl -sS --fail 'https://httpd' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] https Intranet / from container\\n"
- run "docker-compose exec -T php curl -v 'https://httpd' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec -T php curl -v 'https://httpd' || true" "1" "${DVLBOX_PATH}"
ERROR=1
else
printf "\\r[OK] https Intranet / from container\\n"
@@ -90,7 +90,7 @@ fi
### Intranet /credits.php from host
###
printf "[TEST] https Intranet /credits.php from host"
-if ! run "curl -sS --fail --cacert ${DVLBOX_PATH}/ca/devilbox-ca.crt 'https://localhost:${HOST_PORT_HTTPD_SSL}/credits.php' | tac | tac | grep -E 'https:\\/\\/github\\.com\\/cytopia' >/dev/null" "${RETRIES}" "" "0"; then
+if ! run "curl -sS --fail --cacert ${DVLBOX_PATH}/ca/devilbox-ca.crt 'https://localhost:${HOST_PORT_HTTPD_SSL}/credits.php' | tac | tac | grep -E 'https:\\/\\/github\\.com\\/nntoan' >/dev/null" "${RETRIES}" "" "0"; then
printf "\\r[FAIL] https Intranet /credits.php from host\\n"
run "curl -v --cacert ${DVLBOX_PATH}/ca/devilbox-ca.crt 'https://localhost:${HOST_PORT_HTTPD_SSL}/credits.php' || true" "1"
ERROR=1
@@ -103,9 +103,9 @@ fi
### Intranet /credits.php from container
###
printf "[TEST] https Intranet /credits.php from container"
-if ! run "docker-compose exec -T php curl -sS --fail 'https://httpd/credits.php' | tac | tac | grep -E 'https:\\/\\/github\\.com\\/cytopia' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec -T php curl -sS --fail 'https://httpd/credits.php' | tac | tac | grep -E 'https:\\/\\/github\\.com\\/nntoan' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] https Intranet /credits.php from container\\n"
- run "docker-compose exec -T php curl -v 'https://httpd/credits.php' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec -T php curl -v 'https://httpd/credits.php' || true" "1" "${DVLBOX_PATH}"
ERROR=1
else
printf "\\r[OK] https Intranet /credits.php from container\\n"
diff --git a/.tests/tests/ssl-vhost.sh b/.tests/tests/ssl-vhost.sh
index 6dda5d410..50af5a5ab 100755
--- a/.tests/tests/ssl-vhost.sh
+++ b/.tests/tests/ssl-vhost.sh
@@ -71,10 +71,10 @@ ERROR=0
###
### Create vhost directory
###
-run "docker-compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
-run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/htdocs" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php bash -c 'echo \" /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.php'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/htdocs" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'echo \" /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.php'" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
@@ -95,9 +95,9 @@ fi
### Vhost / from container
###
printf "[TEST] https vhost / from container"
-if ! run "docker-compose exec -T php curl -sS --fail 'https://${VHOST}.${TLD_SUFFIX}' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec -T php curl -sS --fail 'https://${VHOST}.${TLD_SUFFIX}' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] https vhost / from container\\n"
- run "docker-compose exec -T php curl -v 'https://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}" "0"
+ run "docker compose exec -T php curl -v 'https://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}" "0"
ERROR=1
else
printf "\\r[OK] https vhost / from container\\n"
diff --git a/.tests/tests/vhost-directory_index.sh b/.tests/tests/vhost-directory_index.sh
index 2c3de608d..db7307bf4 100755
--- a/.tests/tests/vhost-directory_index.sh
+++ b/.tests/tests/vhost-directory_index.sh
@@ -64,9 +64,9 @@ VHOST=test-vhost-dir_index
###
### Create vhost directory
###
-run "docker-compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
-run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/htdocs" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/htdocs" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
@@ -79,11 +79,11 @@ ERROR=0
###
### index.htm should be served by default
###
-run "docker-compose exec --user devilbox -T php bash -c 'echo \"indexhtm\" > /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.htm'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'echo \"indexhtm\" > /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.htm'" "${RETRIES}" "${DVLBOX_PATH}"
printf "[TEST] index.htm should be served by default"
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep -E '^indexhtm$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep -E '^indexhtm$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] index.htm should be served by default\\n"
- run "docker-compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
ERROR=1
else
printf "\\r[OK] index.htm should be served by default\\n"
@@ -93,11 +93,11 @@ fi
###
### index.html should be served by default
###
-run "docker-compose exec --user devilbox -T php bash -c 'echo \"indexhtml\" > /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.html'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'echo \"indexhtml\" > /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.html'" "${RETRIES}" "${DVLBOX_PATH}"
printf "[TEST] index.html should be served by default"
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep -E '^indexhtml$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep -E '^indexhtml$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] index.html should be served by default\\n"
- run "docker-compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
ERROR=1
else
printf "\\r[OK] index.html should be served by default\\n"
@@ -107,11 +107,11 @@ fi
###
### index.php should be served by default
###
-run "docker-compose exec --user devilbox -T php bash -c 'echo \" /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.php'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'echo \" /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.php'" "${RETRIES}" "${DVLBOX_PATH}"
printf "[TEST] index.php should be served by default"
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep -E '^indexphp$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep -E '^indexphp$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] index.php should be served by default\\n"
- run "docker-compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
ERROR=1
else
printf "\\r[OK] index.php should be served by default\\n"
@@ -123,9 +123,9 @@ fi
### index.htm is available via direct path
###
printf "[TEST] index.htm is available via direct path"
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/index.htm' | tac | tac | grep -E '^indexhtm$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/index.htm' | tac | tac | grep -E '^indexhtm$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] index.htm is available via direct path\\n"
- run "docker-compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/index.htm' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/index.htm' || true" "1" "${DVLBOX_PATH}"
ERROR=1
else
printf "\\r[OK] index.htm is available via direct path\\n"
@@ -136,9 +136,9 @@ fi
### index.html is available via direct path
###
printf "[TEST] index.html is available via direct path"
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/index.html' | tac | tac | grep -E '^indexhtml$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/index.html' | tac | tac | grep -E '^indexhtml$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] index.html is available via direct path\\n"
- run "docker-compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/index.html' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/index.html' || true" "1" "${DVLBOX_PATH}"
ERROR=1
else
printf "\\r[OK] index.html is available via direct path\\n"
@@ -149,9 +149,9 @@ fi
### index.php is available via direct path
###
printf "[TEST] index.php is available via direct path"
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/index.php' | tac | tac | grep -E '^indexphp$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}/index.php' | tac | tac | grep -E '^indexphp$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] index.php is available via direct path\\n"
- run "docker-compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/index.php' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}/index.php' || true" "1" "${DVLBOX_PATH}"
ERROR=1
else
printf "\\r[OK] index.php is available via direct path\\n"
diff --git a/.tests/tests/vhost-vhostgen_customize.sh b/.tests/tests/vhost-vhostgen_customize.sh
index 1e06742e1..c49712aa1 100755
--- a/.tests/tests/vhost-vhostgen_customize.sh
+++ b/.tests/tests/vhost-vhostgen_customize.sh
@@ -70,24 +70,24 @@ VHOST=test-vhost-vhostgen_customize
###
### Create vhost directory
###
-run "docker-compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
-run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/htdocs" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/htdocs" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
###
### Add index.htm, index.html and index.php
###
-run "docker-compose exec --user devilbox -T php bash -c 'echo \"indexhtm\" > /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.htm'" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php bash -c 'echo \"indexhtml\" > /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.html'" "${RETRIES}" "${DVLBOX_PATH}"
-run "docker-compose exec --user devilbox -T php bash -c 'echo \" /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.php'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'echo \"indexhtm\" > /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.htm'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'echo \"indexhtml\" > /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.html'" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php bash -c 'echo \" /shared/httpd/${VHOST}/${HTTPD_DOCROOT_DIR}/index.php'" "${RETRIES}" "${DVLBOX_PATH}"
###
### Copy default configuration
###
-run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
run "cp ${DVLBOX_PATH}/cfg/vhost-gen/apache24.yml-example-vhost ${SCRIPT_PATH}/../www/${VHOST}/${HTTPD_TEMPLATE_DIR}/apache24.yml" "${RETRIES}"
run "cp ${DVLBOX_PATH}/cfg/vhost-gen/nginx.yml-example-vhost ${SCRIPT_PATH}/../www/${VHOST}/${HTTPD_TEMPLATE_DIR}/nginx.yml" "${RETRIES}"
@@ -102,9 +102,9 @@ replace "__INDEX__" "index.html" "${SCRIPT_PATH}/../www/${VHOST}/${HTTPD_TEMPLAT
###
### Ensure webserver reloads configuration
###
-run "docker-compose exec --user devilbox -T php mv /shared/httpd/${VHOST} /shared/httpd/${VHOST}.tmp" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mv /shared/httpd/${VHOST} /shared/httpd/${VHOST}.tmp" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
-run "docker-compose exec --user devilbox -T php mv /shared/httpd/${VHOST}.tmp /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mv /shared/httpd/${VHOST}.tmp /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
@@ -112,9 +112,9 @@ run "sleep 4"
### Ensure index.html will be served by default (as configured)
###
printf "[TEST] index.html should be served"
-if ! run "docker-compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep -E '^indexhtml$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
+if ! run "docker compose exec --user devilbox -T php curl -sS --fail 'http://${VHOST}.${TLD_SUFFIX}' | tac | tac | grep -E '^indexhtml$' >/dev/null" "${RETRIES}" "${DVLBOX_PATH}" "0"; then
printf "\\r[FAIL] index.html should be served\\n"
- run "docker-compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
+ run "docker compose exec --user devilbox -T php curl -sS 'http://${VHOST}.${TLD_SUFFIX}' || true" "1" "${DVLBOX_PATH}"
exit 1
else
printf "\\r[OK] index.html should be served\\n"
diff --git a/.tests/tests/vhost-vhostgen_default_template.sh b/.tests/tests/vhost-vhostgen_default_template.sh
index 1f0f998e2..91b0d8879 100755
--- a/.tests/tests/vhost-vhostgen_default_template.sh
+++ b/.tests/tests/vhost-vhostgen_default_template.sh
@@ -69,9 +69,9 @@ VHOST=test-vhost-vhostgen_def_tpl
###
### Create vhost directory
###
-run "docker-compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php rm -rf /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
-run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/htdocs" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/htdocs" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
@@ -84,7 +84,7 @@ TEMPLATE1="$( run "curl -sS --fail 'http://localhost:${HOST_PORT_HTTPD}/vhost.d/
###
### Copy default configuration
###
-run "docker-compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mkdir -p /shared/httpd/${VHOST}/${HTTPD_TEMPLATE_DIR}" "${RETRIES}" "${DVLBOX_PATH}"
run "cp ${DVLBOX_PATH}/cfg/vhost-gen/apache24.yml-example-vhost ${SCRIPT_PATH}/../www/${VHOST}/${HTTPD_TEMPLATE_DIR}/apache24.yml" "${RETRIES}"
run "cp ${DVLBOX_PATH}/cfg/vhost-gen/nginx.yml-example-vhost ${SCRIPT_PATH}/../www/${VHOST}/${HTTPD_TEMPLATE_DIR}/nginx.yml" "${RETRIES}"
@@ -92,9 +92,9 @@ run "cp ${DVLBOX_PATH}/cfg/vhost-gen/nginx.yml-example-vhost ${SCRIPT_PATH}/../w
###
### Ensure webserver reloads configuration
###
-run "docker-compose exec --user devilbox -T php mv /shared/httpd/${VHOST} /shared/httpd/${VHOST}.tmp" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mv /shared/httpd/${VHOST} /shared/httpd/${VHOST}.tmp" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
-run "docker-compose exec --user devilbox -T php mv /shared/httpd/${VHOST}.tmp /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
+run "docker compose exec --user devilbox -T php mv /shared/httpd/${VHOST}.tmp /shared/httpd/${VHOST}" "${RETRIES}" "${DVLBOX_PATH}"
run "sleep 4"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a10c1d68..1e1d16871 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,34 @@ Make sure to have a look at [UPDATING.md](https://github.com/cytopia/devilbox/bl
## Unreleased
+## Release v3.0.0 (2025-03-27)
+
+### Added
+- Support PHP 8.4
+- Simplified the initialize webapp process of `dvl.sh`
+- Wrapping all PHP related commands with a detection to check and use PHP version
+- New sub-command `ece-tools` for `dvl.sh`
+- New sub-command `cloud-patches` for `dvl.sh`
+- New sub-command `update-docroot` for `dvl.sh`
+- New sub-command `sync-env` for `dvl.sh`
+
+### Changed
+- Updated PHP image version to `0.155`
+- Updated softwares of image to latest versions
+
+
+## Release v3.0.0-beta-0.7 (2024-11-05)
+
+## Added
+- New sub-command `magerun` for `dvl.sh`
+- New sub-command `db:import` (or `db-import`) for `dvl.sh`
+- Add a new way to initialize project for `dvl init` (via `.devilbox.yaml`)
+
+## Changed
+- Removed unsupported and EOL PHP versions out of Devilbox
+- Update PHP image version to `0.154` (remove EOL versions, PHP EOL versions still available in `0.153` and previous)
+
+
## Release v3.0.0-beta-0.6 (2024-06-01)
### Added
diff --git a/README.md b/README.md
index 433325dae..33df22d2b 100644
--- a/README.md
+++ b/README.md
@@ -760,114 +760,106 @@ The Devilbox is a development stack, so it is made sure that a lot of PHP module
-| Modules | PHP 7.4 | PHP 8.0 | PHP 8.1 | PHP 8.2 | PHP 8.3 |
-|-------------------------------|:-------:|:-------:|:-------:|:-------:|:-------:|
-| amqp | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| apc | | | | | |
-| apcu | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| bcmath | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| blackfire | d | d | d | d | d |
-| bz2 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| calendar | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| ctype | ✔ | ✔ | ✔ | ✔ | ✔ |
-| curl | ✔ | ✔ | ✔ | ✔ | ✔ |
-| date | ✔ | ✔ | ✔ | ✔ | ✔ |
-| dba | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| dom | ✔ | ✔ | ✔ | ✔ | ✔ |
-| enchant | | 🗸 | 🗸 | 🗸 | 🗸 |
-| ereg | | | | | |
-| exif | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| FFI | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| fileinfo | ✔ | ✔ | ✔ | ✔ | ✔ |
-| filter | ✔ | ✔ | ✔ | ✔ | ✔ |
-| ftp | ✔ | ✔ | ✔ | | |
-| gd | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| gettext | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| gmp | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| hash | ✔ | ✔ | ✔ | ✔ | ✔ |
-| iconv | ✔ | ✔ | ✔ | ✔ | ✔ |
-| igbinary | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| imagick | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| imap | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| interbase | | | | | |
-| intl | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| ioncube | d | | d | d | |
-| json | ✔ | ✔ | ✔ | ✔ | ✔ |
-| ldap | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| libxml | ✔ | ✔ | ✔ | ✔ | ✔ |
-| lz4 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| lzf | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| mbstring | ✔ | ✔ | ✔ | ✔ | ✔ |
-| mcrypt | 🗸 | 🗸 | | | |
-| memcache | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| memcached | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| mhash | | | | | |
-| mongo | | | | | |
-| mongodb | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| msgpack | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| mysql | | | | | |
-| mysqli | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| mysqlnd | ✔ | ✔ | ✔ | ✔ | ✔ |
-| OAuth | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| oci8 | d | d | d | d | d |
-| OPcache | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| openssl | ✔ | ✔ | ✔ | ✔ | ✔ |
-| pcntl | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| pcre | ✔ | ✔ | ✔ | ✔ | ✔ |
-| PDO | ✔ | ✔ | ✔ | ✔ | ✔ |
-| pdo_dblib | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| PDO_Firebird | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| pdo_mysql | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| PDO_OCI | d | d | d | d | d |
-| pdo_pgsql | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| pdo_sqlite | ✔ | ✔ | ✔ | ✔ | ✔ |
-| pdo_sqlsrv | d | d | d | d | d |
-| pgsql | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| phalcon | d | d | d | d | d |
-| Phar | ✔ | ✔ | ✔ | ✔ | ✔ |
-| posix | ✔ | ✔ | ✔ | ✔ | ✔ |
-| pspell | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| psr | d | d | d | d | d |
-| random | | | | ✔ | ✔ |
-| rdkafka | d | d | d | d | d |
-| readline | ✔ | ✔ | ✔ | ✔ | ✔ |
-| recode | | | | | |
-| redis | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| Reflection | ✔ | ✔ | ✔ | ✔ | ✔ |
-| session | ✔ | ✔ | ✔ | ✔ | ✔ |
-| shmop | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| SimpleXML | ✔ | ✔ | ✔ | ✔ | ✔ |
-| snmp | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| soap | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| sockets | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| sodium | ✔ | ✔ | ✔ | ✔ | ✔ |
-| solr | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| SPL | ✔ | ✔ | ✔ | ✔ | ✔ |
-| sqlite3 | ✔ | ✔ | ✔ | ✔ | ✔ |
-| sqlsrv | d | d | d | d | d |
-| ssh2 | 🗸 | | | | |
-| swoole | d | d | d | d | d |
-| sysvmsg | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| sysvsem | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| sysvshm | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| tidy | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| tokenizer | ✔ | ✔ | ✔ | ✔ | ✔ |
-| uploadprogress | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| uuid | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| vips | 🗸 | 🗸 | 🗸 | | |
-| wddx | | | | | |
-| Xdebug | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| xhprof | d | d | d | d | d |
-| xlswriter | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| xml | ✔ | ✔ | ✔ | ✔ | ✔ |
-| xmlreader | ✔ | ✔ | ✔ | ✔ | ✔ |
-| xmlrpc | 🗸 | | | | |
-| xmlwriter | ✔ | ✔ | ✔ | ✔ | ✔ |
-| xsl | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| yaml | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| zip | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
-| zlib | ✔ | ✔ | ✔ | ✔ | ✔ |
-| zstd | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| Modules | PHP 7.4 | PHP 8.0 | PHP 8.1 | PHP 8.2 | PHP 8.3 | PHP 8.4 |
+|-------------------------------|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
+| amqp | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| apcu | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| bcmath | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| blackfire | d | d | d | d | d | d |
+| bz2 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| calendar | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| ctype | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| curl | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| date | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| dba | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| dom | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| enchant | | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| exif | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| FFI | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| fileinfo | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| filter | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| ftp | ✔ | ✔ | ✔ | | | |
+| gd | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| gettext | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| gmp | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| hash | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| iconv | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| igbinary | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| imagick | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| imap | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| intl | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| ioncube | d | | d | d | d | d |
+| json | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| ldap | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| libxml | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| lz4 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| lzf | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| mbstring | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| mcrypt | 🗸 | 🗸 | | | | |
+| memcache | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| memcached | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| mongodb | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| msgpack | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| mysqli | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| mysqlnd | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| OAuth | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| oci8 | d | d | d | d | d | d |
+| OPcache | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| openssl | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| pcntl | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| pcre | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| PDO | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| pdo_dblib | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| PDO_Firebird | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| pdo_mysql | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| PDO_OCI | d | d | d | d | d | d |
+| pdo_pgsql | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| pdo_sqlite | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| pdo_sqlsrv | d | d | d | d | d | d |
+| pgsql | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| Phar | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| posix | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| pspell | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| psr | d | d | d | d | d | d |
+| random | | | | ✔ | ✔ | ✔ |
+| rdkafka | d | d | d | d | d | d |
+| readline | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| redis | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| Reflection | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| session | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| shmop | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| SimpleXML | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| snmp | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| soap | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| sockets | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| sodium | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| solr | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | |
+| sourceguardian | d | d | d | d | d | d |
+| SPL | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| sqlite3 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| sqlsrv | d | d | d | d | d | d |
+| ssh2 | 🗸 | | | | | |
+| swoole | d | d | d | d | d | d |
+| sysvmsg | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| sysvsem | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| sysvshm | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| tidy | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| tokenizer | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| uploadprogress | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| uuid | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| vips | 🗸 | 🗸 | 🗸 | | | |
+| Xdebug | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| xhprof | d | d | d | d | d | d |
+| xlswriter | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| xml | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| xmlreader | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| xmlrpc | 🗸 | | | | | |
+| xmlwriter | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| xsl | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| yaml | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| zip | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
+| zlib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| zstd | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 | 🗸 |
@@ -910,62 +902,62 @@ Well-known and popular tools will be at your service:
-| Tool | PHP 7.4 | PHP 8.0 | PHP 8.1 | PHP 8.2 | PHP 8.3 |
-|--------------------------------------------|---------|---------|---------|---------|---------|
-| [angular-cli][lnk_angular-cli] | | | | | |
-| [asgardcms][lnk_asgardcms] | | | | | |
-| [awesome-ci][lnk_awesome-ci] | | | | | |
-| [codeception][lnk_codeception] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [**composer**][lnk_**composer**] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [**corepack**][lnk_**corepack**] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [deployer][lnk_deployer] | | | | | |
-| [eslint][lnk_eslint] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [git][lnk_git] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [git-flow][lnk_git-flow] | | | | | |
-| [grunt-cli][lnk_grunt-cli] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [gulp][lnk_gulp] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [jq][lnk_jq] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [jsonlint][lnk_jsonlint] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [laravel-installer][lnk_laravel-installer] | | | | | |
-| [laravel-lumen][lnk_laravel-lumen] | | | | | |
-| [linkcheck][lnk_linkcheck] | | | | | |
-| [magerun][lnk_magerun] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [mdl][lnk_mdl] | | | | | |
-| [mdlint][lnk_mdlint] | | | | | |
-| [mupdf-tools][lnk_mupdf-tools] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [net-tools][lnk_net-tools] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [**node**][lnk_**node**] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [**npm**][lnk_**npm**] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [**nvm**][lnk_**nvm**] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [phalcon-devtools][lnk_phalcon-devtools] | | | | | |
-| [php-cs-fixer][lnk_php-cs-fixer] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [phpcbf][lnk_phpcbf] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [phpcs][lnk_phpcs] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [phpmd][lnk_phpmd] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [phpunit][lnk_phpunit] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [**pip**][lnk_**pip**] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [pm2][lnk_pm2] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [pwncat][lnk_pwncat] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [rsync][lnk_rsync] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [sass][lnk_sass] | | | | | |
-| [shellcheck][lnk_shellcheck] | | | | | |
-| [ssh][lnk_ssh] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [stencil-cli][lnk_stencil-cli] | | | | | |
-| [stylelint][lnk_stylelint] | | | | | |
-| [svn][lnk_svn] | | | | | |
-| [symfony-cli][lnk_symfony-cli] | | | | | |
-| [taskfile][lnk_taskfile] | | | | | |
-| [tig][lnk_tig] | | | | | |
-| [vim][lnk_vim] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [vue-cli][lnk_vue-cli] | | | | | |
-| [webpack-cli][lnk_webpack-cli] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [wkhtmltopdf][lnk_wkhtmltopdf] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [wp-cli][lnk_wp-cli] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [wscat][lnk_wscat] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [yamllint][lnk_yamllint] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [**yarn**][lnk_**yarn**] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [yq][lnk_yq] | ✓ | ✓ | ✓ | ✓ | ✓ |
-| [zsh][lnk_zsh] | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Tool | PHP 7.4 | PHP 8.0 | PHP 8.1 | PHP 8.2 | PHP 8.3 | PHP 8.4 |
+|--------------------------------------------|---------|---------|---------|---------|---------|---------|
+| [angular-cli][lnk_angular-cli] | | | | | | |
+| [asgardcms][lnk_asgardcms] | | | | | | |
+| [awesome-ci][lnk_awesome-ci] | | | | | | |
+| [codeception][lnk_codeception] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [**composer**][lnk_**composer**] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [**corepack**][lnk_**corepack**] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [deployer][lnk_deployer] | | | | | | |
+| [eslint][lnk_eslint] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [git][lnk_git] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [git-flow][lnk_git-flow] | | | | | | |
+| [grunt-cli][lnk_grunt-cli] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [gulp][lnk_gulp] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [jq][lnk_jq] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [jsonlint][lnk_jsonlint] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [laravel-installer][lnk_laravel-installer] | | | | | | |
+| [laravel-lumen][lnk_laravel-lumen] | | | | | | |
+| [linkcheck][lnk_linkcheck] | | | | | | |
+| [magerun][lnk_magerun] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [mdl][lnk_mdl] | | | | | | |
+| [mdlint][lnk_mdlint] | | | | | | |
+| [mupdf-tools][lnk_mupdf-tools] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [net-tools][lnk_net-tools] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [**node**][lnk_**node**] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [**npm**][lnk_**npm**] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [**nvm**][lnk_**nvm**] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [phalcon-devtools][lnk_phalcon-devtools] | | | | | | |
+| [php-cs-fixer][lnk_php-cs-fixer] | ✓ | ✓ | ✓ | ✓ | ✓ | |
+| [phpcbf][lnk_phpcbf] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [phpcs][lnk_phpcs] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [phpmd][lnk_phpmd] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [phpunit][lnk_phpunit] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [**pip**][lnk_**pip**] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [pm2][lnk_pm2] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [pwncat][lnk_pwncat] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [rsync][lnk_rsync] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [sass][lnk_sass] | | | | | | |
+| [shellcheck][lnk_shellcheck] | | | | | | |
+| [ssh][lnk_ssh] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [stencil-cli][lnk_stencil-cli] | | | | | | |
+| [stylelint][lnk_stylelint] | | | | | | |
+| [svn][lnk_svn] | | | | | | |
+| [symfony-cli][lnk_symfony-cli] | | | | | | |
+| [taskfile][lnk_taskfile] | | | | | | |
+| [tig][lnk_tig] | | | | | | |
+| [vim][lnk_vim] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [vue-cli][lnk_vue-cli] | | | | | | |
+| [webpack-cli][lnk_webpack-cli] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [wkhtmltopdf][lnk_wkhtmltopdf] | | | | | | |
+| [wp-cli][lnk_wp-cli] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [wscat][lnk_wscat] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [yamllint][lnk_yamllint] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [**yarn**][lnk_**yarn**] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [yq][lnk_yq] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [zsh][lnk_zsh] | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
[lnk_angular-cli]: ../php_tools/angular-cli
[lnk_asgardcms]: ../php_tools/asgardcms
diff --git a/autostart/downgrade-composer-twopoint2.sh.example b/autostart/downgrade-composer-twopoint2.sh.example
old mode 100755
new mode 100644
index bfa6cf004..bd7f0db02
--- a/autostart/downgrade-composer-twopoint2.sh.example
+++ b/autostart/downgrade-composer-twopoint2.sh.example
@@ -7,4 +7,6 @@ set -o pipefail
# COMPOSER binary
COMPOSER_BIN="/usr/local/bin/composer-2"
+# Only use this script if you are still on version 154 and prior.
+# Starting from .155, default version of composer has been tuning for perfect match.
$COMPOSER_BIN self-update --2.2
diff --git a/cfg/php-fpm-8.4/.keepme b/cfg/php-fpm-8.4/.keepme
new file mode 100644
index 000000000..e69de29bb
diff --git a/cfg/php-fpm-8.4/README.md b/cfg/php-fpm-8.4/README.md
new file mode 100644
index 000000000..bedcb4285
--- /dev/null
+++ b/cfg/php-fpm-8.4/README.md
@@ -0,0 +1,54 @@
+# PHP-FPM 8.3 config directory
+
+## General
+
+* Add you custom php-fpm.conf files into this directory.
+* Only files ending by `.conf` will be enabled
+* Only files ending by `.conf` are ignored by git
+
+
+## Example files
+
+This directory also holds three example files:
+
+| File | Description |
+|---------------------------------|---------------------------------------------|
+| `devilbox-fpm.conf-default` | Represents current PHP-FPM default settings |
+| `devilbox-fpm.conf-pm_dynamic` | Example settings for dynamic workers |
+| `devilbox-fpm.conf-pm_ondemand` | Example settings for ondemand workers |
+
+* Do not edit these example files!
+* Copy them to a new file (in case you want to use them)
+
+
+## Worker configuration
+
+When changing worker processes or scheduler, the following commands will come in handy
+to monitor number of processes and memory consumption.
+
+```bash
+# Show current PHP-FPM child memory consumption in MB
+ps -ylC php-fpm --sort:rss | awk '!/RSS/ { s+=$8 } END { printf "%dM\n", s/1024 }'
+
+# (repeatedly) show current PHP-FPM child memory consumption in MB
+watch --interval=1 "ps -ylC php-fpm --sort:rss | awk '"'!'"/RSS/ { s+=\$8 } END { printf \"%dM\n\", s/1024 }'"
+
+# (repeatedly) Current number of PHP-FPM childs
+watch --interval=1 "ps auxw | grep -E 'php-(cgi|fpm)' | grep -vE 'grep|master' | wc -l"
+```
+
+
+## Overwriting
+
+If multiple `.conf` files are present in this directory specifying different values for the
+same settings, the last file (alphabetically by filename) will overwrite any previous values.
+
+
+## Compatibility
+
+**Note:**
+
+PHP-FPM 5.2 uses XML-style configuration and does not allow includes.
+If you want to change php-fpm.conf for PHP-FPM 5.2 you need to adjust the main configuration file.
+
+See `php-fpm-5.2/` directory.
diff --git a/cfg/php-fpm-8.4/devilbox-fpm.conf-default b/cfg/php-fpm-8.4/devilbox-fpm.conf-default
new file mode 100644
index 000000000..37e1f8ed5
--- /dev/null
+++ b/cfg/php-fpm-8.4/devilbox-fpm.conf-default
@@ -0,0 +1,80 @@
+; ############################################################
+; Devilbox php-fpm.conf: Current default settings
+; ############################################################
+;
+; Information
+; -----------
+; * Do not edit this file (it belongs to git)
+; * This file shows example settings that are currently effective
+; * If this file is enabled, nothing will change as it reflects the current default settings
+;
+; How to enable?
+; --------------
+; * Copy this file to another file with ".conf" extension
+; * Only files with ".conf" extensions will be applied by PHP-FPM
+
+
+; ###
+; ### PHP-FPM global settings
+; ###
+;
+[global]
+
+; Error log level. Possible values: alert, error, warning, notice, debug. Default value: notice.
+log_level = notice
+
+
+
+; ###
+; ### Pool configuratoin
+; ###
+
+[www]
+
+; The timeout for serving a single request after which the worker process will be killed.
+; This option should be used when the 'max_execution_time' ini option does not stop script
+; execution for some reason.
+request_terminate_timeout = 120s
+
+
+; A maximum of backlog incoming connections will be queued for processing.
+; If a connection request arrives with the queue full the client may receive an error with an
+; indication of ECONNREFUSED, or, if the underlying protocol supports retransmission,
+; the request may be ignored so that retries may succeed.
+; This should not be greater than `cat /proc/sys/net/core/somaxconn`, otherwise connections
+; are silently truncated
+listen.backlog = 1024
+
+
+; static - the number of child processes is fixed (pm.max_children).
+;
+; dynamic - the number of child processes is set dynamically based on the following directives:
+; pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers.
+;
+; ondemand - the processes spawn on demand (when requested, as opposed to dynamic, where
+; pm.start_servers are started when the service is started.
+pm = ondemand
+
+; The maximum number of child processes to be created
+pm.max_children = 50
+
+; The number of child processes created on startup. Used only when pm is set to dynamic.
+; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2.
+pm.start_servers = 4
+
+; The desired minimum number of idle server processes.
+pm.min_spare_servers = 2
+
+; The desired maximum number of idle server processes.
+pm.max_spare_servers = 6
+
+; The number of requests each child process should execute before respawning.
+; This can be useful to work around memory leaks in 3rd party libraries.
+; For endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
+; Default value: 0.
+pm.max_requests = 500
+
+; The number of seconds after which an idle process will be killed. Used only when pm is set to ondemand
+pm.process_idle_timeout = 10s
+
+; vim: set ft=dosini:
diff --git a/cfg/php-fpm-8.4/devilbox-fpm.conf-pm_dynamic b/cfg/php-fpm-8.4/devilbox-fpm.conf-pm_dynamic
new file mode 100644
index 000000000..59ec044b9
--- /dev/null
+++ b/cfg/php-fpm-8.4/devilbox-fpm.conf-pm_dynamic
@@ -0,0 +1,46 @@
+; ############################################################
+; # Devilbox php-fpm.conf: dynamic example
+; ############################################################
+;
+; Information
+; -----------
+; * Do not edit this file (it belongs to git)
+; * This file show a possible dynamic example configuration
+; * If this file is enabled, it will overwrite the current worker settings
+;
+; How to enable?
+; --------------
+; * Copy this file to another file with ".conf" extension
+; * Only files with ".conf" extensions will be applied by PHP-FPM
+
+
+; ###
+; ### Pool configuratoin
+; ###
+
+[www]
+
+; dynamic - the number of child processes is set dynamically based on the following directives:
+pm = dynamic
+
+; The maximum number of child processes to be created
+pm.max_children = 50
+
+; The number of child processes created on startup. Used only when pm is set to dynamic.
+; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2.
+pm.start_servers = 4
+
+; The desired minimum number of idle server processes.
+pm.min_spare_servers = 2
+
+; The desired maximum number of idle server processes.
+pm.max_spare_servers = 6
+
+; The number of requests each child process should execute before respawning.
+; This can be useful to work around memory leaks in 3rd party libraries.
+; For endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
+; Default value: 0.
+pm.max_requests = 500
+
+
+; vim: set ft=dosini:
diff --git a/cfg/php-fpm-8.4/devilbox-fpm.conf-pm_ondemand b/cfg/php-fpm-8.4/devilbox-fpm.conf-pm_ondemand
new file mode 100644
index 000000000..84cd3ca72
--- /dev/null
+++ b/cfg/php-fpm-8.4/devilbox-fpm.conf-pm_ondemand
@@ -0,0 +1,39 @@
+; ############################################################
+; # Devilbox php-fpm.conf: ondemand example
+; ############################################################
+;
+; Information
+; -----------
+; * Do not edit this file (it belongs to git)
+; * This file show a possible ondemand example configuration
+; * If this file is enabled, it will overwrite the current worker settings
+;
+; How to enable?
+; --------------
+; * Copy this file to another file with ".conf" extension
+; * Only files with ".conf" extensions will be applied by PHP-FPM
+
+
+; ###
+; ### Pool configuratoin
+; ###
+
+[www]
+
+; ondemand - the processes spawn on demand (when requested, as opposed to dynamic, where
+; pm.start_servers are started when the service is started.
+pm = ondemand
+
+; The maximum number of child processes to be created
+pm.max_children = 50
+
+; The number of requests each child process should execute before respawning.
+; This can be useful to work around memory leaks in 3rd party libraries.
+; For endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
+; Default value: 0.
+pm.max_requests = 500
+
+; The number of seconds after which an idle process will be killed.
+pm.process_idle_timeout = 10s
+
+; vim: set ft=dosini:
diff --git a/cfg/php-ini-8.4/.keepme b/cfg/php-ini-8.4/.keepme
new file mode 100644
index 000000000..e69de29bb
diff --git a/cfg/php-ini-8.4/README.md b/cfg/php-ini-8.4/README.md
new file mode 100644
index 000000000..5fc7a01a7
--- /dev/null
+++ b/cfg/php-ini-8.4/README.md
@@ -0,0 +1,26 @@
+# PHP 8.3 ini directory
+
+## General
+
+* Add you custom php.ini files into this directory.
+* Only files ending by `.ini` will be enabled
+* Only files ending by `.ini` are ignored by git
+
+
+## Example files
+
+This directory also holds two example files:
+
+| File | Description |
+|----------------------------|-----------------------------------------|
+| `devilbox-php.ini-default` | Represents current PHP default settings |
+| `devilbox-php.ini-xdebug ` | Example settings for Xdebug |
+
+* Do not edit these example files!
+* Copy them to a new file (in case you want to use them)
+
+
+## Overwriting
+
+If multiple `.ini` files are present in this directory specifying different values for the
+same settings, the last file (alphabetically by filename) will overwrite any previous values.
diff --git a/cfg/php-ini-8.4/devilbox-php.ini-default b/cfg/php-ini-8.4/devilbox-php.ini-default
new file mode 100644
index 000000000..83d037120
--- /dev/null
+++ b/cfg/php-ini-8.4/devilbox-php.ini-default
@@ -0,0 +1,63 @@
+; ############################################################
+; # Devilbox php.ini: Current default settings
+; ############################################################
+;
+; Information
+; -----------
+; * Do not edit this file (it belongs to git)
+; * This file shows example settings that are currently effective
+; * If this file is enabled, nothing will change as it reflects the current default settings
+;
+; How to enable?
+; --------------
+; * Copy this file to another file with ".ini" extension
+; * Only files with ".ini" extensions will be applied by PHP
+
+
+
+;
+; PHP.ini configuration
+;
+[PHP]
+
+; Memory
+; Note: "memory_limit" should be larger than "post_max_size"
+memory_limit = 512M
+
+
+; Timeouts
+max_execution_time = 120
+max_input_time = 120
+
+
+; Uploads
+; Note: "post_max_size" should be greater than "upload_max_filesize"
+post_max_size = 72M
+upload_max_filesize = 64M
+max_file_uploads = 20
+
+
+; Vars
+variables_order = EGPCS
+max_input_vars = 8000
+max_input_nesting_level = 64
+
+
+; Error reporting
+; Note: error_log is dynamic and handled during start to set appropriate setting
+error_reporting = E_ALL | E_NOTICE | E_STRICT | E_DEPRECATED
+xmlrpc_errors = Off
+report_memleaks = On
+display_errors = On
+display_startup_errors = On
+log_errors = On
+html_errors = On
+
+
+; Xdebug settings
+xdebug.default_enable = Off
+xdebug.profiler_enable = Off
+xdebug.remote_enable = Off
+xdebug.remote_autostart = Off
+
+; vim: set ft=dosini:
diff --git a/cfg/php-ini-8.4/devilbox-php.ini-mailhog b/cfg/php-ini-8.4/devilbox-php.ini-mailhog
new file mode 100644
index 000000000..2ed99e535
--- /dev/null
+++ b/cfg/php-ini-8.4/devilbox-php.ini-mailhog
@@ -0,0 +1,22 @@
+; ############################################################
+; # Devilbox php.ini: MailHog example
+; ############################################################
+;
+; Information
+; -----------
+; * Do not edit this file (it belongs to git)
+; * This file show a possible Xdebug example configuration
+; * If this file is enabled, it will overwrite the current Xdebug settings
+;
+; How to enable?
+; --------------
+; * Copy this file to another file with ".ini" extension
+; * Only files with ".ini" extensions will be applied by PHP
+
+
+
+;
+; PHP.ini configuration
+;
+[PHP]
+sendmail_path = '/usr/local/bin/mhsendmail --smtp-addr="mailhog:1025"'
diff --git a/cfg/php-ini-8.4/devilbox-php.ini-msmtp b/cfg/php-ini-8.4/devilbox-php.ini-msmtp
new file mode 100644
index 000000000..58f4fc1b1
--- /dev/null
+++ b/cfg/php-ini-8.4/devilbox-php.ini-msmtp
@@ -0,0 +1,22 @@
+; ############################################################
+; # Devilbox php.ini: msmtp example
+; ############################################################
+;
+; Information
+; -----------
+; * Do not edit this file (it belongs to git)
+; * This file show a possible Xdebug example configuration
+; * If this file is enabled, it will overwrite the current Xdebug settings
+;
+; How to enable?
+; --------------
+; * Copy this file to another file with ".ini" extension
+; * Only files with ".ini" extensions will be applied by PHP
+
+
+
+;
+; PHP.ini configuration
+;
+[smtp]
+sendmail_path = '/usr/local/bin/msmtp -t'
diff --git a/cfg/php-ini-8.4/devilbox-php.ini-performance b/cfg/php-ini-8.4/devilbox-php.ini-performance
new file mode 100644
index 000000000..512aec804
--- /dev/null
+++ b/cfg/php-ini-8.4/devilbox-php.ini-performance
@@ -0,0 +1,51 @@
+; Max execution time per request
+max_execution_time = 300
+
+; Max memory per instance
+memory_limit = 4G
+
+;The maximum size of an uploaded file.
+upload_max_filesize = 128M
+
+; Increase max input variables value
+max_input_vars = 10000000
+
+;Sets max size of post data allowed. This setting also affects file upload.
+;To upload large files, this value must be larger than upload_max_filesize
+post_max_size = 128M
+
+session.auto_start = off
+session.gc_probability = 0
+suhosin.session.cryptua = off
+
+; Disable garbage collector
+zend.enable_gc = off
+
+[opcache]
+opcache.enable = 1
+opcache.enable_cli = 1
+opcache.memory_consumption = 2048
+opcache.interned_strings_buffer = 20
+opcache.file_cache = 1
+opcache.max_accelerated_files = 80000
+opcache.max_wasted_percentage = 5
+opcache.use_cwd = 1
+opcache.validate_timestamps = 1
+opcache.revalidate_freq = 0
+opcache.file_update_protection = 2
+opcache.revalidate_path = 0
+opcache.save_comments = 1
+opcache.load_comments = 1
+opcache.fast_shutdown = 1
+opcache.enable_file_override = 0
+opcache.optimization_level = 0xffffffff
+opcache.inherited_hack = 1
+opcache.blacklist_filename = ""
+opcache.max_file_size = 0
+opcache.consistency_checks = 0
+opcache.force_restart_timeout = 180
+opcache.error_log = ""
+opcache.log_verbosity_level = 1
+opcache.preferred_memory_model = ""
+opcache.protect_memory = 0
+apc.cache_by_default = false
diff --git a/cfg/php-ini-8.4/devilbox-php.ini-xdebug b/cfg/php-ini-8.4/devilbox-php.ini-xdebug
new file mode 100644
index 000000000..2608fedc5
--- /dev/null
+++ b/cfg/php-ini-8.4/devilbox-php.ini-xdebug
@@ -0,0 +1,54 @@
+; ############################################################
+; # Devilbox php.ini: Xdebug example
+; ############################################################
+;
+; Information
+; -----------
+; * Do not edit this file (it belongs to git)
+; * This file show a possible Xdebug example configuration
+; * If this file is enabled, it will overwrite the current Xdebug settings
+;
+; How to enable?
+; --------------
+; * Copy this file to another file with ".ini" extension
+; * Only files with ".ini" extensions will be applied by PHP
+
+
+
+;
+; PHP.ini configuration
+;
+[PHP]
+
+; Xdebug (version 3.x.x - latest)
+; Upgrade Guide: https://3.xdebug.org/docs/upgrade_guide
+; Settings Guide: https://xdebug.org/docs/all_settings
+;
+; Use these settings to enable Xdebug for PHP
+; Make sure to read up on Xdebug some settings might significantly slow down requests.
+; The following is just an example configuration and should be adjusted.
+;
+; In order to use Xdebug in macOS, make sure to configure as per following article:
+; https://devilbox.readthedocs.io/en/latest/howto/xdebug/host-address-alias-an-mac.html#howto-host-address-alias-on-mac
+
+; Defaults
+xdebug.mode = debug
+;xdebug.remote_handler = dbgp
+xdebug.start_with_request = yes
+;xdebug.start_with_request = trigger
+;xdebug.trigger_value = randomkey
+
+; How to connect
+xdebug.client_port = 9000
+xdebug.client_host = 10.254.254.254
+xdebug.discover_client_host = 0
+
+; Logging
+xdebug.log = /var/log/php/xdebug.log
+xdebug.log_level = 7
+
+; IDE Configuration
+xdebug.idekey = PHPSTORM
+;xdebug.idekey = VSCODE
+
+; vim: set ft=dosini:
diff --git a/cfg/php-startup-8.4/.keepme b/cfg/php-startup-8.4/.keepme
new file mode 100644
index 000000000..e69de29bb
diff --git a/cfg/php-startup-8.4/01-update-apt-index.sh-example b/cfg/php-startup-8.4/01-update-apt-index.sh-example
new file mode 100755
index 000000000..d324ef890
--- /dev/null
+++ b/cfg/php-startup-8.4/01-update-apt-index.sh-example
@@ -0,0 +1,6 @@
+#!/bin/bash
+#
+# Simple example showing how to update the packet index
+#
+
+DEBIAN_FRONTEND=noninteractive apt-get update -q
diff --git a/cfg/php-startup-8.4/README.md b/cfg/php-startup-8.4/README.md
new file mode 100644
index 000000000..a9b0013e8
--- /dev/null
+++ b/cfg/php-startup-8.4/README.md
@@ -0,0 +1,29 @@
+# Custom startup scripts (for PHP 8.3 only)
+
+Any script inside this directory ending by `.sh` will be executed during the PHP container startup.
+This is useful to apply your custom settings such as installing software that usually requires
+the user to accept a license or similar.
+
+A few examples are given that do not end by `.sh` which won't be run. If you want to use the
+provided examples, copy them to a file ending by `.sh`
+
+
+## Info
+
+If you want to autostart NodeJS applications, you can use [pm2](https://github.com/Unitech/pm2).
+Ensure you do this as user `devilbox`, as by default everything is run by root.
+
+```bash
+su -c 'cd /shared/httpd/node/node; pm2 start index.js' -l devilbox
+```
+
+
+## Note
+
+This directory will startup commands only for a specific PHP version. If you want to run commands
+for all versions , go to `autostart/` in the root of the Devilbox git directory.
+
+
+## Important
+
+All provided scripts will be executed with **root** permissions.
diff --git a/cfg/vhost-gen/nginx.yml-example-rproxy-default b/cfg/vhost-gen/nginx.yml-example-rproxy-default
new file mode 100644
index 000000000..c7bea2268
--- /dev/null
+++ b/cfg/vhost-gen/nginx.yml-example-rproxy-default
@@ -0,0 +1,125 @@
+---
+
+# Nginx Reverse Proxy Template defintion for vhost-gen.py
+#
+# The 'feature' section contains optional features that can be enabled via
+# conf.yml and will then be replaced into the main vhost ('structure' section)
+# into their corresponding position:
+#
+# __XDOMAIN_REQ__
+# __ALIASES__
+# __DENIES__
+# __STATUS__
+#
+# The features itself also contain variables to be adjusted in conf.yml
+# and will then be replaced in their corresponding feature section
+# before being replaced into the vhost section (if enabled):
+#
+# XDomain:
+# __REGEX__
+# Alias:
+# __REGEX__
+# __PATH__
+# Deny:
+# __REGEX__
+# Status:
+# __REGEX__
+#
+# Variables to be replaced directly in the vhost configuration can also be set
+# in conf.yml and include:
+# __VHOST_NAME__
+# __DOCUMENT_ROOT__
+# __INDEX__
+# __ACCESS_LOG__
+# __ERROR_LOG__
+#
+
+
+###
+### Basic vHost skeleton
+###
+vhost: |
+ server {
+ listen __PORT____HTTP_PROTO____DEFAULT_VHOST__;
+ server_name __VHOST_NAME__;
+
+ access_log "__ACCESS_LOG__" combined;
+ error_log "__ERROR_LOG__" warn;
+
+ # Reverse Proxy definition (Ensure to adjust the port, currently '8000')
+ location / {
+ # https://stackoverflow.com/a/72586833
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ # Proxy connection
+ proxy_pass http://php:8000;
+ }
+
+ __REDIRECT__
+ __SSL__
+ __ALIASES__
+ __DENIES__
+ __SERVER_STATUS__
+ # Custom directives
+ __CUSTOM__
+ }
+
+###
+### vHost Type (normal or reverse proxy)
+###
+vhost_type:
+ docroot: ""
+ rproxy: ""
+
+###
+### Optional features to be enabled in vHost
+###
+features:
+
+ # SSL Configuration
+ ssl: |
+ ssl_certificate __SSL_PATH_CRT__;
+ ssl_certificate_key __SSL_PATH_KEY__;
+ ssl_protocols __SSL_PROTOCOLS__;
+ ssl_prefer_server_ciphers __SSL_HONOR_CIPHER_ORDER__;
+ ssl_ciphers __SSL_CIPHERS__;
+
+ # Redirect to SSL directive
+ redirect: |
+ return 301 https://__VHOST_NAME__:__SSL_PORT__$request_uri;
+
+ # PHP-FPM left empty, as we are an reverse proxy configuration
+ php_fpm: ""
+
+ alias: |
+ # Alias Definition
+ location ~ __ALIAS__ {
+ root __PATH__;
+ __XDOMAIN_REQ__
+ }
+
+ deny: |
+ # Deny Definition
+ location ~ __REGEX__ {
+ deny all;
+ }
+
+ server_status: |
+ # Status Page
+ location ~ __REGEX__ {
+ stub_status on;
+ access_log off;
+ }
+
+ xdomain_request: |
+ # Allow cross domain request from these hosts
+ # https://fetch.spec.whatwg.org/#forbidden-header-name
+ if ( $http_origin ~* (__REGEX__) ) {
+ add_header "Access-Control-Allow-Origin" "$http_origin";
+ add_header 'Access-Control-Allow-Methods' 'HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS';
+ add_header 'Access-Control-Allow-Headers' 'Accept, Authorization, Content-Security-Policy, Content-Type, Location, Origin, X-Requested-With';
+ add_header 'Access-Control-Expose-Headers' 'Content-Security-Policy, Location';
+ add_header 'Access-Control-Max-Age' 0;
+ return 200;
+ }
diff --git a/compose/docker-compose.override.yml-magento2 b/compose/docker-compose.override.yml-magento2
index 86ac7f38c..150fcfdb5 100644
--- a/compose/docker-compose.override.yml-magento2
+++ b/compose/docker-compose.override.yml-magento2
@@ -61,6 +61,11 @@ services:
# - ${DEVILBOX_PATH}/cfg/msmtp/msmtprc:/etc/msmtprc:ro${MOUNT_OPTIONS}
- ${DEVILBOX_PATH}/autostart:/startup.2.d:rw${MOUNT_OPTIONS}
- devilbox-mail:/var/mail:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ # Certificate Authority public key
+ - ${DEVILBOX_PATH}/ca:/ca:rw${MOUNT_OPTIONS}
+ # Users SSH directory (read-only)
+ - ${HOST_PATH_SSH_DIR}:/home/devilbox/.ssh:ro${MOUNT_OPTIONS}
php72:
<<: *default-php
@@ -82,6 +87,11 @@ services:
# - ${DEVILBOX_PATH}/cfg/msmtp/msmtprc:/etc/msmtprc:ro${MOUNT_OPTIONS}
- ${DEVILBOX_PATH}/autostart:/startup.2.d:rw${MOUNT_OPTIONS}
- devilbox-mail:/var/mail:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ # Certificate Authority public key
+ - ${DEVILBOX_PATH}/ca:/ca:rw${MOUNT_OPTIONS}
+ # Users SSH directory (read-only)
+ - ${HOST_PATH_SSH_DIR}:/home/devilbox/.ssh:ro${MOUNT_OPTIONS}
php73:
<<: *default-php
@@ -103,10 +113,15 @@ services:
# - ${DEVILBOX_PATH}/cfg/msmtp/msmtprc:/etc/msmtprc:ro${MOUNT_OPTIONS}
- ${DEVILBOX_PATH}/autostart:/startup.2.d:rw${MOUNT_OPTIONS}
- devilbox-mail:/var/mail:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ # Certificate Authority public key
+ - ${DEVILBOX_PATH}/ca:/ca:rw${MOUNT_OPTIONS}
+ # Users SSH directory (read-only)
+ - ${HOST_PATH_SSH_DIR}:/home/devilbox/.ssh:ro${MOUNT_OPTIONS}
php74:
<<: *default-php
- image: devilboxcommunity/php-fpm:7.4-slim-0.154
+ image: devilboxcommunity/php-fpm:7.4-slim-0.155
hostname: php74
networks:
app_net:
@@ -124,10 +139,15 @@ services:
# - ${DEVILBOX_PATH}/cfg/msmtp/msmtprc:/etc/msmtprc:ro${MOUNT_OPTIONS}
- ${DEVILBOX_PATH}/autostart:/startup.2.d:rw${MOUNT_OPTIONS}
- devilbox-mail:/var/mail:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ # Certificate Authority public key
+ - ${DEVILBOX_PATH}/ca:/ca:rw${MOUNT_OPTIONS}
+ # Users SSH directory (read-only)
+ - ${HOST_PATH_SSH_DIR}:/home/devilbox/.ssh:ro${MOUNT_OPTIONS}
php80:
<<: *default-php
- image: devilboxcommunity/php-fpm:8.0-slim-0.154
+ image: devilboxcommunity/php-fpm:8.0-slim-0.155
hostname: php80
networks:
app_net:
@@ -145,10 +165,15 @@ services:
# - ${DEVILBOX_PATH}/cfg/msmtp/msmtprc:/etc/msmtprc:ro${MOUNT_OPTIONS}
- ${DEVILBOX_PATH}/autostart:/startup.2.d:rw${MOUNT_OPTIONS}
- devilbox-mail:/var/mail:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ # Certificate Authority public key
+ - ${DEVILBOX_PATH}/ca:/ca:rw${MOUNT_OPTIONS}
+ # Users SSH directory (read-only)
+ - ${HOST_PATH_SSH_DIR}:/home/devilbox/.ssh:ro${MOUNT_OPTIONS}
php81:
<<: *default-php
- image: devilboxcommunity/php-fpm:8.1-slim-0.154
+ image: devilboxcommunity/php-fpm:8.1-slim-0.155
hostname: php81
networks:
app_net:
@@ -166,10 +191,15 @@ services:
# - ${DEVILBOX_PATH}/cfg/msmtp/msmtprc:/etc/msmtprc:ro${MOUNT_OPTIONS}
- ${DEVILBOX_PATH}/autostart:/startup.2.d:rw${MOUNT_OPTIONS}
- devilbox-mail:/var/mail:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ # Certificate Authority public key
+ - ${DEVILBOX_PATH}/ca:/ca:rw${MOUNT_OPTIONS}
+ # Users SSH directory (read-only)
+ - ${HOST_PATH_SSH_DIR}:/home/devilbox/.ssh:ro${MOUNT_OPTIONS}
php82:
<<: *default-php
- image: devilboxcommunity/php-fpm:8.2-slim-0.154
+ image: devilboxcommunity/php-fpm:8.2-slim-0.155
hostname: php82
networks:
app_net:
@@ -187,10 +217,15 @@ services:
# - ${DEVILBOX_PATH}/cfg/msmtp/msmtprc:/etc/msmtprc:ro${MOUNT_OPTIONS}
- ${DEVILBOX_PATH}/autostart:/startup.2.d:rw${MOUNT_OPTIONS}
- devilbox-mail:/var/mail:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ # Certificate Authority public key
+ - ${DEVILBOX_PATH}/ca:/ca:rw${MOUNT_OPTIONS}
+ # Users SSH directory (read-only)
+ - ${HOST_PATH_SSH_DIR}:/home/devilbox/.ssh:ro${MOUNT_OPTIONS}
php83:
<<: *default-php
- image: devilboxcommunity/php-fpm:8.3-slim-0.154
+ image: devilboxcommunity/php-fpm:8.3-slim-0.155
hostname: php83
networks:
app_net:
@@ -208,6 +243,37 @@ services:
# - ${DEVILBOX_PATH}/cfg/msmtp/msmtprc:/etc/msmtprc:ro${MOUNT_OPTIONS}
- ${DEVILBOX_PATH}/autostart:/startup.2.d:rw${MOUNT_OPTIONS}
- devilbox-mail:/var/mail:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ # Certificate Authority public key
+ - ${DEVILBOX_PATH}/ca:/ca:rw${MOUNT_OPTIONS}
+ # Users SSH directory (read-only)
+ - ${HOST_PATH_SSH_DIR}:/home/devilbox/.ssh:ro${MOUNT_OPTIONS}
+
+ php84:
+ <<: *default-php
+ image: devilboxcommunity/php-fpm:8.4-slim-0.155
+ hostname: php84
+ networks:
+ app_net:
+ ipv4_address: 172.16.238.213
+ volumes:
+ # Specific volumes
+ - ${DEVILBOX_PATH}/cfg/php-ini-8.4:/etc/php-custom.d:ro${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/cfg/php-fpm-8.4:/etc/php-fpm-custom.d:ro${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/cfg/php-startup-8.4:/startup.1.d:rw${MOUNT_OPTIONS}
+ # Generic volumes
+ - ${HOST_PATH_HTTPD_DATADIR}:/shared/httpd:rw${MOUNT_OPTIONS}
+ - ${HOST_PATH_BACKUPDIR}:/shared/backups:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/bash:/etc/bashrc-devilbox.d:rw${MOUNT_OPTIONS}
+ # - ${DEVILBOX_PATH}/cfg/msmtp/msmtprc:/etc/msmtprc:ro${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/autostart:/startup.2.d:rw${MOUNT_OPTIONS}
+ - devilbox-mail:/var/mail:rw${MOUNT_OPTIONS}
+ - ${DEVILBOX_PATH}/supervisor:/etc/supervisor/custom.d:rw${MOUNT_OPTIONS}
+ # Certificate Authority public key
+ - ${DEVILBOX_PATH}/ca:/ca:rw${MOUNT_OPTIONS}
+ # Users SSH directory (read-only)
+ - ${HOST_PATH_SSH_DIR}:/home/devilbox/.ssh:ro${MOUNT_OPTIONS}
# ------------------------------------------------------------
# MySQL Database
diff --git a/docker-compose.yml b/docker-compose.yml
index 87e200789..1002d289d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -104,7 +104,7 @@ services:
# PHP
# ------------------------------------------------------------
php:
- image: devilboxcommunity/php-fpm:${PHP_SERVER}-work-0.154
+ image: devilboxcommunity/php-fpm:${PHP_SERVER}-work-0.156
hostname: php
##
diff --git a/dvl.sh b/dvl.sh
index 628b09d96..f466c3f9a 100755
--- a/dvl.sh
+++ b/dvl.sh
@@ -188,7 +188,7 @@ TEMPLATE_CONFIG="$DEVILBOX_PATH/.tests/devilbox-template-config.yaml"
YQ_BINARY="$DEVILBOX_PATH/.tests/binaries/yq"
# Read-only variables
-readonly VERSION="1.2.2"
+readonly VERSION="1.2.3"
function main {
if [[ $# -eq 0 ]] ; then
@@ -317,17 +317,501 @@ function RestartServices {
fi
}
+function GetPhpVersionFromYaml {
+ local debug_mode=${1:-false}
+
+ # Check in current directory first
+ local yaml_file="$CURRENT_DIR/$CONFIG_FILE"
+
+ # If not found, check parent directory (common for Magento AWS projects)
+ if [[ ! -f "$yaml_file" ]]; then
+ yaml_file="$(dirname "$CURRENT_DIR")/$CONFIG_FILE"
+ fi
+
+ # If still not found and we're in htdocs or a subdirectory
+ if [[ ! -f "$yaml_file" ]]; then
+ # Check if current dir matches htdocs name
+ if [[ "$(basename "$CURRENT_DIR")" == "$HTTPD_DOCROOT_DIR" ]]; then
+ # We're in htdocs, try the parent directory
+ yaml_file="$(dirname "$CURRENT_DIR")/$CONFIG_FILE"
+ elif [[ "$(basename "$(dirname "$CURRENT_DIR")")" == "$HTTPD_DOCROOT_DIR" ]]; then
+ # We're in a subdirectory of htdocs, try going up two levels
+ yaml_file="$(dirname "$(dirname "$CURRENT_DIR")")/$CONFIG_FILE"
+ fi
+ fi
+
+ # Debug mode to help troubleshoot version detection
+ if [[ "$debug_mode" == "true" ]]; then
+ echo "Current directory: $CURRENT_DIR" >&2
+ echo "Document root dir: $HTTPD_DOCROOT_DIR" >&2
+ echo "Checking multiple locations for YAML file" >&2
+ echo "1. Current directory: $CURRENT_DIR/$CONFIG_FILE" >&2
+ echo "2. Parent directory: $(dirname "$CURRENT_DIR")/$CONFIG_FILE" >&2
+
+ if [[ -f "$yaml_file" ]]; then
+ echo "Found YAML file at: $yaml_file" >&2
+ echo "PHP version in YAML: $("$YQ_BINARY" '.php.version' "$yaml_file")" >&2
+ else
+ echo "YAML file not found in any of the checked locations" >&2
+ fi
+ fi
+
+ # First check if we're in a project with a yaml file
+ if [[ -f "$yaml_file" ]]; then
+ local php_version=$("$YQ_BINARY" '.php.version' "$yaml_file")
+
+ # If we have a valid PHP version in the yaml file
+ if [[ -n "$php_version" && "$php_version" != "null" ]]; then
+ # Get the PHP_SERVER from .env file (default PHP version)
+ local php_server="$( "${SCRIPT_PATH}/env-getvar.sh" "PHP_SERVER" )"
+
+ if [[ "$debug_mode" == "true" ]]; then
+ echo "Default PHP server from .env: $php_server" >&2
+ fi
+
+ # If php_version matches the pattern phpXX
+ if [[ "$php_version" =~ ^php[0-9]{2}$ ]]; then
+ # Extract numeric part from php_version (e.g., "74" from "php74")
+ local yaml_version_num="${php_version#php}"
+
+ # Convert env PHP version to same format (e.g., "7.4" to "74")
+ local env_version_num=$(echo "$php_server" | sed 's/\.//g')
+
+ if [[ "$debug_mode" == "true" ]]; then
+ echo "YAML PHP version num: $yaml_version_num" >&2
+ echo "ENV PHP version num: $env_version_num" >&2
+ fi
+
+ # If versions match, use default "php" container
+ if [[ "$yaml_version_num" == "$env_version_num" ]]; then
+ echo "php"
+ else
+ echo "$php_version"
+ fi
+ return 0
+ else
+ # Invalid PHP version format in yaml
+ if [[ "$debug_mode" == "true" ]]; then
+ echo "Invalid PHP version format in YAML" >&2
+ fi
+ echo "php"
+ return 1
+ fi
+ fi
+ fi
+
+ # Default fallback
+ echo "php"
+ return 1
+}
+
+function CheckPhpContainerFlavor {
+ local php_container="$1"
+ local debug=${2:-false}
+
+ if [[ "$debug" == "true" ]]; then
+ echo "Checking flavor for container: $php_container" >&2
+ fi
+
+ # Skip check for default php container
+ if [[ "$php_container" == "php" ]]; then
+ if [[ "$debug" == "true" ]]; then
+ echo "Default PHP container, assuming work flavor" >&2
+ fi
+ echo "work"
+ return 0
+ fi
+
+ # Get current container image from docker-compose config
+ local container_image=""
+ local config_output=""
+
+ if hash docker-compose 2>/dev/null; then
+ if [[ "$debug" == "true" ]]; then
+ echo "Using docker-compose to get config" >&2
+ fi
+ config_output=$(cd "$DEVILBOX_PATH" && docker-compose config)
+ else
+ if [[ "$debug" == "true" ]]; then
+ echo "Using docker compose to get config" >&2
+ fi
+ config_output=$(cd "$DEVILBOX_PATH" && docker compose config)
+ fi
+
+ # First, try to extract service and image using a different pattern
+ if [[ "$debug" == "true" ]]; then
+ echo "Trying to find $php_container in docker-compose config" >&2
+ fi
+
+ # Save the config to a temp file for easier debugging
+ local temp_config=$(mktemp)
+ echo "$config_output" > "$temp_config"
+
+ if [[ "$debug" == "true" ]]; then
+ echo "Docker compose config written to temp file at: $temp_config" >&2
+ echo "Checking with grep -A 20 '$php_container:'" >&2
+ fi
+
+ # Try various patterns to match the container
+ container_image=$(grep -A 20 "$php_container:" "$temp_config" | grep -m 1 "image:" | sed 's/image://g' | sed 's/^[[:space:]]*//g')
+
+ if [[ -z "$container_image" ]]; then
+ if [[ "$debug" == "true" ]]; then
+ echo "First attempt failed, trying with different pattern" >&2
+ fi
+ container_image=$(grep -A 20 " $php_container:" "$temp_config" | grep -m 1 "image:" | sed 's/image://g' | sed 's/^[[:space:]]*//g')
+ fi
+
+ if [[ -z "$container_image" ]]; then
+ if [[ "$debug" == "true" ]]; then
+ echo "Second attempt failed, trying with looser pattern" >&2
+ fi
+ # More aggressive pattern
+ container_image=$(grep -A 50 -i "$php_container" "$temp_config" | grep -m 1 "image:" | sed 's/image://g' | sed 's/^[[:space:]]*//g')
+ fi
+
+ # Clean up
+ rm -f "$temp_config"
+
+ if [[ "$debug" == "true" ]]; then
+ echo "Found container image: $container_image" >&2
+ fi
+
+ # Still no image found
+ if [[ -z "$container_image" ]]; then
+ if [[ "$debug" == "true" ]]; then
+ echo "Could not determine container image for $php_container" >&2
+ fi
+ echo "unknown"
+ return 2 # Could not determine image
+ fi
+
+ # Check if container is using work or slim flavor
+ if [[ "$container_image" == *"-slim-"* ]]; then
+ if [[ "$debug" == "true" ]]; then
+ echo "Container using slim flavor" >&2
+ fi
+ echo "slim"
+ return 1 # Not work flavor - THIS IS CRITICAL: must return 1 for slim
+ elif [[ "$container_image" == *"-work-"* ]]; then
+ if [[ "$debug" == "true" ]]; then
+ echo "Container using work flavor" >&2
+ fi
+ echo "work"
+ return 0 # Is work flavor - returning 0 for work
+ fi
+
+ # Default response for unknown flavor
+ if [[ "$debug" == "true" ]]; then
+ echo "Unknown container flavor" >&2
+ fi
+ echo "unknown"
+ return 2 # Unknown flavor
+}
+
+function UpdateContainerFlavor {
+ local php_container="$1"
+ local target_flavor="$2"
+
+ # Use get_workspace_path to get the correct path
+ local devilbox_path=$(get_workspace_path)
+ local override_file="$devilbox_path/docker-compose.override.yml"
+
+ echo "Updating container flavor for $php_container to $target_flavor" >&2
+ echo "Using Devilbox path: $devilbox_path" >&2
+ echo "Override file: $override_file" >&2
+
+ # Create the override file if it doesn't exist
+ if [[ ! -f "$override_file" ]]; then
+ echo "Override file not found. Creating minimal override file..." >&2
+
+ # Create a minimal docker-compose.override.yml file
+ cat > "$override_file" <&2
+ fi
+
+ # Get current container image using more robust pattern matching
+ local current_image=""
+ local config_output=""
+
+ if hash docker-compose 2>/dev/null; then
+ config_output=$(cd "$devilbox_path" && docker-compose config 2>/dev/null)
+ else
+ config_output=$(cd "$devilbox_path" && docker compose config 2>/dev/null)
+ fi
+
+ # Save the config to a temp file for easier debugging
+ local temp_config=$(mktemp)
+ echo "$config_output" > "$temp_config"
+
+ # Try various patterns to match the container image
+ current_image=$(grep -A 20 "$php_container:" "$temp_config" | grep -m 1 "image:" | sed 's/image://g' | sed 's/^[[:space:]]*//g')
+
+ if [[ -z "$current_image" ]]; then
+ current_image=$(grep -A 20 " $php_container:" "$temp_config" | grep -m 1 "image:" | sed 's/image://g' | sed 's/^[[:space:]]*//g')
+ fi
+
+ if [[ -z "$current_image" ]]; then
+ # More aggressive pattern
+ current_image=$(grep -A 50 -i "$php_container" "$temp_config" | grep -m 1 "image:" | sed 's/image://g' | sed 's/^[[:space:]]*//g')
+ fi
+
+ # Clean up
+ rm -f "$temp_config"
+
+ echo "Current image from config: $current_image" >&2
+
+ if [[ -z "$current_image" ]]; then
+ echo "Could not find image for $php_container in docker-compose config" >&2
+ # Try to extract information from container name
+ local version_num=${php_container#php}
+ if [[ "$version_num" =~ ^[0-9]{2}$ ]]; then
+ # Convert to decimal format (74 -> 7.4)
+ local major="${version_num:0:1}"
+ local minor="${version_num:1:1}"
+ local version="$major.$minor"
+ echo "Using version $version derived from container name" >&2
+ current_image="devilboxcommunity/php-fpm:$version-slim-0.155"
+ else
+ # Get default PHP version if container name doesn't contain version
+ local default_php="$( "${SCRIPT_PATH}/env-getvar.sh" "PHP_SERVER" )"
+ echo "Using default PHP version: $default_php" >&2
+ current_image="devilboxcommunity/php-fpm:$default_php-slim-0.155"
+ fi
+ echo "Using derived image: $current_image" >&2
+ fi
+
+ # Extract version and build number
+ local version_build=$(echo "$current_image" | sed -E 's/.*:([0-9.]+)-[a-z]+-([0-9.]+)/\1-\2/')
+ local version=$(echo "$version_build" | cut -d'-' -f1)
+ local build=$(echo "$version_build" | cut -d'-' -f2)
+
+ echo "Extracted version: $version, build: $build" >&2
+
+ # Create new image name
+ local new_image="devilboxcommunity/php-fpm:$version-$target_flavor-$build"
+
+ echo "New image will be: $new_image" >&2
+ echo -ne "${YELLOW}Updating $php_container image to $target_flavor flavor..."
+
+ # Make a backup of the original file
+ if [[ -f "$override_file" && -s "$override_file" ]]; then
+ cp "$override_file" "${override_file}.bak"
+ fi
+
+ # Process YAML with careful line-by-line approach to maintain structure
+ local temp_file=$(mktemp)
+ local in_container_section=0
+ local image_line_found=0
+ local indent_level=""
+
+ while IFS= read -r line; do
+ # Detect if we're entering the container section
+ if [[ "$line" =~ ^[[:space:]]*"$php_container:"($|[[:space:]]) ]]; then
+ in_container_section=1
+ # Capture the indent level for this section
+ indent_level=$(echo "$line" | sed -E 's/^([[:space:]]*)'"$php_container"'.*/\1/')
+ echo "$line" >> "$temp_file"
+ continue
+ fi
+
+ # If we're in the container section and find an image line, replace it
+ if [[ $in_container_section -eq 1 && "$line" =~ ^[[:space:]]*image: ]]; then
+ # Maintain the existing indentation
+ local img_indent=$(echo "$line" | sed -E 's/^([[:space:]]*)image:.*/\1/')
+ echo "${img_indent}image: $new_image" >> "$temp_file"
+ image_line_found=1
+ continue
+ fi
+
+ # If we encounter another service or the end of the services section, we're exiting our container section
+ if [[ $in_container_section -eq 1 && ( "$line" =~ ^[[:space:]]*[a-zA-Z0-9_-]+:($|[[:space:]]) || "$line" =~ ^[^[:space:]#] ) ]]; then
+ # If we didn't find an image line, add it before moving on
+ if [[ $image_line_found -eq 0 ]]; then
+ # Use parent indentation plus 2 spaces for the image line
+ echo "${indent_level} image: $new_image" >> "$temp_file"
+ image_line_found=1
+ fi
+ in_container_section=0
+ fi
+
+ # Write the current line to the output file
+ echo "$line" >> "$temp_file"
+ done < "$override_file"
+
+ # If we're still in the container section at the end of the file and haven't added an image line
+ if [[ $in_container_section -eq 1 && $image_line_found -eq 0 ]]; then
+ echo "${indent_level} image: $new_image" >> "$temp_file"
+ fi
+
+ # If we never found the container section, add it at the end of the file
+ if [[ $in_container_section -eq 0 && $image_line_found -eq 0 ]]; then
+ # Check if there's a services: line
+ if grep -q "^services:" "$override_file"; then
+ # Add to existing services section
+ echo " $php_container:" >> "$temp_file"
+ echo " <<: *default-php" >> "$temp_file"
+ echo " image: $new_image" >> "$temp_file"
+ else
+ # Create a completely new section
+ echo "services:" >> "$temp_file"
+ echo " $php_container:" >> "$temp_file"
+ echo " <<: *default-php" >> "$temp_file"
+ echo " image: $new_image" >> "$temp_file"
+ fi
+ fi
+
+ # Replace the original file with our new one
+ mv "$temp_file" "$override_file"
+
+ echo -e "...${NORMAL} ${GREEN}DONE ✔${NORMAL}\n"
+ echo -ne "${YELLOW}Pulling new image: $new_image..."
+
+ # Pull the new image with error handling
+ if hash docker-compose 2>/dev/null; then
+ if ! (cd "$devilbox_path" && docker-compose pull "$php_container"); then
+ echo -e "...${NORMAL} ${RED}FAILED ✘${NORMAL}\n"
+ echo "Warning: Failed to pull new image. Check Docker connectivity." >&2
+ # Continue anyway - don't return error
+ fi
+ else
+ if ! (cd "$devilbox_path" && docker compose pull "$php_container"); then
+ echo -e "...${NORMAL} ${RED}FAILED ✘${NORMAL}\n"
+ echo "Warning: Failed to pull new image. Check Docker connectivity." >&2
+ # Continue anyway - don't return error
+ fi
+ fi
+
+ echo -e "...${NORMAL} ${GREEN}DONE ✔${NORMAL}\n"
+ echo "${YELLOW}Restarting $php_container container...${NORMAL}"
+
+ # Restart the container with error handling
+ if hash docker-compose 2>/dev/null; then
+ if ! (cd "$devilbox_path" && docker-compose up -d "$php_container"); then
+ echo -e "${RED}FAILED ✘${NORMAL}\n"
+ echo "Warning: Failed to restart container $php_container." >&2
+ # Continue anyway - don't return error
+ fi
+ else
+ if ! (cd "$devilbox_path" && docker compose up -d "$php_container"); then
+ echo -e "${RED}FAILED ✘${NORMAL}\n"
+ echo "Warning: Failed to restart container $php_container." >&2
+ # Continue anyway - don't return error
+ fi
+ fi
+
+ echo "${GREEN}Successfully updated container settings${NORMAL}"
+
+ # Wait for container to be ready
+ echo "${YELLOW}Waiting for $php_container container to be ready...${NORMAL}"
+ sleep 5
+
+ # Clean up backup file if it exists
+ if [[ -f "${override_file}.bak" ]]; then
+ rm -f "${override_file}.bak"
+ fi
+
+ return 0
+}
+
+function CommandRequiringWorkFlavor {
+ local command_type="$1"
+ local php_version="$2"
+ local args="${@:3}"
+
+ # Check if container has work flavor
+ local flavor=$(CheckPhpContainerFlavor "$php_version")
+ local has_work_flavor=$?
+
+ # Debug output
+ echo "Detected PHP container: $php_version with flavor: $flavor (return code: $has_work_flavor)" >&2
+
+ # Fixed condition - check actual flavor string instead of relying only on return code
+ if [[ "$flavor" == "slim" ]] || [[ "$flavor" == "unknown" ]]; then
+ echo -ne "${YELLOW}$command_type requires 'work' flavor, but $php_version is using $flavor flavor.${NORMAL}\n"
+ read -r -p "${CYAN}Would you like to update $php_version to 'work' flavor? [Y/n]${NORMAL} " response
+ case "$response" in
+ [nN][oO]|[nN])
+ error "$command_type requires work flavor. Command aborted."
+ return 1
+ ;;
+ *)
+ # Update container flavor and continue if successful
+ if ! UpdateContainerFlavor "$php_version" "work"; then
+ error "Failed to update container flavor. Command aborted."
+ return 1
+ fi
+ # Additional debug output to confirm flavor was updated
+ echo "Container flavor updated successfully, proceeding with command" >&2
+ ;;
+ esac
+ fi
+
+ case "$command_type" in
+ "magento")
+ BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox "$php_version" bash -c "php -dmemory_limit=-1 bin/magento $args"
+ ;;
+ "magerun")
+ BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox "$php_version" bash -c "php -dmemory_limit=-1 /usr/local/bin/magerun $args"
+ ;;
+ "composer")
+ BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox "$php_version" bash -c "composer $args"
+ ;;
+ "ece-tools")
+ BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox "$php_version" bash -c "php -dmemory_limit=-1 ./vendor/bin/ece-tools $args"
+ ;;
+ "ece-patches")
+ BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox "$php_version" bash -c "php -dmemory_limit=-1 ./vendor/bin/ece-patches $args"
+ ;;
+ *)
+ error "Unknown command type: $command_type"
+ return 1
+ ;;
+ esac
+}
+
function OpenShell {
if [[ -z "$*" ]]; then
- BaseComposeCommand exec --user devilbox php bash -l
+ local php_version=$(GetPhpVersionFromYaml)
+
+ if [[ "$php_version" != "php" ]]; then
+ read -r -p "${CYAN}Use detected PHP version $php_version instead of default PHP? [Y/n]${NORMAL} " response
+ case "$response" in
+ [nN][oO]|[nN])
+ php_version="php"
+ ;;
+ *)
+ ;;
+ esac
+ fi
+
+ echo "${YELLOW}Opening shell with $php_version${NORMAL}"
+ BaseComposeCommand exec --user devilbox "$php_version" bash -l
else
BaseComposeCommand exec --user devilbox "$1" bash -l
fi
}
function ExecShell {
- info "Workdir: $TARGET_WORKDIR"
- BaseComposeCommand exec --user devilbox php bash -c "cd $TARGET_WORKDIR; $*"
+ local php_version=$(GetPhpVersionFromYaml)
+
+ if [[ "$php_version" != "php" ]]; then
+ read -r -p "${CYAN}Use detected PHP version $php_version instead of default PHP? [Y/n]${NORMAL} " response
+ case "$response" in
+ [nN][oO]|[nN])
+ php_version="php"
+ ;;
+ *)
+ ;;
+ esac
+ fi
+
+ info "Workdir: $TARGET_WORKDIR using $php_version"
+ BaseComposeCommand exec --user devilbox "$php_version" bash -c "cd $TARGET_WORKDIR; $*"
}
function ExecShellTTY {
@@ -335,23 +819,88 @@ function ExecShellTTY {
}
function MagentoCommand {
- BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox php bash -c "php -dmemory_limit=-1 bin/magento $*"
+ local php_version=$(GetPhpVersionFromYaml)
+
+ if [[ "$php_version" != "php" ]]; then
+ read -r -p "${CYAN}Use detected PHP version $php_version instead of default PHP? [Y/n]${NORMAL} " response
+ case "$response" in
+ [nN][oO]|[nN])
+ php_version="php"
+ ;;
+ *)
+ ;;
+ esac
+ fi
+
+ CommandRequiringWorkFlavor "magento" "$php_version" "$@"
}
function MagerunCommand {
- BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox php bash -c "php -dmemory_limit=-1 /usr/local/bin/magerun $*"
+ local php_version=$(GetPhpVersionFromYaml)
+
+ if [[ "$php_version" != "php" ]]; then
+ read -r -p "${CYAN}Use detected PHP version $php_version instead of default PHP? [Y/n]${NORMAL} " response
+ case "$response" in
+ [nN][oO]|[nN])
+ php_version="php"
+ ;;
+ *)
+ ;;
+ esac
+ fi
+
+ CommandRequiringWorkFlavor "magerun" "$php_version" "$@"
}
function ComposerCommand {
- BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox php bash -c "composer $*"
+ local php_version=$(GetPhpVersionFromYaml)
+
+ if [[ "$php_version" != "php" ]]; then
+ read -r -p "${CYAN}Use detected PHP version $php_version instead of default PHP? [Y/n]${NORMAL} " response
+ case "$response" in
+ [nN][oO]|[nN])
+ php_version="php"
+ ;;
+ *)
+ ;;
+ esac
+ fi
+
+ CommandRequiringWorkFlavor "composer" "$php_version" "$@"
}
function EceToolsCommand {
- BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox php bash -c "php -dmemory_limit=-1 ./vendor/bin/ece-tools $*"
+ local php_version=$(GetPhpVersionFromYaml)
+
+ if [[ "$php_version" != "php" ]]; then
+ read -r -p "${CYAN}Use detected PHP version $php_version instead of default PHP? [Y/n]${NORMAL} " response
+ case "$response" in
+ [nN][oO]|[nN])
+ php_version="php"
+ ;;
+ *)
+ ;;
+ esac
+ fi
+
+ CommandRequiringWorkFlavor "ece-tools" "$php_version" "$@"
}
function EcePatchesCommand {
- BaseComposeCommand exec --workdir "$TARGET_WORKDIR" --user devilbox php bash -c "php -dmemory_limit=-1 ./vendor/bin/ece-patches $*"
+ local php_version=$(GetPhpVersionFromYaml)
+
+ if [[ "$php_version" != "php" ]]; then
+ read -r -p "${CYAN}Use detected PHP version $php_version instead of default PHP? [Y/n]${NORMAL} " response
+ case "$response" in
+ [nN][oO]|[nN])
+ php_version="php"
+ ;;
+ *)
+ ;;
+ esac
+ fi
+
+ CommandRequiringWorkFlavor "ece-patches" "$php_version" "$@"
}
function DatabaseImport {
@@ -545,11 +1094,36 @@ function InteractiveQuestions {
}
function InitializeProject {
- if [[ ! -f "$CURRENT_DIR/$CONFIG_FILE" ]]; then
+ local yaml_file="$CURRENT_DIR/$CONFIG_FILE"
+ local apps_to_bootstrap=()
+
+ # Check if yaml file exists
+ if [[ -f "$yaml_file" ]]; then
+ echo "${YELLOW}Found existing .devilbox.yaml configuration file.${NORMAL}"
+
+ # Check if we need to add a new app or bootstrap existing apps
+ read -r -p "${CYAN}Do you want to (a)dd a new app or (b)ootstrap existing apps? [b]${NORMAL} " response
+
+ case "$response" in
+ [aA])
+ # Scenario 3 - Add new app to existing configuration
+ InteractiveQuestions
+ UpdateYamlWithNewApp "$yaml_file"
+ BootstrapWebApplication "$WEBAPP_STACK"
+ ;;
+
+ [bB]|*)
+ # Scenario 2 - Bootstrap existing apps
+ ReadYamlConfiguration "$yaml_file"
+ BootstrapExistingApps "$yaml_file"
+ ;;
+ esac
+ else
+ # Scenario 1 - No yaml file exists
InteractiveQuestions
+ BootstrapWebApplication "$WEBAPP_STACK"
+ GenerateYamlConf "$WEBAPP_STACK" "$APPNAME" "$APPDOMAINS" "$WEB_MULTI" "$MAGE_INFRA" "$APPREPOSITORY" "$PHP_VERSION" "$PROXY_PORT"
fi
- BootstrapWebApplication "$WEBAPP_STACK"
- GenerateYamlConf "$WEBAPP_STACK" "$APPNAME" "$APPDOMAINS" "$WEB_MULTI" "$MAGE_INFRA" "$APPREPOSITORY" "$PHP_VERSION" "$PROXY_PORT"
}
function UpdateConfig {
@@ -563,6 +1137,23 @@ function UpdateConfig {
"$YQ_BINARY$nullInput" "$@"
}
+function ReadYamlConfiguration {
+ local yaml_file="$1"
+
+ # Read stack, infra type, PHP version, etc.
+ WEBAPP_STACK=$("$YQ_BINARY" '.stack' "$yaml_file")
+ MAGE_INFRA=$("$YQ_BINARY" '.infra' "$yaml_file")
+ APPREPOSITORY=$("$YQ_BINARY" '.repo' "$yaml_file")
+ PHP_VERSION=$("$YQ_BINARY" '.php.version' "$yaml_file")
+ PROXY_PORT=$("$YQ_BINARY" '.proxy.port' "$yaml_file")
+
+ echo "${YELLOW}Loaded configuration from yaml file:${NORMAL}"
+ echo "Stack: ${GREEN}$WEBAPP_STACK${NORMAL}"
+ echo "Infrastructure: ${GREEN}$MAGE_INFRA${NORMAL}"
+ echo "PHP Version: ${GREEN}$PHP_VERSION${NORMAL}"
+ echo "Repository: ${GREEN}$APPREPOSITORY${NORMAL}"
+}
+
function GenerateYamlConf {
local baseAppDir="$WEBAPP_DIR/$2"
local filePath="$baseAppDir/$HTTPD_DOCROOT_DIR/$CONFIG_FILE"
@@ -585,11 +1176,85 @@ function GenerateYamlConf {
fi
}
+function UpdateYamlWithNewApp {
+ local yaml_file="$1"
+
+ # Check if app already exists in yaml
+ local app_exists=$("$YQ_BINARY" ".apps[] | select(.name == \"$APPNAME\") | .name" "$yaml_file")
+
+ if [[ -n "$app_exists" ]]; then
+ echo "${YELLOW}App ${GREEN}$APPNAME${YELLOW} already exists in configuration file.${NORMAL}"
+ return
+ fi
+
+ # Add new app to yaml
+ "$YQ_BINARY" -i ".apps += [{\"name\": \"$APPNAME\", \"is_subdomain\": \"$WEB_MULTI\"}]" "$yaml_file"
+
+ echo "${GREEN}Added new app ${BOLD}$APPNAME${NORMAL}${GREEN} to configuration file.${NORMAL}"
+}
+
+function BootstrapExistingApps {
+ local yaml_file="$1"
+ local apps_count=$("$YQ_BINARY" '.apps | length' "$yaml_file")
+
+ echo "${YELLOW}Found ${apps_count} application(s) defined in configuration.${NORMAL}"
+
+ for ((i=0; i /dev/null
- if [[ "$AWS_BASEDIR" != "$HTTPD_DOCROOT_DIR" ]]; then
- (cd "$WEBAPP_DIR/$APPNAME" || exit; ln -snf "$AWS_BASEDIR" "$HTTPD_DOCROOT_DIR" > /dev/null)
+ if [[ -d "$repo_dir" ]] && [[ "$repo_name" != "$APPNAME" ]]; then
+ echo -ne "\n${YELLOW}Found repository directory with different name: $repo_name"
+ echo -ne "\n${YELLOW}Renaming to match app name: $APPNAME"
+ mv "$repo_dir" "$WEBAPP_DIR/$APPNAME"
+ echo -ne "...${NORMAL} ${GREEN}DONE ✔${NORMAL}\n"
fi
fi
- mkdir -p "$WEBAPP_DIR/$APPNAME"
- mkdir -p "$devilboxConfDir"
+ # If directory already exists
+ if [[ -d "$WEBAPP_DIR/$APPNAME" ]]; then
+ echo -ne "\n${YELLOW}Directory $APPNAME already exists"
- # General Configuration
- if [[ -f "$DEVILBOX_PATH/cfg/vhost-gen/backend.cfg-example-php-multi" ]] && [[ $currentStack != "nodejs" ]] && [[ $currentStack != "bigcommerce" ]] && [[ $currentStack != "shopify" ]]; then
- cat "$DEVILBOX_PATH/cfg/vhost-gen/backend.cfg-example-php-multi" | sed "s/PHP_VERSION/$PHP_VERSION/g" > "$devilboxConfDir/backend.cfg"
- fi
+ # Always ensure the template directory exists regardless of subdomain status
+ mkdir -p "$devilboxConfDir"
- if [[ -f "$DEVILBOX_PATH/cfg/vhost-gen/backend.cfg-example-rproxy-multi" ]] && [[ $currentStack != "magento" ]] && [[ $currentStack != "laravel" ]] && [[ $currentStack != "phpweb" ]]; then
- cat "$DEVILBOX_PATH/cfg/vhost-gen/backend.cfg-example-rproxy-multi" | sed "s/PHP_VERSION/$PHP_VERSION/g" | sed "s/PROXY_PORT/$PROXY_PORT/g" > "$devilboxConfDir/backend.cfg"
- fi
+ # For subdomains, we ensure the symbolic link exists
+ if [[ "$WEB_MULTI" == "Y" ]]; then
+ echo -ne "\n${YELLOW}Ensuring subdomain configuration exists"
- if [[ "$WEB_MULTI" == "N" ]]; then
- if [[ "$MAGE_INFRA" == "cloud" ]] || [[ "$MAGE_INFRA" == "" ]]; then
- git clone --quiet "$APPREPOSITORY" "$WEBAPP_DIR/$APPNAME/$HTTPD_DOCROOT_DIR" > /dev/null
+ # Setup symbolic link to parent app if not already set
+ if [[ ! -L "$WEBAPP_DIR/$APPNAME/$HTTPD_DOCROOT_DIR" ]]; then
+ (cd "$WEBAPP_DIR/$APPNAME" || exit; ln -snf "../$PARENT_APPNAME/$HTTPD_DOCROOT_DIR" "$HTTPD_DOCROOT_DIR" > /dev/null)
+ fi
+ fi
+
+ # For Magento AWS infrastructure, ensure symlinks are correct
+ if [[ "$currentStack" == "magento" ]] && [[ "$MAGE_INFRA" == "aws" ]]; then
+ if [[ ! -L "$WEBAPP_DIR/$APPNAME/$HTTPD_DOCROOT_DIR" ]] && [[ -d "$WEBAPP_DIR/$APPNAME/$AWS_BASEDIR" ]]; then
+ echo -ne "\n${YELLOW}Setting up AWS infrastructure symlinks"
+ (cd "$WEBAPP_DIR/$APPNAME" || exit; ln -snf "$AWS_BASEDIR" "$HTTPD_DOCROOT_DIR" > /dev/null)
+ fi
+ fi
+ else
+ # Create new directory structure
+ mkdir -p "$WEBAPP_DIR/$APPNAME"
+ mkdir -p "$devilboxConfDir"
+
+ # For non-subdomains, clone repository if provided
+ if [[ "$WEB_MULTI" == "N" ]]; then
+ if [[ "$MAGE_INFRA" == "aws" ]]; then
+ git clone --quiet "$APPREPOSITORY" "$WEBAPP_DIR/$APPNAME" > /dev/null
+ if [[ "$AWS_BASEDIR" != "$HTTPD_DOCROOT_DIR" ]]; then
+ (cd "$WEBAPP_DIR/$APPNAME" || exit; ln -snf "$AWS_BASEDIR" "$HTTPD_DOCROOT_DIR" > /dev/null)
+ fi
+ elif [[ "$MAGE_INFRA" == "cloud" ]] || [[ "$MAGE_INFRA" == "" ]]; then
+ git clone --quiet "$APPREPOSITORY" "$WEBAPP_DIR/$APPNAME/$HTTPD_DOCROOT_DIR" > /dev/null
+ fi
+ elif [[ "$WEB_MULTI" == "Y" ]]; then
+ # For subdomains, create symbolic link to parent app
+ (cd "$WEBAPP_DIR/$APPNAME" || exit; ln -snf "../$PARENT_APPNAME/$HTTPD_DOCROOT_DIR" "$HTTPD_DOCROOT_DIR" > /dev/null)
fi
- elif [[ "$WEB_MULTI" == "Y" ]]; then
- (cd "$WEBAPP_DIR" || exit; ln -snf "../$PARENT_APPNAME/$HTTPD_DOCROOT_DIR" "$WEBAPP_DIR/$APPNAME/$HTTPD_DOCROOT_DIR" > /dev/null)
fi
+ # Configure based on stack type
case "$currentStack" in
magento)
templateType="magento2"
@@ -651,6 +1342,21 @@ function BootstrapWebApplication {
;;
esac
+ # Ensure template directory exists before writing config files
+ if [[ ! -d "$devilboxConfDir" ]]; then
+ mkdir -p "$devilboxConfDir"
+ fi
+
+ # General Configuration
+ if [[ -f "$DEVILBOX_PATH/cfg/vhost-gen/backend.cfg-example-php-multi" ]] && [[ $currentStack != "nodejs" ]] && [[ $currentStack != "bigcommerce" ]] && [[ $currentStack != "shopify" ]]; then
+ cat "$DEVILBOX_PATH/cfg/vhost-gen/backend.cfg-example-php-multi" | sed "s/PHP_VERSION/$PHP_VERSION/g" > "$devilboxConfDir/backend.cfg"
+ fi
+
+ if [[ -f "$DEVILBOX_PATH/cfg/vhost-gen/backend.cfg-example-rproxy-multi" ]] && [[ $currentStack != "magento" ]] && [[ $currentStack != "laravel" ]] && [[ $currentStack != "phpweb" ]]; then
+ cat "$DEVILBOX_PATH/cfg/vhost-gen/backend.cfg-example-rproxy-multi" | sed "s/PHP_VERSION/php/g" | sed "s/PROXY_PORT/$PROXY_PORT/g" > "$devilboxConfDir/backend.cfg"
+ fi
+
+ # Setup web server configuration
if [[ "$HTTPD_SERVER" =~ "nginx" ]]; then
cp "$DEVILBOX_PATH/cfg/vhost-gen/nginx.yml-example-$templateType" "$devilboxConfDir/nginx.yml"
elif [[ "$HTTPD_SERVER" = "apache-2.2" ]]; then
@@ -733,6 +1439,139 @@ function SyncHttpdConf {
echo ""
}
+function SyncEnvConf {
+ # STEP 1: Handle docker-compose.override.yml synchronization
+ local DOCKER_OVERRIDE_SOURCE="$DEVILBOX_PATH/compose/docker-compose.override.yml-magento2"
+ local DOCKER_OVERRIDE_TARGET="$DEVILBOX_PATH/docker-compose.override.yml"
+
+ if [[ -f "$DOCKER_OVERRIDE_SOURCE" ]] && [[ -f "$DOCKER_OVERRIDE_TARGET" ]]; then
+ echo "${YELLOW}${BOLD}Step 1: Checking docker-compose.override.yml differences${NORMAL}"
+ echo "Comparing $DOCKER_OVERRIDE_SOURCE with $DOCKER_OVERRIDE_TARGET"
+ echo ""
+
+ # Check if files are different
+ if ! diff -q "$DOCKER_OVERRIDE_SOURCE" "$DOCKER_OVERRIDE_TARGET" >/dev/null; then
+ # Show differences
+ diff -u "$DOCKER_OVERRIDE_TARGET" "$DOCKER_OVERRIDE_SOURCE" || true
+ echo ""
+
+ # Prompt user for action
+ read -r -p "${CYAN}Would you like to apply these changes to your docker-compose.override.yml? (y/n): ${NORMAL}" response
+ case "$response" in
+ [yY][eE][sS]|[yY])
+ echo -ne "${YELLOW}[!] Updating docker-compose.override.yml..."
+ cp "$DOCKER_OVERRIDE_SOURCE" "$DOCKER_OVERRIDE_TARGET"
+ echo -ne "...${NORMAL} ${GREEN}DONE ✔${NORMAL}"
+ echo ""
+ ;;
+ *)
+ echo -ne "${YELLOW}[!] Skipping docker-compose.override.yml update..."
+ echo -ne "...${NORMAL} ${CYAN}SKIPPED${NORMAL}"
+ echo ""
+ ;;
+ esac
+ else
+ echo -ne "${YELLOW}[!] No differences found in docker-compose.override.yml..."
+ echo -ne "...${NORMAL} ${GREEN}DONE ✔${NORMAL}"
+ echo ""
+ fi
+ elif [[ -f "$DOCKER_OVERRIDE_SOURCE" ]] && [[ ! -f "$DOCKER_OVERRIDE_TARGET" ]]; then
+ echo -ne "${YELLOW}[!] Creating new docker-compose.override.yml..."
+ cp "$DOCKER_OVERRIDE_SOURCE" "$DOCKER_OVERRIDE_TARGET"
+ echo -ne "...${NORMAL} ${GREEN}DONE ✔${NORMAL}"
+ echo ""
+ fi
+
+ # STEP 2: Handle .env synchronization
+ local ENV_SOURCE="$DEVILBOX_PATH/env-example"
+ local ENV_TARGET="$DEVILBOX_PATH/.env"
+
+ echo ""
+ echo "${YELLOW}${BOLD}Step 2: Checking .env file differences${NORMAL}"
+ echo "Comparing $ENV_SOURCE with $ENV_TARGET"
+ echo ""
+
+ if [[ -f "$ENV_SOURCE" ]] && [[ -f "$ENV_TARGET" ]]; then
+ # Create temporary files for comparison with normalized preserved variables
+ local TMP_SOURCE=$(mktemp)
+ local TMP_TARGET=$(mktemp)
+
+ # Copy original files to temp files
+ cp "$ENV_SOURCE" "$TMP_SOURCE"
+ cp "$ENV_TARGET" "$TMP_TARGET"
+
+ # Normalize preserved variables to same values in both files
+ for var in "TLD_SUFFIX" "NEW_UID" "NEW_GID" "HOST_PORT_BIND"; do
+ sed -i.bak "s/^$var=.*/$var=NORMALIZED_VALUE/" "$TMP_SOURCE" && rm -f "${TMP_SOURCE}.bak"
+ sed -i.bak "s/^$var=.*/$var=NORMALIZED_VALUE/" "$TMP_TARGET" && rm -f "${TMP_TARGET}.bak"
+ done
+
+ # Check if files are different (ignoring the preserved variables)
+ if ! diff -q "$TMP_SOURCE" "$TMP_TARGET" >/dev/null; then
+ # Show differences in original files
+ diff -u "$ENV_TARGET" "$ENV_SOURCE" || true
+ echo ""
+
+ # Prompt user for action
+ read -r -p "${CYAN}Would you like to apply these changes to your .env file? (y/n): ${NORMAL}" response
+ case "$response" in
+ [yY][eE][sS]|[yY])
+ echo -ne "${YELLOW}[!] Updating .env file while preserving key variables..."
+
+ # Backup the current values of preserved variables
+ local tld_suffix=$(grep -E "^TLD_SUFFIX=" "$ENV_TARGET" | cut -d '=' -f2-)
+ local new_uid=$(grep -E "^NEW_UID=" "$ENV_TARGET" | cut -d '=' -f2-)
+ local new_gid=$(grep -E "^NEW_GID=" "$ENV_TARGET" | cut -d '=' -f2-)
+ local host_port_bind=$(grep -E "^HOST_PORT_BIND=" "$ENV_TARGET" | cut -d '=' -f2-)
+
+ # Copy the new env file
+ cp "$ENV_SOURCE" "$ENV_TARGET"
+
+ # Restore preserved variables if they were found
+ if [[ ! -z "$tld_suffix" ]]; then
+ sed -i.bak "s/^TLD_SUFFIX=.*/TLD_SUFFIX=${tld_suffix}/" "$ENV_TARGET" && rm -f "${ENV_TARGET}.bak"
+ fi
+
+ if [[ ! -z "$new_uid" ]]; then
+ sed -i.bak "s/^NEW_UID=.*/NEW_UID=${new_uid}/" "$ENV_TARGET" && rm -f "${ENV_TARGET}.bak"
+ fi
+
+ if [[ ! -z "$new_gid" ]]; then
+ sed -i.bak "s/^NEW_GID=.*/NEW_GID=${new_gid}/" "$ENV_TARGET" && rm -f "${ENV_TARGET}.bak"
+ fi
+
+ if [[ ! -z "$host_port_bind" ]]; then
+ sed -i.bak "s/^HOST_PORT_BIND=.*/HOST_PORT_BIND=${host_port_bind}/" "$ENV_TARGET" && rm -f "${ENV_TARGET}.bak"
+ fi
+
+ echo -ne "...${NORMAL} ${GREEN}DONE ✔${NORMAL}"
+ echo ""
+ ;;
+ *)
+ echo -ne "${YELLOW}[!] Aborting environment synchronization..."
+ echo -ne "...${NORMAL} ${RED}ABORTED${NORMAL}"
+ echo ""
+ ;;
+ esac
+ else
+ echo -ne "${YELLOW}[!] No meaningful differences found in .env file (ignoring preserved variables)..."
+ echo -ne "...${NORMAL} ${GREEN}DONE ✔${NORMAL}"
+ echo ""
+ fi
+
+ # Clean up temporary files
+ rm -f "$TMP_SOURCE" "$TMP_TARGET"
+
+ elif [[ -f "$ENV_SOURCE" ]] && [[ ! -f "$ENV_TARGET" ]]; then
+ echo -ne "${YELLOW}[!] Creating new .env file..."
+ cp "$ENV_SOURCE" "$ENV_TARGET"
+ echo -ne "...${NORMAL} ${GREEN}DONE ✔${NORMAL}"
+ echo ""
+ fi
+
+ success "Environment configuration synchronization complete!"
+}
+
function DoctorForBox {
/bin/bash "$DEVILBOX_PATH/check-config.sh"
}
@@ -813,7 +1652,7 @@ function Usage {
echo " cloud-patches${NORMAL} Run EcePatches command from the current project directory"
echo " update-docroot${NORMAL} Update new document root for all current webapps"
echo " sync-httpd${NORMAL} Sync Httpd configuration to all current webapps"
- echo " sync-env${NORMAL} Sync current .env from default env file (prompting for changes)"
+ echo " sync-env${NORMAL} Sync current .env from default env file & docker-compose.override.yml (prompting for changes)"
;;
esac
}
diff --git a/env-example b/env-example
index 60d8bc732..c8ae690e8 100644
--- a/env-example
+++ b/env-example
@@ -580,7 +580,7 @@ HOST_PATH_SSH_DIR=~/.ssh
### Also ensure to disable xdebug when using any of the above:
### https://xdebug.org/docs/install#compat
###
-### PHP_MODULES_ENABLE=ioncube, blackfire
+### PHP_MODULES_ENABLE=ioncube, blackfire, sourceguardian
###
PHP_MODULES_ENABLE=
@@ -592,7 +592,7 @@ PHP_MODULES_ENABLE=
###
### PHP_MODULES_DISABLE=xdebug,imagick,swoole
###
-PHP_MODULES_DISABLE=oci8,PDO_OCI,PDO_Firebird,pdo_dblib,pdo_sqlite,pdo_sqlsrv,sqlsrv,rdkafka,swoole,psr,phalcon,amqp,apcu,FFI,ldap,lz4,lzf,memcache,memcached,mongodb,OAuth,snmp,solr,sqlite3,uploadprogress,uuid,vips,xlswriter,yaml,zstd
+PHP_MODULES_DISABLE=oci8,PDO_OCI,pdo_sqlsrv,sqlsrv,rdkafka,swoole,psr,phalcon
###