Files
minerops/scripts/seed-development-demo.sh
2026-08-26 15:48:59 +00:00

108 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${repo_root}"
env_file="${MINEROPS_DEMO_ENV_FILE:-.env.dev}"
project_name="${MINEROPS_DEMO_PROJECT:-minerops-dev}"
mode="${1:-seed}"
usage() {
cat <<'EOF'
Usage: scripts/seed-development-demo.sh [--reseed]
Seeds the current Docker development database with deterministic synthetic data.
--reseed reapplies the mutable demo projections without deleting immutable history.
EOF
}
case "${mode}" in
seed) [[ $# -eq 0 ]] || { usage >&2; exit 2; } ;;
--reseed) [[ $# -eq 1 ]] || { usage >&2; exit 2; } ;;
-h|--help) usage; exit 0 ;;
*) usage >&2; exit 2 ;;
esac
[[ -f "${env_file}" ]] || { echo "Missing development environment file: ${env_file}" >&2; exit 1; }
[[ -f compose.dev.yaml ]] || { echo "Missing compose.dev.yaml." >&2; exit 1; }
[[ -f sql/development-demo.sql ]] || { echo "Missing sql/development-demo.sql." >&2; exit 1; }
env_value() {
awk -F= -v wanted="$1" '
$1 == wanted {
sub(/^[^=]*=/, "")
gsub(/\r$/, "")
print
exit
}
' "${env_file}"
}
app_env="$(env_value APP_ENV)"
database_name="$(env_value POSTGRES_DB)"
database_host="$(env_value POSTGRES_HOST)"
if [[ "${app_env}" != "development" ]]; then
echo "Refusing demo seed: APP_ENV must be exactly development." >&2
exit 1
fi
if [[ ! "${database_name}" =~ (^|_)(dev|development|test)(_|$) ]]; then
echo "Refusing demo seed: POSTGRES_DB must be clearly named for development or testing." >&2
exit 1
fi
if [[ "${database_name,,}" =~ (prod|production|live) ]]; then
echo "Refusing demo seed: POSTGRES_DB resembles a production database." >&2
exit 1
fi
if [[ "${database_host}" != "postgres" ]]; then
echo "Refusing demo seed: POSTGRES_HOST must be the compose.dev.yaml postgres service." >&2
exit 1
fi
compose=(
docker compose
--project-name "${project_name}"
--env-file "${env_file}"
-f compose.dev.yaml
)
"${compose[@]}" config --quiet
if ! "${compose[@]}" ps --status running --services | grep -qx postgres; then
echo "Development PostgreSQL is not running for project ${project_name}." >&2
echo "Start it with: docker compose --project-name ${project_name} --env-file ${env_file} -f compose.dev.yaml up -d" >&2
exit 1
fi
migration_head="$(
"${compose[@]}" exec -T postgres sh -ec \
'psql -v ON_ERROR_STOP=1 -At -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT version_num FROM alembic_version"'
)"
if [[ "${migration_head}" != "0016_agent_zones" ]]; then
echo "Refusing demo seed: database Alembic head is ${migration_head:-missing}, expected 0016_agent_zones." >&2
exit 1
fi
if [[ "${mode}" == "--reseed" ]]; then
echo "Reapplying deterministic demo projections; immutable repair and MAC history will not be rewritten."
else
echo "Seeding deterministic MinerOps development demo data..."
fi
"${compose[@]}" exec -T postgres sh -ec \
'psql -v ON_ERROR_STOP=1 -v app_env=development -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
< sql/development-demo.sql
"${compose[@]}" exec -T postgres sh -ec \
'psql -v ON_ERROR_STOP=1 -At -F " | " -U "$POSTGRES_USER" -d "$POSTGRES_DB"' <<'SQL'
SELECT
'demo summary',
count(*) FILTER (WHERE asset_tag LIKE 'DEMO-MIN-%') || ' miners',
(SELECT count(*) FROM location_positions WHERE source_file = 'MinerOps demo seed') || ' positions',
(SELECT count(*) FROM location_positions WHERE source_file = 'MinerOps demo seed' AND miner_id IS NULL) || ' empty',
(SELECT count(*) FROM repairs WHERE id::text LIKE 'd4000000-0000-4000-8000-%') || ' repairs'
FROM miners;
SQL
echo "Demo data is ready at the configured development gateway."