#!/bin/sh set -eu ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) if [ ! -f "$ROOT/.env" ]; then echo "Missing $ROOT/.env." >&2 exit 1 fi set -a # shellcheck source=/dev/null . "$ROOT/.env" set +a PROJECT=${WNH_DEV_COMPOSE_PROJECT:-who_need_help} EXPECTED_DATABASE=${WNH_DEV_SCALE_EXPECTED_DATABASE:-who_need_help} REQUESTS=${WNH_DEV_SCALE_REQUESTS:-1000000} ACTIVITIES=${WNH_DEV_SCALE_ACTIVITIES:-1000000} WEB_CONTAINER=${PROJECT}-web-1 DB_CONTAINER=${PROJECT}-db-1 NETWORK=${PROJECT}_internal TOOLS_IMAGE=who-need-help:dev-scale-tools OUTPUT_DIR="$ROOT/output/dev-scale" SUMMARY="$OUTPUT_DIR/summary.json" container_label() { docker inspect "$1" --format "{{index .Config.Labels \"$2\"}}" } container_env() { docker inspect "$WEB_CONTAINER" --format '{{range .Config.Env}}{{println .}}{{end}}' | sed -n "s/^$1=//p" } require_positive_integer() { case "$2" in ''|*[!0-9]*|0) echo "$1 must be a positive integer." >&2 exit 2 ;; esac } require_positive_integer WNH_DEV_SCALE_REQUESTS "$REQUESTS" require_positive_integer WNH_DEV_SCALE_ACTIVITIES "$ACTIVITIES" for container in "$WEB_CONTAINER" "$DB_CONTAINER"; do if ! docker inspect "$container" >/dev/null 2>&1; then echo "Required development container $container does not exist." >&2 exit 1 fi if [ "$(docker inspect "$container" --format '{{.State.Running}}')" != true ]; then echo "Required development container $container is not running." >&2 exit 1 fi if [ "$(container_label "$container" com.docker.compose.project)" != "$PROJECT" ]; then echo "Container $container does not belong to Compose project $PROJECT." >&2 exit 1 fi done if [ "$(container_label "$WEB_CONTAINER" com.docker.compose.service)" != web ]; then echo "$WEB_CONTAINER is not the development web service." >&2 exit 1 fi if [ "$(container_label "$DB_CONTAINER" com.docker.compose.service)" != db ]; then echo "$DB_CONTAINER is not the development database service." >&2 exit 1 fi if ! docker network inspect "$NETWORK" >/dev/null 2>&1; then echo "Development network $NETWORK does not exist." >&2 exit 1 fi DATABASE_URL=$(container_env DATABASE_URL) SECRET_KEY_BASE=$(container_env SECRET_KEY_BASE) HANDOVER_SECRET=$(container_env HANDOVER_SECRET) RELEASE_COOKIE=$(container_env RELEASE_COOKIE) METRICS_TOKEN=$(container_env METRICS_TOKEN) PHX_HOST=$(container_env PHX_HOST) PHX_SCHEME=$(container_env PHX_SCHEME) PHX_URL_PORT=$(container_env PHX_URL_PORT) DB_USER=$( docker inspect "$DB_CONTAINER" --format '{{range .Config.Env}}{{println .}}{{end}}' | sed -n 's/^POSTGRES_USER=//p' ) DB_NAME=$( docker inspect "$DB_CONTAINER" --format '{{range .Config.Env}}{{println .}}{{end}}' | sed -n 's/^POSTGRES_DB=//p' ) if [ -z "${DEV_SCALE_VIEWER_PASSWORD:-}" ]; then echo "DEV_SCALE_VIEWER_PASSWORD must be set in the project .env." >&2 exit 1 fi for pair in \ "DATABASE_URL:$DATABASE_URL" \ "SECRET_KEY_BASE:$SECRET_KEY_BASE" \ "HANDOVER_SECRET:$HANDOVER_SECRET" \ "RELEASE_COOKIE:$RELEASE_COOKIE" \ "METRICS_TOKEN:$METRICS_TOKEN" \ "PHX_HOST:$PHX_HOST" \ "PHX_SCHEME:$PHX_SCHEME" \ "PHX_URL_PORT:$PHX_URL_PORT"; do name=${pair%%:*} value=${pair#*:} if [ -z "$value" ]; then echo "The running development web container is missing $name." >&2 exit 1 fi done export DATABASE_URL SECRET_KEY_BASE HANDOVER_SECRET RELEASE_COOKIE METRICS_TOKEN export PHX_HOST PHX_SCHEME PHX_URL_PORT SCALE_VIEWER_PASSWORD=$DEV_SCALE_VIEWER_PASSWORD export SCALE_VIEWER_PASSWORD if [ -z "$DB_USER" ] || [ -z "$DB_NAME" ]; then echo "The running development database container is missing POSTGRES_USER or POSTGRES_DB." >&2 exit 1 fi actual_database=$( docker exec "$DB_CONTAINER" \ psql -U "$DB_USER" -d "$DB_NAME" -Atc "SELECT current_database()" ) if [ "$actual_database" != "$EXPECTED_DATABASE" ]; then echo "Refusing dev-scale mutation: expected database $EXPECTED_DATABASE, observed $actual_database." >&2 exit 1 fi mkdir -p "$OUTPUT_DIR" docker build --target load_tools --tag "$TOOLS_IMAGE" "$ROOT" docker run --rm \ --network "$NETWORK" \ --env APP_ROLE=migrate \ --env DATABASE_URL \ --env POOL_SIZE=2 \ --env ERL_ZFLAGS='+Q 65536 +S 1:1' \ --env SECRET_KEY_BASE \ --env HANDOVER_SECRET \ --env RELEASE_COOKIE \ --env METRICS_TOKEN \ --env PHX_HOST \ --env PHX_SCHEME \ --env PHX_URL_PORT \ --env SCALE_VIEWER_PASSWORD \ --env EMAIL_FROM_NAME='Who Need Help development scale fixtures' \ --env EMAIL_FROM_ADDRESS=dev-scale@example.invalid \ --env WNH_SCALE_EXPECTED_DATABASE="$EXPECTED_DATABASE" \ --env WNH_SCALE_FIXTURE_CONFIRM=persistent-dev-scale \ --volume "$OUTPUT_DIR:/output" \ "$TOOLS_IMAGE" \ mix wnh.scale_fixtures append \ --requests "$REQUESTS" \ --activities "$ACTIVITIES" \ --output /output/summary.json docker run --rm \ --volume "$OUTPUT_DIR:/output" \ alpine:3.23.3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 \ chown -R "$(id -u):$(id -g)" /output printf 'Development scale summary: %s\n' "$SUMMARY"