From 0dc3daaa4fc0aa83bcb82b32cebfa6d6b3d5a317 Mon Sep 17 00:00:00 2001 From: Egor fureunoir Gorbunov Date: Tue, 28 Oct 2025 15:31:26 +0300 Subject: [PATCH] Features: 1) Add fallback for missing jq in image verification; 2) Enhance verbosity control for management commands in `run.sh`; 3) Update `generate-environment-file.sh` to use consistent variable names and handle CORS origins dynamically. Fixes: 1) Correct `.env` export script to handle sorted variables without associative arrays; 2) Fix incomplete `.env` output in `generate-environment-file.sh`. Extra: 1) Improve code readability and maintainability across shell scripts; 2) Standardize echo statements and reduce excessive formatting. --- scripts/Unix/export-environment-file.sh | 39 +++++++-------- scripts/Unix/generate-environment-file.sh | 61 +++++++++++++++++++++-- scripts/Unix/run.sh | 36 +++++++------ 3 files changed, 96 insertions(+), 40 deletions(-) diff --git a/scripts/Unix/export-environment-file.sh b/scripts/Unix/export-environment-file.sh index f6572466..575b809b 100755 --- a/scripts/Unix/export-environment-file.sh +++ b/scripts/Unix/export-environment-file.sh @@ -9,27 +9,26 @@ if [ ! -f "$env_file" ]; then exit 1 fi -declare -A env_vars -while IFS= read -r line; do - line="${line#"${line%%[![:space:]]*}"}" - line="${line%"${line##*[![:space:]]}"}" - if [ -z "$line" ] || [[ "$line" == \#* ]] || [[ "$line" != *=* ]]; then - continue - fi - key="${line%%=*}" - value="${line#*=}" - if [[ ( "$value" == \"*\" && "$value" == *\" ) || ( "$value" == \'*\' && "$value" == *\' ) ]]; then - value="${value:1:-1}" +# Read .env and export variables; collect for sorted output (portable: no associative arrays) +mapfile -t lines < <(sed -e 's/^\s*//;s/\s*$//' "$env_file" | awk 'NF && $0 !~ /^#/ && $0 ~ /=/') + +kv_list=() +for raw in "${lines[@]}"; do + key=${raw%%=*} + value=${raw#*=} + # Trim whitespace around key and value + key=$(echo "$key" | sed -e 's/^\s*//' -e 's/\s*$//') + value=$(echo "$value" | sed -e 's/^\s*//' -e 's/\s*$//') + # Strip matching quotes + if [ -n "$value" ] && [ "${value:0:1}" = '"' ] && [ "${value: -1}" = '"' ]; then + value=${value:1:${#value}-2} + elif [ -n "$value" ] && [ "${value:0:1}" = "'" ] && [ "${value: -1}" = "'" ]; then + value=${value:1:${#value}-2} fi export "$key=$value" - env_vars["$key"]="$value" -done < "$env_file" + kv_list+=("$key=$value") +done -if [ "${#env_vars[@]}" -gt 0 ]; then - IFS=$'\n' sorted=($(for k in "${!env_vars[@]}"; do echo "${k}=${env_vars[$k]}"; done | sort)) - printf "%s" "${sorted[0]}" - for entry in "${sorted[@]:1}"; do - printf ";%s" "$entry" - done - echo +if [ ${#kv_list[@]} -gt 0 ]; then + printf "%s\n" "${kv_list[@]}" | sort | tr "\n" ";" | sed 's/;$/\n/' fi diff --git a/scripts/Unix/generate-environment-file.sh b/scripts/Unix/generate-environment-file.sh index 47703cdf..7c57d637 100755 --- a/scripts/Unix/generate-environment-file.sh +++ b/scripts/Unix/generate-environment-file.sh @@ -33,9 +33,9 @@ if [ -f .env ]; then read -r fi -PROJECT_NAME=$(prompt_default EVIBES_PROJECT_NAME eVibes) -FRONTEND_DOMAIN=$(prompt_default EVIBES_FRONTEND_DOMAIN evibes.com) -BASE_DOMAIN=$(prompt_default EVIBES_BASE_DOMAIN evibes.com) +EVIBES_PROJECT_NAME=$(prompt_default EVIBES_PROJECT_NAME eVibes) +EVIBES_FRONTEND_DOMAIN=$(prompt_default EVIBES_FRONTEND_DOMAIN evibes.com) +EVIBES_BASE_DOMAIN=$(prompt_default EVIBES_BASE_DOMAIN evibes.com) SENTRY_DSN=$(prompt_default SENTRY_DSN "") DEBUG=$(prompt_default DEBUG 1) TIME_ZONE=$(prompt_default TIME_ZONE "Europe/London") @@ -45,7 +45,7 @@ JWT_SIGNING_KEY=$(prompt_autogen JWT_SIGNING_KEY 64) ALLOWED_HOSTS=$(prompt_default ALLOWED_HOSTS "evibes.com api.evibes.com b2b.evibes.com") CSRF_TRUSTED_ORIGINS=$(prompt_default CSRF_TRUSTED_ORIGINS "https://evibes.com https://api.evibes.com https://www.evibes.com https://b2b.evibes.com") -CORS_ALLOWED_ORIGINS=$CSRF_TRUSTED_ORIGINS +CORS_ALLOWED_ORIGINS=$(prompt_default CORS_ALLOWED_ORIGINS "$CSRF_TRUSTED_ORIGINS") POSTGRES_DB=$(prompt_default POSTGRES_DB evibes) POSTGRES_USER=$(prompt_default POSTGRES_USER evibes_user) @@ -80,4 +80,55 @@ ABSTRACT_API_KEY=$(prompt_default ABSTRACT_API_KEY "Haha, really? x2") DEEPL_AUTH_KEY=$(prompt_default DEEPL_AUTH_KEY "Haha, really? x3") cat > .env < /dev/null 2>&1; then - echo "Required images not found. Please run install.sh first." >&2 - exit 1 +echo "Verifying all images are present..." +if command -v jq >/dev/null 2>&1; then + images=$(docker compose config --format json | jq -r '.services[].image // empty') + if [ -n "$images" ]; then + for image in $images; do + if ! docker image inspect "$image" > /dev/null 2>&1; then + echo "Required images not found. Please run install.sh first." >&2 + exit 1 + fi + echo " - Found image: $image" + done fi - echo " • Found image: $image" -done +else + echo "jq is not installed; skipping image verification step." +fi -echo "Spinning services up…" +echo "Spinning services up..." docker compose up --no-build --detach --wait echo "Services are up and healthy!" -echo "Applying migrations…" -docker compose exec app uv run python manage.py migrate --no-input +echo "Applying migrations..." +docker compose exec app uv run python manage.py migrate --no-input --verbosity 0 echo "Migrations applied successfully!" -echo "Collecting static files…" -docker compose exec app uv run python manage.py collectstatic --clear --no-input +echo "Collecting static files..." +docker compose exec app uv run python manage.py collectstatic --clear --no-input --verbosity 0 echo "Static files collected successfully!" -echo "Setting default caches…" +echo "Setting default caches..." docker compose exec app uv run python manage.py set_default_caches echo "Default caches set successfully!" -echo "Cleaning unused Docker data…" +echo "Cleaning unused Docker data..." docker system prune -f echo "Unused Docker data cleaned successfully!"