Files
Classeo/deploy/vps/generate-demo-data.sh
Mathias STRASSER 8c70ed1324
Some checks failed
CI / Backend Tests (push) Has been cancelled
CI / Frontend Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Naming Conventions (push) Has been cancelled
CI / Build Check (push) Has been cancelled
fix(tenant): route runtime traffic to tenant databases
Wire Doctrine's default connection to the tenant database resolved from the subdomain for HTTP requests and tenant-scoped Messenger messages while keeping master-only services on the master connection.

This removes the production inconsistency where demo data, migrations and tenant commands used the tenant database but the web runtime still read from master.
2026-03-10 23:38:26 +01:00

227 lines
5.3 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR=$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)
ROOT_DIR=$(cd -- "${SCRIPT_DIR}/../.." && pwd)
ENV_FILE="${CLASSEO_ENV_FILE:-${SCRIPT_DIR}/.env}"
COMPOSE_FILE="${CLASSEO_COMPOSE_FILE:-${ROOT_DIR}/compose.prod.yaml}"
PHP_SERVICE="${CLASSEO_PHP_SERVICE:-php}"
usage() {
cat <<EOF
Usage: ./deploy/vps/generate-demo-data.sh [options]
Generate a full demo dataset inside the tenant database used by the VPS deployment.
Options:
--tenant SUBDOMAIN Tenant subdomain. Defaults to TENANT_SUBDOMAIN from ${ENV_FILE}.
--password PASSWORD Shared password for all generated accounts.
Default: DemoPassword123!
--school NAME School name displayed on generated accounts.
--zone ZONE School zone: A, B or C. Default: B
--period-type TYPE Academic period type: trimester or semester.
Default: trimester
--target TARGET Where to write demo data: master or tenant.
Default: tenant
--env-file PATH Override env file path. Default: ${ENV_FILE}
--compose-file PATH Override compose file path. Default: ${COMPOSE_FILE}
--service NAME Override PHP service name. Default: ${PHP_SERVICE}
-h, --help Show this help.
Examples:
./deploy/vps/generate-demo-data.sh
./deploy/vps/generate-demo-data.sh --password 'Demo2026!'
./deploy/vps/generate-demo-data.sh --tenant demo --school 'College de demo'
./deploy/vps/generate-demo-data.sh --target master
EOF
}
prompt_with_default() {
local label="${1}"
local default_value="${2:-}"
local answer
if [ -n "${default_value}" ]; then
printf "%s [%s]: " "${label}" "${default_value}" >&2
else
printf "%s: " "${label}" >&2
fi
IFS= read -r answer
printf '%s\n' "${answer:-${default_value}}"
}
require_file() {
local path="${1}"
local label="${2}"
if [ ! -f "${path}" ]; then
echo "Missing ${label}: ${path}" >&2
exit 1
fi
}
ensure_command() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "Required command not found: $1" >&2
exit 1
fi
}
TENANT=""
PASSWORD="DemoPassword123!"
SCHOOL=""
ZONE="B"
PERIOD_TYPE="trimester"
TARGET="tenant"
while [ "$#" -gt 0 ]; do
case "$1" in
--tenant)
TENANT="${2:-}"
shift 2
;;
--tenant=*)
TENANT="${1#*=}"
shift
;;
--password)
PASSWORD="${2:-}"
shift 2
;;
--password=*)
PASSWORD="${1#*=}"
shift
;;
--school)
SCHOOL="${2:-}"
shift 2
;;
--school=*)
SCHOOL="${1#*=}"
shift
;;
--zone)
ZONE="${2:-}"
shift 2
;;
--zone=*)
ZONE="${1#*=}"
shift
;;
--period-type)
PERIOD_TYPE="${2:-}"
shift 2
;;
--period-type=*)
PERIOD_TYPE="${1#*=}"
shift
;;
--target)
TARGET="${2:-}"
shift 2
;;
--target=*)
TARGET="${1#*=}"
shift
;;
--env-file)
ENV_FILE="${2:-}"
shift 2
;;
--env-file=*)
ENV_FILE="${1#*=}"
shift
;;
--compose-file)
COMPOSE_FILE="${2:-}"
shift 2
;;
--compose-file=*)
COMPOSE_FILE="${1#*=}"
shift
;;
--service)
PHP_SERVICE="${2:-}"
shift 2
;;
--service=*)
PHP_SERVICE="${1#*=}"
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
echo >&2
usage >&2
exit 1
;;
esac
done
ensure_command docker
require_file "${ENV_FILE}" "env file"
require_file "${COMPOSE_FILE}" "compose file"
set -a
# shellcheck disable=SC1090
. "${ENV_FILE}"
set +a
if [ -z "${TENANT}" ]; then
TENANT="${TENANT_SUBDOMAIN:-}"
fi
if [ -z "${TENANT}" ] && [ -t 0 ]; then
TENANT=$(prompt_with_default "Tenant subdomain" "demo")
fi
if [ -z "${TENANT}" ]; then
echo "Tenant subdomain is required. Pass --tenant or define TENANT_SUBDOMAIN in ${ENV_FILE}." >&2
exit 1
fi
case "${TARGET}" in
master|tenant)
;;
*)
echo "Invalid target: ${TARGET}. Expected 'master' or 'tenant'." >&2
exit 1
;;
esac
if [ -z "${SCHOOL}" ] && [ -t 0 ]; then
SCHOOL=$(prompt_with_default "School name (optional)" "")
fi
COMMAND=(
docker compose
--env-file "${ENV_FILE}"
-f "${COMPOSE_FILE}"
exec "${PHP_SERVICE}"
php bin/console app:dev:generate-demo-data
"--tenant=${TENANT}"
"--password=${PASSWORD}"
"--zone=${ZONE}"
"--period-type=${PERIOD_TYPE}"
)
if [ "${TARGET}" = "master" ]; then
COMMAND+=("--internal-run")
fi
if [ -n "${SCHOOL}" ]; then
COMMAND+=("--school=${SCHOOL}")
fi
echo "Running demo data generator for tenant: ${TENANT}"
echo "Compose file: ${COMPOSE_FILE}"
echo "Env file: ${ENV_FILE}"
echo "Target database: ${TARGET}"
echo
"${COMMAND[@]}"