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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .docker/database-services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,34 @@ services:
- MYSQL_DATABASE=${MYSQL_DATABASE:-nextcloud}
- MYSQL_USER=${MYSQL_USER:-nextcloud}
- MYSQL_PASSWORD=${MYSQL_PASSWORD:-nextcloud}
mariadb106:
image: mariadb:10.6.28@sha256:23616f0bd3aff922f4dea4130f1d0a09f3571d20b7b36c8f49840672dc309e8c
volumes:
- ${WORKER_VOLUMES_DIR:-../volumes}/mariadb/data:/var/lib/mysql
ports:
- target: 3306
published: "3306-3325"
host_ip: ${MARIADB_IP_BIND:-127.0.0.1}
environment:
- TZ=${TZ:-CET}
- MARIADB_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-root}
- MARIADB_DATABASE=${MYSQL_DATABASE:-nextcloud}
- MARIADB_USER=${MYSQL_USER:-nextcloud}
- MARIADB_PASSWORD=${MYSQL_PASSWORD:-nextcloud}
mariadb1011:
image: mariadb:10.11.19@sha256:07c0aaff7396b74cb7975cba78257178d188e30f531a5db2b617c48beef13c41
volumes:
- ${WORKER_VOLUMES_DIR:-../volumes}/mariadb/data:/var/lib/mysql
ports:
- target: 3306
published: "3306-3325"
host_ip: ${MARIADB_IP_BIND:-127.0.0.1}
environment:
- TZ=${TZ:-CET}
- MARIADB_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-root}
- MARIADB_DATABASE=${MYSQL_DATABASE:-nextcloud}
- MARIADB_USER=${MYSQL_USER:-nextcloud}
- MARIADB_PASSWORD=${MYSQL_PASSWORD:-nextcloud}
pgsql:
image: postgres:13-alpine@sha256:fb9065b6e3e213bdc07edd372a5b2a26245840b7fb65d1fd8b6700106d51805c
volumes:
Expand Down
4 changes: 3 additions & 1 deletion .docker/scripts/nextcloud-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fi
# Set configurations, if needed
if [[ ! -f "config/config.php" && ${AUTOINSTALL} -eq 1 ]]; then
echo "⌛️ Starting installation ..."
if [[ "${db_type}" == 'mysql' ]]; then
if [[ "${db_type}" == 'mysql' || "${db_type}" == 'mariadb' ]]; then
occ maintenance:install --verbose --database="${db_driver}" --database-name="${MYSQL_DATABASE}" --database-host="${db_host}" --database-port= --database-user="${MYSQL_USER}" --database-pass="${MYSQL_PASSWORD}" --admin-user="${NEXTCLOUD_ADMIN_USER}" --admin-pass="${NEXTCLOUD_ADMIN_PASSWORD}" --admin-email="${NEXTCLOUD_ADMIN_EMAIL}"
install_cmd_status=$?
elif [[ "${db_type}" == 'pgsql' ]]; then
Expand All @@ -61,6 +61,8 @@ if [[ ! -f "config/config.php" && ${AUTOINSTALL} -eq 1 ]]; then
db_reset_hint="volumes/nextcloud/config and volumes/nextcloud/data"
if [[ "${db_type}" == 'mysql' ]]; then
db_reset_hint="volumes/mysql/data, ${db_reset_hint}"
elif [[ "${db_type}" == 'mariadb' ]]; then
db_reset_hint="volumes/mariadb/data, ${db_reset_hint}"
elif [[ "${db_type}" == 'pgsql' ]]; then
db_reset_hint="volumes/postgres/data, ${db_reset_hint}"
fi
Expand Down
2 changes: 1 addition & 1 deletion .docker/scripts/wait-for-db.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

function dbIsUp(string $dbName): bool {
try {
if ($GLOBALS['dbType'] === 'mysql') {
if ($GLOBALS['dbType'] === 'mysql' || $GLOBALS['dbType'] === 'mariadb') {
$dsn = 'mysql:dbname='.getenv('MYSQL_DATABASE').';host='.$GLOBALS['dbHost'];
new PDO($dsn, getenv('MYSQL_USER'), getenv('MYSQL_PASSWORD'));
} elseif ($GLOBALS['dbType'] === 'pgsql') {
Expand Down
75 changes: 71 additions & 4 deletions .github/workflows/proxy-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ jobs:
DB_TYPE=sqlite sh ./dev-worker sqlite-b exec occ status | grep -q 'installed: true'
- name: Verify SQLite worker state isolation
run: |
DB_TYPE=sqlite sh ./dev-worker sqlite-a exec occ config:system:set worker_probe --value alpha
DB_TYPE=sqlite sh ./dev-worker sqlite-b exec occ config:system:set worker_probe --value beta
alpha="$(DB_TYPE=sqlite sh ./dev-worker sqlite-a exec occ config:system:get worker_probe | tail -n 1)"
beta="$(DB_TYPE=sqlite sh ./dev-worker sqlite-b exec occ config:system:get worker_probe | tail -n 1)"
DB_TYPE=sqlite sh ./dev-worker sqlite-a exec sh -c 'printf alpha > /var/www/html/data/worker-probe'
DB_TYPE=sqlite sh ./dev-worker sqlite-b exec sh -c 'printf beta > /var/www/html/data/worker-probe'
alpha="$(DB_TYPE=sqlite sh ./dev-worker sqlite-a exec cat /var/www/html/data/worker-probe)"
beta="$(DB_TYPE=sqlite sh ./dev-worker sqlite-b exec cat /var/www/html/data/worker-probe)"
printf 'sqlite-a worker_probe=%s\nsqlite-b worker_probe=%s\n' "$alpha" "$beta"
test "$alpha" = alpha
test "$beta" = beta
Expand All @@ -88,3 +88,70 @@ jobs:
run: |
DB_TYPE=sqlite sh ./dev-worker sqlite-a destroy || true
DB_TYPE=sqlite sh ./dev-worker sqlite-b destroy || true

mariadb-worker:
name: MariaDB ${{ matrix.mariadb }} worker integration
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
mariadb: ['10.6', '10.11']
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Build PHP 8.3 development image
run: docker build -f .docker/Dockerfile.php83 -t ghcr.io/librecodecoop/nextcloud-dev-php83:latest .docker
- name: Start MariaDB worker
env:
MARIADB_VERSION: ${{ matrix.mariadb }}
DB_SQL_MODE: ONLY_FULL_GROUP_BY
run: |
worker="maria-${MARIADB_VERSION//./-}"
DB_TYPE=mariadb sh ./dev-worker "$worker" up
- name: Verify MariaDB version and SQL mode
env:
MARIADB_VERSION: ${{ matrix.mariadb }}
DB_SQL_MODE: ONLY_FULL_GROUP_BY
run: |
worker="maria-${MARIADB_VERSION//./-}"
version="$(DB_TYPE=mariadb sh ./dev-worker "$worker" db-exec mariadb -uroot -proot -Nse 'SELECT VERSION()')"
case "$version" in
"$MARIADB_VERSION".*) ;;
*) echo "Unexpected MariaDB version: $version" >&2; exit 1 ;;
esac
DB_TYPE=mariadb sh ./dev-worker "$worker" db-exec mariadb -uroot -proot -Nse 'SELECT @@GLOBAL.sql_mode' | grep -q 'ONLY_FULL_GROUP_BY'
DB_TYPE=mariadb sh ./dev-worker "$worker" status | grep -q 'installed: true'
- name: Verify two-worker isolation
if: matrix.mariadb == '10.11'
env:
MARIADB_VERSION: ${{ matrix.mariadb }}
DB_SQL_MODE: ONLY_FULL_GROUP_BY
run: |
DB_TYPE=mariadb sh ./dev-worker maria-peer up
DB_TYPE=mariadb sh ./dev-worker maria-10-11 exec sh -c 'printf alpha > /var/www/html/data/worker-probe'
DB_TYPE=mariadb sh ./dev-worker maria-peer exec sh -c 'printf beta > /var/www/html/data/worker-probe'
alpha="$(DB_TYPE=mariadb sh ./dev-worker maria-10-11 exec cat /var/www/html/data/worker-probe)"
beta="$(DB_TYPE=mariadb sh ./dev-worker maria-peer exec cat /var/www/html/data/worker-probe)"
printf 'maria-10-11 worker_probe=%s\nmaria-peer worker_probe=%s\n' "$alpha" "$beta"
test "$alpha" = alpha
test "$beta" = beta
- name: Collect worker logs
if: failure()
env:
MARIADB_VERSION: ${{ matrix.mariadb }}
run: |
worker="maria-${MARIADB_VERSION//./-}"
DB_TYPE=mariadb sh ./dev-worker "$worker" logs || true
if [ "$MARIADB_VERSION" = 10.11 ]; then
DB_TYPE=mariadb sh ./dev-worker maria-peer logs || true
fi
- name: Destroy workers
if: always()
env:
MARIADB_VERSION: ${{ matrix.mariadb }}
run: |
worker="maria-${MARIADB_VERSION//./-}"
DB_TYPE=mariadb sh ./dev-worker "$worker" destroy || true
if [ "$MARIADB_VERSION" = 10.11 ]; then
DB_TYPE=mariadb sh ./dev-worker maria-peer destroy || true
fi
63 changes: 57 additions & 6 deletions dev-worker
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ Commands:
logs Print worker logs
config Render the resolved Compose configuration
status Run occ status in the worker
db-exec <command...> Run a command in the selected database container
destroy Stop the worker and remove only its mutable state

Environment:
DB_TYPE=sqlite|mysql|pgsql Database backend
DB_TYPE=sqlite|mysql|mariadb|pgsql Database backend
DB_HOST=<hostname> Connection hostname (defaults to DB_TYPE)
MARIADB_VERSION=10.6|10.11 MariaDB series (default: 10.11)
DB_SQL_MODE=<modes> Optional global SQL mode for MySQL-compatible backends
PHP_VERSION=<version> Existing PHP image selector
VERSION_NEXTCLOUD=<ref> Existing Nextcloud ref selector
WORKER_READY_TIMEOUT=180 Seconds to wait for a clean installation
Expand Down Expand Up @@ -53,11 +56,7 @@ repo_root="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
db_type="${DB_TYPE:-mysql}"

case "$db_type" in
sqlite|mysql|pgsql) ;;
mariadb)
echo "DB_TYPE=$db_type is reserved by the worker contract but is not implemented yet." >&2
exit 3
;;
sqlite|mysql|mariadb|pgsql) ;;
*)
echo "Unsupported DB_TYPE: $db_type" >&2
exit 2
Expand All @@ -74,6 +73,17 @@ export DB_HOST="${DB_HOST:-$db_type}"
if [ "$db_type" = "sqlite" ]; then
export DB_SERVICE_TYPE=mysql
export DB_DRIVER=sqlite
elif [ "$db_type" = "mariadb" ]; then
mariadb_version="${MARIADB_VERSION:-10.11}"
case "$mariadb_version" in
10.6) export DB_SERVICE_TYPE=mariadb106 ;;
10.11) export DB_SERVICE_TYPE=mariadb1011 ;;
*)
echo "Unsupported MARIADB_VERSION: $mariadb_version (supported: 10.6, 10.11)" >&2
exit 2
;;
esac
export DB_DRIVER=mysql
else
export DB_SERVICE_TYPE="${DB_SERVICE_TYPE:-$db_type}"
fi
Expand All @@ -82,6 +92,26 @@ compose() {
docker compose --project-directory "$repo_root" --file "$repo_root/docker-compose.yml" "$@"
}

wait_for_mariadb() {
timeout="${WORKER_READY_TIMEOUT:-180}"
started="$(date +%s)"

while :; do
if compose exec -T database mariadb-admin ping -h 127.0.0.1 -uroot -p"${MYSQL_ROOT_PASSWORD:-root}" --silent >/dev/null 2>&1; then
return 0
fi

now="$(date +%s)"
if [ $((now - started)) -ge "$timeout" ]; then
echo "MariaDB for worker $worker_id did not become ready within ${timeout}s." >&2
compose logs --no-color database >&2 || true
return 1
fi

sleep 1
done
}

wait_until_ready() {
timeout="${WORKER_READY_TIMEOUT:-180}"
started="$(date +%s)"
Expand All @@ -107,6 +137,16 @@ case "$command" in
mkdir -p "$worker_volumes_dir"
if [ "$db_type" = "sqlite" ]; then
compose up -d nextcloud nginx proxy-coordinator mailpit redis
elif [ "$db_type" = "mariadb" ]; then
compose up -d database
wait_for_mariadb
if [ -n "${DB_SQL_MODE:-}" ]; then
case "${DB_SQL_MODE}" in
*[!A-Z0-9_,]*) echo "DB_SQL_MODE contains unsupported characters" >&2; exit 2 ;;
esac
compose exec -T database mariadb -uroot -p"${MYSQL_ROOT_PASSWORD:-root}" -e "SET GLOBAL sql_mode='${DB_SQL_MODE}'"
fi
compose up -d
else
compose up -d
fi
Expand All @@ -129,6 +169,17 @@ case "$command" in
status)
compose exec -T nextcloud occ status
;;
db-exec)
[ "$db_type" != "sqlite" ] || {
echo "SQLite workers do not have a database container" >&2
exit 3
}
[ "$#" -gt 0 ] || {
echo "db-exec requires a command" >&2
exit 2
}
compose exec -T database "$@"
;;
destroy)
compose down --remove-orphans
# Mutable bind mounts contain files created by container UIDs. Clean the
Expand Down
17 changes: 15 additions & 2 deletions docs/advanced-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ The currently implemented backends are:

- `sqlite`
- `mysql` (default)
- `mariadb`
- `pgsql`

To use PostgreSQL:
Expand Down Expand Up @@ -78,8 +79,20 @@ DB_TYPE=sqlite sh ./dev-worker sqlite-a status
DB_TYPE=sqlite sh ./dev-worker sqlite-a destroy
```

MariaDB remains reserved by the `DB_TYPE` contract until its dedicated
backend implementation lands.
MariaDB workers support the 10.6 and 10.11 series without editing Compose YAML:

```bash
DB_TYPE=mariadb MARIADB_VERSION=10.6 sh ./dev-worker maria106 up
DB_TYPE=mariadb MARIADB_VERSION=10.11 sh ./dev-worker maria1011 up
```

The worker maps each supported series to a pinned image. Use `DB_SQL_MODE` to
request a deterministic global SQL mode when a test suite needs one:

```bash
DB_TYPE=mariadb MARIADB_VERSION=10.11 DB_SQL_MODE=ONLY_FULL_GROUP_BY \
sh ./dev-worker maria-full-group-by up
```

## Optional services

Expand Down
22 changes: 18 additions & 4 deletions tests/worker/contract.bats
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,24 @@ setup() {
[[ "$output" == *"DB_DRIVER: sqlite"* ]]
}

@test "MariaDB remains reserved for its dedicated implementation" {
run env DB_TYPE=mariadb sh "$WORKER" mariadb config
[ "$status" -eq 3 ]
[[ "$output" == *"not implemented yet"* ]]
@test "MariaDB 10.6 selects the pinned 10.6 service" {
run env DB_TYPE=mariadb MARIADB_VERSION=10.6 sh "$WORKER" maria106 config
[ "$status" -eq 0 ]
[[ "$output" == *"mariadb:10.6.28@sha256:23616f0bd3aff922f4dea4130f1d0a09f3571d20b7b36c8f49840672dc309e8c"* ]]
[[ "$output" == *"DB_TYPE: mariadb"* ]]
[[ "$output" == *"DB_DRIVER: mysql"* ]]
}

@test "MariaDB 10.11 selects the pinned 10.11 service" {
run env DB_TYPE=mariadb MARIADB_VERSION=10.11 sh "$WORKER" maria1011 config
[ "$status" -eq 0 ]
[[ "$output" == *"mariadb:10.11.19@sha256:07c0aaff7396b74cb7975cba78257178d188e30f531a5db2b617c48beef13c41"* ]]
}

@test "unsupported MariaDB versions fail before startup" {
run env DB_TYPE=mariadb MARIADB_VERSION=11.4 sh "$WORKER" maria114 config
[ "$status" -eq 2 ]
[[ "$output" == *"Unsupported MARIADB_VERSION"* ]]
}

@test "supported PHP images install PDO SQLite" {
Expand Down
Loading