Features: 1) Added validation to ensure scripts execute from project root with 'evibes' directory check; 2) Introduced color formatting and ASCII art for enhanced script output; 3) Added RAM, CPU, and disk space verification to installation scripts; 4) Ensured Docker images existence before service startup; 5) Unified spinner-based progress display in Windows and Unix scripts.

Fixes: 1) Replaced hardcoded paths with script-relative paths for better portability; 2) Corrected CPU and memory calculation logic for system checks; 3) Replaced inconsistent script formatting and error handling; 4) Resolved redundant cleanup steps post service startup.

Extra: Refactored and cleaned up script logic for maintainability; added WISELESS branding across scripts for consistency; enhanced terminal output and user messaging.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-06-16 15:40:44 +03:00
parent 6b829331c3
commit 7d1bcaa8d4
13 changed files with 681 additions and 216 deletions

12
scripts/ASCII_ART_EVIBES Normal file
View file

@ -0,0 +1,12 @@
=== ==. ===
.=== ==: ==== ===
==== ==- ===
==== === ===
=. ==== === .== === .===== =====- .===.
.=.= == = ===: ==- === ====. :===. ==== === .==:
.=::=== -= ===. ==- === === === ====::::::=== ===-
:== === === === === === === ====.
.. === === === === === === ====
= ====- === === === .===. . :===
.= == ==- === =:========. :========. ======.

View file

@ -1,26 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail
env_file='.env'
if [[ ! -f $env_file ]]; then
echo "Error: $env_file not found in the current directory." >&2
return 1 2>/dev/null || exit 1
if [ ! -d "./evibes" ]; then
printf "\e[31m❌ Please run this script from the project's root (where the 'evibes' directory lives).\e[0m\n"
exit 1
fi
while IFS= read -r line || [[ -n $line ]]; do
line="${line#"${line%%[![:space:]]*}"}"
line="${line%"${line##*[![:space:]]}"}"
[[ -z $line || $line == \#* ]] && continue
[[ $line != *"="* ]] && continue
PURPLE="\e[38;2;121;101;209m"
RESET="\e[0m"
GRAY="\e[90m"
SOURCE="${BASH_SOURCE[0]:-$0}"
SCRIPT_DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
ART_PATH="$SCRIPT_DIR/../ASCII_ART_EVIBES"
if [ ! -f "$ART_PATH" ]; then
printf "\e[31m❌ Could not find ASCII art at %s\e[0m\n" "$ART_PATH"
exit 1
fi
while IFS= read -r line; do
printf "%b%s%b\n" "$PURPLE" "$line" "$RESET"
done < "$ART_PATH"
printf "\n%bby WISELESS TEAM%b\n\n" "$GRAY" "$RESET"
ENV_FILE=".env"
if [ ! -f "$ENV_FILE" ]; then
printf "\e[31m.env file not found in the current directory.\e[0m\n"
exit 1
fi
declare -A env_vars
declare -a keys
while IFS= read -r raw; do
line="${raw%%#*}"
line="${line%"${line##*[![:space:]]}"}"
line="${line#"${line%%[![:space:]]*}"}"
[ -z "$line" ] || [[ "$line" != *=* ]] && continue
key="${line%%=*}"
value="${line#*=}"
if [[ ( $value == \"*\" && $value == *\" ) || ( $value == \'*\' && $value == *\' ) ]]; then
if [[ "${value:0:1}" == '"' && "${value: -1}" == '"' ]] || \
[[ "${value:0:1}" == "'" && "${value: -1}" == "'" ]]; then
value="${value:1:-1}"
fi
export "$key"="$value"
echo "Exported $key"
done < "$env_file"
env_vars["$key"]="$value"
keys+=("$key")
done < "$ENV_FILE"
if [ "${#keys[@]}" -gt 0 ]; then
IFS=$'\n' sorted=($(sort <<<"${keys[*]}"))
unset IFS
formatted=""
for k in "${sorted[@]}"; do
[ -z "$formatted" ] && formatted="$k=${env_vars[$k]}" \
|| formatted="$formatted;$k=${env_vars[$k]}"
done
printf "%s\n" "$formatted"
fi

View file

@ -1,122 +1,145 @@
#!/usr/bin/env bash
set -euo pipefail
rand_hex() {
openssl rand -hex "$1"
}
prompt_default() {
local name="$1" default="$2" val
read -rp "Enter $name [$default]: " val
printf -v "$name" '%s' "${val:-$default}"
}
prompt_autogen() {
local name="$1" bytes="$2" val
read -rp "Enter $name (leave blank to auto-generate): " val
if [[ -z "$val" ]]; then
printf -v "$name" '%s' "$(rand_hex "$bytes")"
else
printf -v "$name" '%s' "$val"
fi
}
prompt_default EVIBES_PROJECT_NAME "eVibes"
prompt_default EVIBES_FRONTEND_DOMAIN "evibes.com"
prompt_default EVIBES_BASE_DOMAIN "evibes.com"
prompt_default SENTRY_DSN ""
prompt_default DEBUG "1"
prompt_autogen SECRET_KEY 32
prompt_autogen JWT_SIGNING_KEY 64
prompt_default ALLOWED_HOSTS "evibes.com api.evibes.com b2b.evibes.com"
prompt_default CSRF_TRUSTED_ORIGINS "https://evibes.com https://api.evibes.com https://www.evibes.com https://b2b.evibes.com"
prompt_default CORS_ALLOWED_ORIGINS "$CSRF_TRUSTED_ORIGINS"
prompt_default POSTGRES_DB "evibes"
prompt_default POSTGRES_USER "evibes_user"
prompt_autogen POSTGRES_PASSWORD 16
prompt_default DBBACKUP_SFTP_HOST "Your SFTP backup host"
prompt_default DBBACKUP_SFTP_USER "The username to use to log in to that host"
prompt_default DBBACKUP_SFTP_PASS "The password to use to log in to that host"
prompt_autogen ELASTIC_PASSWORD 16
prompt_autogen REDIS_PASSWORD 16
prompt_default PROMETHEUS_USER "evibes"
prompt_autogen PROMETHEUS_PASSWORD 16
prompt_default EMAIL_BACKEND "django.core.mail.backends.smtp.EmailBackend"
prompt_default EMAIL_HOST "smtp.whatever.evibes.com"
prompt_default EMAIL_PORT "465"
prompt_default EMAIL_USE_TLS "0"
prompt_default EMAIL_USE_SSL "1"
prompt_default EMAIL_HOST_USER "your-email-user@whatever.evibes.com"
prompt_default EMAIL_FROM "$EMAIL_HOST_USER"
prompt_default EMAIL_HOST_PASSWORD "SUPERSECRETEMAILHOSTPASSWORD"
prompt_default COMPANY_NAME "eVibes, Inc."
prompt_default COMPANY_PHONE_NUMBER "+888888888888"
prompt_default COMPANY_ADDRESS "The place that does not exist"
prompt_default OPENAI_API_KEY "Haha, really?"
prompt_default ABSTRACT_API_KEY "Haha, really? x2"
prompt_default DEEPL_AUTH_KEY "Haha, really? x3"
if [[ -f .env ]]; then
read -rp ".env already exists and will be overwritten. Press ENTER to continue or Ctrl+C to abort. "
if [ ! -d "./evibes" ]; then
printf "\e[31m❌ Please run this script from the project's root (where the 'evibes' directory lives).\e[0m\n"
exit 1
fi
cat > .env <<EOF
EVIBES_PROJECT_NAME="${EVIBES_PROJECT_NAME}"
EVIBES_FRONTEND_DOMAIN="${EVIBES_FRONTEND_DOMAIN}"
EVIBES_BASE_DOMAIN="${EVIBES_BASE_DOMAIN}"
SENTRY_DSN="${SENTRY_DSN}"
DEBUG=${DEBUG}
PURPLE="\e[38;2;121;101;209m"
RESET="\e[0m"
GRAY="\e[90m"
SECRET_KEY="${SECRET_KEY}"
JWT_SIGNING_KEY="${JWT_SIGNING_KEY}"
SOURCE="${BASH_SOURCE[0]:-$0}"
SCRIPT_DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
ART_PATH="$SCRIPT_DIR/../ASCII_ART_EVIBES"
ALLOWED_HOSTS="${ALLOWED_HOSTS}"
CSRF_TRUSTED_ORIGINS="${CSRF_TRUSTED_ORIGINS}"
CORS_ALLOWED_ORIGINS="${CORS_ALLOWED_ORIGINS}"
if [ ! -f "$ART_PATH" ]; then
printf "\e[31m❌ Could not find ASCII art at %s\e[0m\n" "$ART_PATH"
exit 1
fi
POSTGRES_DB="${POSTGRES_DB}"
POSTGRES_USER="${POSTGRES_USER}"
POSTGRES_PASSWORD="${POSTGRES_PASSWORD}"
while IFS= read -r line; do
printf "%b%s%b\n" "$PURPLE" "$line" "$RESET"
done < "$ART_PATH"
DBBACKUP_SFTP_HOST="${DBBACKUP_SFTP_HOST}"
DBBACKUP_SFTP_USER="${DBBACKUP_SFTP_USER}"
DBBACKUP_SFTP_PASS="${DBBACKUP_SFTP_PASS}"
printf "\n%bby WISELESS TEAM%b\n\n" "$GRAY" "$RESET"
ELASTIC_PASSWORD="${ELASTIC_PASSWORD}"
# prompt for a value with default
prompt_default() {
local name="$1" default="$2" result
read -rp "Enter $name [$default]: " result
printf '%s\n' "${result:-$default}"
}
REDIS_PASSWORD="${REDIS_PASSWORD}"
# prompt for a value, auto-generate hex if blank
prompt_autogen() {
local name="$1" bytes="$2" result
read -rp "Enter $name (leave blank to auto-generate): " result
if [ -z "$result" ]; then
# generate $bytes random bytes as hex
result="$(head -c "$bytes" /dev/urandom | od -An -tx1 | tr -d ' \n')"
fi
printf '%s\n' "$result"
}
CELERY_BROKER_URL="redis://:${REDIS_PASSWORD}@redis:6379/0"
CELERY_RESULT_BACKEND="redis://:${REDIS_PASSWORD}@redis:6379/0"
if [ -f .env ]; then
printf "\e[33m.env already exists and will be overwritten.\e[0m\n"
read -rp "Press Enter to continue or Ctrl+C to abort"
fi
PROMETHEUS_USER="${PROMETHEUS_USER}"
PROMETHEUS_PASSWORD="${PROMETHEUS_PASSWORD}"
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')
SENTRY_DSN=$(prompt_default 'SENTRY_DSN' '')
DEBUG=$(prompt_default 'DEBUG' '1')
EMAIL_BACKEND="${EMAIL_BACKEND}"
EMAIL_HOST="${EMAIL_HOST}"
EMAIL_PORT="${EMAIL_PORT}"
EMAIL_USE_TLS=${EMAIL_USE_TLS}
EMAIL_USE_SSL=${EMAIL_USE_SSL}
EMAIL_HOST_USER="${EMAIL_HOST_USER}"
EMAIL_HOST_PASSWORD="${EMAIL_HOST_PASSWORD}"
EMAIL_FROM="${EMAIL_FROM}"
SECRET_KEY=$(prompt_autogen 'SECRET_KEY' 32)
JWT_SIGNING_KEY=$(prompt_autogen 'JWT_SIGNING_KEY' 64)
COMPANY_NAME="${COMPANY_NAME}"
COMPANY_PHONE_NUMBER="${COMPANY_PHONE_NUMBER}"
COMPANY_ADDRESS="${COMPANY_ADDRESS}"
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"
OPENAI_API_KEY="${OPENAI_API_KEY}"
ABSTRACT_API_KEY="${ABSTRACT_API_KEY}"
DEEPL_AUTH_KEY="${DEEPL_AUTH_KEY}"
EOF
POSTGRES_DB=$(prompt_default 'POSTGRES_DB' 'evibes')
POSTGRES_USER=$(prompt_default 'POSTGRES_USER' 'evibes_user')
POSTGRES_PASSWORD=$(prompt_autogen 'POSTGRES_PASSWORD' 16)
echo ".env file generated with fresh values."
DBBACKUP_SFTP_HOST=$(prompt_default 'DBBACKUP_SFTP_HOST' 'Your SFTP backup host')
DBBACKUP_SFTP_USER=$(prompt_default 'DBBACKUP_SFTP_USER' 'The username to use to log in to that host')
DBBACKUP_SFTP_PASS=$(prompt_default 'DBBACKUP_SFTP_PASS' 'The password to use to log in to that host')
ELASTIC_PASSWORD=$(prompt_autogen 'ELASTIC_PASSWORD' 16)
REDIS_PASSWORD=$(prompt_autogen 'REDIS_PASSWORD' 16)
PROMETHEUS_USER=$(prompt_default 'PROMETHEUS_USER' 'evibes')
PROMETHEUS_PASSWORD=$(prompt_autogen 'PROMETHEUS_PASSWORD' 16)
EMAIL_BACKEND=$(prompt_default 'EMAIL_BACKEND' 'django.core.mail.backends.smtp.EmailBackend')
EMAIL_HOST=$(prompt_default 'EMAIL_HOST' 'smtp.whatever.evibes.com')
EMAIL_PORT=$(prompt_default 'EMAIL_PORT' '465')
EMAIL_USE_TLS=$(prompt_default 'EMAIL_USE_TLS' '0')
EMAIL_USE_SSL=$(prompt_default 'EMAIL_USE_SSL' '1')
EMAIL_HOST_USER=$(prompt_default 'EMAIL_HOST_USER' 'your-email-user@whatever.evibes.com')
EMAIL_FROM="$EMAIL_HOST_USER"
EMAIL_HOST_PASSWORD=$(prompt_default 'EMAIL_HOST_PASSWORD' 'SUPERSECRETEMAILHOSTPASSWORD')
COMPANY_NAME=$(prompt_default 'COMPANY_NAME' 'eVibes, Inc.')
COMPANY_PHONE_NUMBER=$(prompt_default 'COMPANY_PHONE_NUMBER' '+888888888888')
COMPANY_ADDRESS=$(prompt_default 'COMPANY_ADDRESS' 'The place that does not exist')
OPENAI_API_KEY=$(prompt_default 'OPENAI_API_KEY' 'Haha, really?')
ABSTRACT_API_KEY=$(prompt_default 'ABSTRACT_API_KEY' 'Haha, really? x2')
DEEPL_AUTH_KEY=$(prompt_default 'DEEPL_AUTH_KEY' 'Haha, really? x3')
# Write to .env
{
printf 'EVIBES_PROJECT_NAME="%s"\n' "$PROJECT_NAME"
printf 'EVIBES_FRONTEND_DOMAIN="%s"\n' "$FRONTEND_DOMAIN"
printf 'EVIBES_BASE_DOMAIN="%s"\n' "$BASE_DOMAIN"
printf 'SENTRY_DSN="%s"\n' "$SENTRY_DSN"
printf 'DEBUG=%s\n\n' "$DEBUG"
printf 'SECRET_KEY="%s"\n' "$SECRET_KEY"
printf 'JWT_SIGNING_KEY="%s"\n\n' "$JWT_SIGNING_KEY"
printf 'ALLOWED_HOSTS="%s"\n' "$ALLOWED_HOSTS"
printf 'CSRF_TRUSTED_ORIGINS="%s"\n' "$CSRF_TRUSTED_ORIGINS"
printf 'CORS_ALLOWED_ORIGINS="%s"\n\n' "$CORS_ALLOWED_ORIGINS"
printf 'POSTGRES_DB="%s"\n' "$POSTGRES_DB"
printf 'POSTGRES_USER="%s"\n' "$POSTGRES_USER"
printf 'POSTGRES_PASSWORD="%s"\n\n' "$POSTGRES_PASSWORD"
printf 'DBBACKUP_SFTP_HOST="%s"\n' "$DBBACKUP_SFTP_HOST"
printf 'DBBACKUP_SFTP_USER="%s"\n' "$DBBACKUP_SFTP_USER"
printf 'DBBACKUP_SFTP_PASS="%s"\n\n' "$DBBACKUP_SFTP_PASS"
printf 'ELASTIC_PASSWORD="%s"\n\n' "$ELASTIC_PASSWORD"
printf 'REDIS_PASSWORD="%s"\n' "$REDIS_PASSWORD"
printf 'CELERY_BROKER_URL="redis://:%s@redis:6379/0"\n' "$REDIS_PASSWORD"
printf 'CELERY_RESULT_BACKEND="redis://:%s@redis:6379/0"\n\n' "$REDIS_PASSWORD"
printf 'PROMETHEUS_USER="%s"\n' "$PROMETHEUS_USER"
printf 'PROMETHEUS_PASSWORD="%s"\n\n' "$PROMETHEUS_PASSWORD"
printf 'EMAIL_BACKEND="%s"\n' "$EMAIL_BACKEND"
printf 'EMAIL_HOST="%s"\n' "$EMAIL_HOST"
printf 'EMAIL_PORT="%s"\n' "$EMAIL_PORT"
printf 'EMAIL_USE_TLS=%s\n' "$EMAIL_USE_TLS"
printf 'EMAIL_USE_SSL=%s\n' "$EMAIL_USE_SSL"
printf 'EMAIL_HOST_USER="%s"\n' "$EMAIL_HOST_USER"
printf 'EMAIL_HOST_PASSWORD="%s"\n' "$EMAIL_HOST_PASSWORD"
printf 'EMAIL_FROM="%s"\n\n' "$EMAIL_FROM"
printf 'COMPANY_NAME="%s"\n' "$COMPANY_NAME"
printf 'COMPANY_PHONE_NUMBER="%s"\n' "$COMPANY_PHONE_NUMBER"
printf 'COMPANY_ADDRESS="%s"\n\n' "$COMPANY_ADDRESS"
printf 'OPENAI_API_KEY="%s"\n\n' "$OPENAI_API_KEY"
printf 'ABSTRACT_API_KEY="%s"\n\n' "$ABSTRACT_API_KEY"
printf 'DEEPL_AUTH_KEY="%s"\n' "$DEEPL_AUTH_KEY"
} > .env
printf "\e[32m.env file generated with fresh values.\e[0m\n"

View file

@ -1,35 +1,63 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ ! -f .env ]]; then
echo "Warning: .env file not found. Exiting without running Docker steps."
if [ ! -d "./evibes" ]; then
printf "\e[31m❌ Please run this script from the project's root (where the 'evibes' directory lives).\e[0m\n"
exit 1
fi
PURPLE="\e[38;2;121;101;209m"
RESET="\e[0m"
GRAY="\e[90m"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ART_PATH="$SCRIPT_DIR/../ASCII_ART_EVIBES"
if [ ! -f "$ART_PATH" ]; then
printf "\e[31m❌ Could not find ASCII art at %s\e[0m\n" "$ART_PATH"
exit 1
fi
while IFS= read -r line; do
printf "%b%s%b\n" "$PURPLE" "$line" "$RESET"
done < "$ART_PATH"
printf "\n%bby WISELESS TEAM%b\n\n" "$GRAY" "$RESET"
if [ ! -f .env ]; then
printf "\e[33m.env file not found. Exiting without running Docker steps.\e[0m\n"
exit 0
fi
cpuCount=$(nproc)
if (( cpuCount < 4 )); then
echo "Error: Insufficient CPU cores: $cpuCount detected. Minimum 4 required." >&2
CPU_COUNT=$(nproc 2>/dev/null || sysctl -n hw.ncpu)
if [ "$CPU_COUNT" -lt 4 ]; then
printf "\e[31mInsufficient CPU cores: %d detected. Minimum 4 required.\e[0m\n" "$CPU_COUNT"
exit 1
fi
mem_kb=$(awk '/MemTotal:/ {print $2}' /proc/meminfo)
totalMemGB=$(awk "BEGIN {printf \"%.2f\", $mem_kb/1024/1024}")
if (( mem_kb < 6*1024*1024 )); then
echo "Error: Insufficient RAM: ${totalMemGB} GB detected. Minimum 6 GB required." >&2
if [ -f /proc/meminfo ]; then
MEM_KB=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
MEM_GB=$(awk "BEGIN {printf \"%.2f\", ${MEM_KB}/1024/1024}")
else
MEM_BYTES=$(vm_stat | awk '/Pages free/ {print $3 * 4096}')
MEM_GB=$(awk "BEGIN {printf \"%.2f\", ${MEM_BYTES}/1024/1024/1024}")
fi
if (( $(echo "$MEM_GB < 6" | bc -l) )); then
printf "\e[31mInsufficient RAM: %.2fGB detected. Minimum 6 GB required.\e[0m\n" "$MEM_GB"
exit 1
fi
avail_kb=$(df --output=avail . | tail -n1)
freeGB=$(awk "BEGIN {printf \"%.2f\", $avail_kb/1024/1024}")
if (( avail_kb < 20*1024*1024 )); then
echo "Error: Insufficient free disk space: ${freeGB} GB available. Minimum 20 GB required." >&2
FREE_GB=$(df -BG . | awk 'NR==2 {gsub("G","",$4); print $4}')
if [ "$FREE_GB" -lt 20 ]; then
printf "\e[31mInsufficient free disk space: %dGB available. Minimum 20 GB required.\e[0m\n" "$FREE_GB"
exit 1
fi
echo "System requirements met: CPU cores=${cpuCount}, RAM=${totalMemGB}GB, FreeDisk=${freeGB}GB"
printf "\e[32mSystem requirements met: CPU cores=%d, RAM=%.2fGB, FreeDisk=%dGB\e[0m\n" "$CPU_COUNT" "$MEM_GB" "$FREE_GB"
echo "Pulling related images..."
docker compose pull
printf "\e[36mPulling related images…\e[0m\n"
docker compose pull --ansi never
echo "Building the project's images..."
docker compose build
printf "\e[36mBuilding the project's images…\e[0m\n"
docker compose build --ansi never

View file

@ -1,35 +1,50 @@
#!/usr/bin/env bash
set -euo pipefail
run_cmd() {
local msg=$1; shift
printf "%s... " "$msg"
"$@"
printf "OK\n"
}
if [ ! -d "./evibes" ]; then
printf "\e[31m❌ Please run this script from the project's root (where the 'evibes' directory lives).\e[0m\n"
exit 1
fi
echo
PURPLE="\e[38;2;121;101;209m"
RESET="\e[0m"
GRAY="\e[90m"
CYAN="\e[36m"
run_cmd "Stopping services (down)" \
docker compose down
SOURCE="${BASH_SOURCE[0]:-$0}"
SCRIPT_DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
ART_PATH="$SCRIPT_DIR/../ASCII_ART_EVIBES"
run_cmd "Rebuilding services" \
docker compose build
if [ ! -f "$ART_PATH" ]; then
printf "\e[31m❌ Could not find ASCII art at %s\e[0m\n" "$ART_PATH"
exit 1
fi
run_cmd "Starting services" \
docker compose up -d
while IFS= read -r line; do
printf "%b%s%b\n" "$PURPLE" "$line" "$RESET"
done < "$ART_PATH"
run_cmd "Applying database migrations" \
docker compose exec app poetry run python manage.py migrate --no-input
printf "\n%bby WISELESS TEAM%b\n\n" "$GRAY" "$RESET"
run_cmd "Collecting static files" \
docker compose exec app poetry run python manage.py collectstatic --no-input
printf "%bStopping services…%b\n" "$CYAN" "$RESET"
docker compose down --ansi never
run_cmd "Setting default caches" \
docker compose exec app poetry run python manage.py set_default_caches
printf "%bRebuilding services…%b\n" "$CYAN" "$RESET"
docker compose build --ansi never
run_cmd "Cleaning up unused Docker data" \
docker system prune -f
printf "%bStarting services…%b\n" "$CYAN" "$RESET"
docker compose up -d --ansi never
echo
echo "All done! eVibes is up and running."
printf "%bApplying database migrations…%b\n" "$CYAN" "$RESET"
docker compose exec app poetry run python manage.py migrate --no-input
printf "%bCollecting static files…%b\n" "$CYAN" "$RESET"
docker compose exec app poetry run python manage.py collectstatic --no-input
printf "%bSetting default caches…%b\n" "$CYAN" "$RESET"
docker compose exec app poetry run python manage.py set_default_caches
printf "%bCleaning up unused Docker data…%b\n" "$CYAN" "$RESET"
docker system prune -f
printf "\n\e[37mAll done! eVibes is up and running.\e[0m\n"

View file

@ -1,11 +1,60 @@
#!/usr/bin/env bash
set -euo pipefail
echo "Starting Docker Compose services..."
if ! docker compose up --no-build --detach --wait; then
echo "Error: Images are not pulled/built. Please run the install.sh script first." >&2
if [ ! -d "./evibes" ]; then
printf "\e[31m❌ Please run this script from the project's root (where the 'evibes' directory lives).\e[0m\n"
exit 1
fi
echo "Containers are up and healthy."
PURPLE="\e[38;2;121;101;209m"
RESET="\e[0m"
GRAY="\e[90m"
SOURCE="${BASH_SOURCE[0]:-$0}"
SCRIPT_DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
ART_PATH="$SCRIPT_DIR/../ASCII_ART_EVIBES"
if [ ! -f "$ART_PATH" ]; then
printf "\e[31m❌ Could not find ASCII art at %s\e[0m\n" "$ART_PATH"
exit 1
fi
while IFS= read -r line; do
printf "%b%s%b\n" "$PURPLE" "$line" "$RESET"
done < "$ART_PATH"
printf "\n%bby WISELESS TEAM%b\n\n" "$GRAY" "$RESET"
printf "\e[32mVerifying all images are present…\e[0m\n"
if ! command -v jq >/dev/null 2>&1; then
printf "\e[31mjq is required for verifying images. Please install jq.\e[0m\n"
exit 1
fi
images=$(docker compose config --format json | jq -r '.services[]?.image // empty')
for image in $images; do
if ! docker image inspect "$image" >/dev/null 2>&1; then
printf "\e[31mRequired images not found. Please run install.sh first.\e[0m\n"
exit 1
fi
printf " • Found image: %s\n" "$image"
done
printf "\e[36mStarting services…\e[0m\n"
docker compose up --no-build --detach --wait --ansi never
printf "\e[36mApplying migrations…\e[0m\n"
docker compose exec app poetry run python manage.py migrate --no-input
printf "\e[36mCollecting static files…\e[0m\n"
docker compose exec app poetry run python manage.py collectstatic --no-input
printf "\e[36mSetting default caches…\e[0m\n"
docker compose exec app poetry run python manage.py set_default_caches
printf "\e[36mCleaning up…\e[0m\n"
docker compose exec app poetry run python manage.py set_default_caches
printf "\e[32mAll done! eVibes is up and running.\e[0m\n"

39
scripts/Unix/uninstall.sh Normal file
View file

@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -euo pipefail
if [ ! -d "./evibes" ]; then
printf "\e[31m❌ Please run this script from the project's root (where the 'evibes' directory lives).\e[0m\n"
exit 1
fi
PURPLE="\e[38;2;121;101;209m"
RESET="\e[0m"
GRAY="\e[90m"
CYAN="\e[36m"
RED="\e[31m"
SOURCE="${BASH_SOURCE[0]:-$0}"
SCRIPT_DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
ART_PATH="$SCRIPT_DIR/../ASCII_ART_EVIBES"
if [ ! -f "$ART_PATH" ]; then
printf "%b❌ Could not find ASCII art at %s%b\n" "$RED" "$ART_PATH" "$RESET"
exit 1
fi
while IFS= read -r line; do
printf "%b%s%b\n" "$PURPLE" "$line" "$RESET"
done < "$ART_PATH"
printf "\n%bby WISELESS TEAM%b\n\n" "$GRAY" "$RESET"
printf "%bKilling services…%b\n" "$CYAN" "$RESET"
docker compose down --ansi never
printf "%bCleaning up Docker data…%b\n" "$CYAN" "$RESET"
docker system prune -f
printf "%bRemoving related files…%b\n" "$CYAN" "$RESET"
rm -rf ./services_data ./media ./static
printf "%bBye-bye, hope you return later!%b\n" "$RED" "$RESET"

View file

@ -2,6 +2,62 @@
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
if (-not (Test-Path -Path ".\evibes" -PathType Container))
{
Write-Host "❌ Please run this script from the project's root (where the 'evibes' directory lives)." -ForegroundColor Red
exit 1
}
$purple = "`e[38;2;121;101;209m"
$reset = "`e[0m"
$artPath = Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Definition) '..\ASCII_ART_EVIBES'
if (-not (Test-Path $artPath))
{
Write-Host "❌ Could not find ASCII art at $artPath" -ForegroundColor Red
exit 1
}
$art = Get-Content -Raw -Path $artPath
$art -split "`r?`n" | ForEach-Object {
Write-Host "$purple$_$reset"
}
Write-Host "`nby WISELESS TEAM`n" -ForegroundColor Gray
$Spinner = @('|', '/', '-', '\')
$Colors = @('White', 'Gray')
$Delay = 100
function Invoke-Spinner
{
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$Arguments,
[Parameter(Mandatory)][string]$Message
)
Write-Host -NoNewLine -ForegroundColor Cyan ("{0}… " -f $Message)
$si = New-Object System.Diagnostics.ProcessStartInfo
$si.FileName = "docker"
$si.Arguments = "$Arguments --ansi never"
$si.RedirectStandardOutput = $true
$si.RedirectStandardError = $true
$si.UseShellExecute = $false
$p = [System.Diagnostics.Process]::Start($si)
$i = 0
while (-not $p.HasExited)
{
$frame = $Spinner[$i % $Spinner.Length]
$col = $Colors[$i % $Colors.Length]
Write-Host -NoNewLine -ForegroundColor $col $frame
Start-Sleep -Milliseconds $Delay
Write-Host -NoNewLine "`b"
$i++
}
$p.WaitForExit()
Write-Host -ForegroundColor Green ""
}
$envFile = '.env'
if (-not (Test-Path $envFile))

View file

@ -2,6 +2,29 @@
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
if (-not (Test-Path -Path ".\evibes" -PathType Container))
{
Write-Host "❌ Please run this script from the project's root (where the 'evibes' directory lives)." -ForegroundColor Red
exit 1
}
$purple = "`e[38;2;121;101;209m"
$reset = "`e[0m"
$artPath = Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Definition) '..\ASCII_ART_EVIBES'
if (-not (Test-Path $artPath))
{
Write-Host "❌ Could not find ASCII art at $artPath" -ForegroundColor Red
exit 1
}
$art = Get-Content -Raw -Path $artPath
$art -split "`r?`n" | ForEach-Object {
Write-Host "$purple$_$reset"
}
Write-Host "`nby WISELESS TEAM`n" -ForegroundColor Gray
function Get-RandomHex
{
param([int]$Bytes)

View file

@ -2,6 +2,29 @@
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
if (-not (Test-Path -Path ".\evibes" -PathType Container))
{
Write-Host "❌ Please run this script from the project's root (where the 'evibes' directory lives)." -ForegroundColor Red
exit 1
}
$purple = "`e[38;2;121;101;209m"
$reset = "`e[0m"
$artPath = Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Definition) '..\ASCII_ART_EVIBES'
if (-not (Test-Path $artPath))
{
Write-Host "❌ Could not find ASCII art at $artPath" -ForegroundColor Red
exit 1
}
$art = Get-Content -Raw -Path $artPath
$art -split "`r?`n" | ForEach-Object {
Write-Host "$purple$_$reset"
}
Write-Host "`nby WISELESS TEAM`n" -ForegroundColor Gray
if (-not (Test-Path '.env'))
{
Write-Warning ".env file not found. Exiting without running Docker steps."
@ -33,13 +56,40 @@ if ($freeGB -lt 20)
exit 1
}
Write-Host "System requirements met:" `
"CPU cores=$cpuCount," `
"RAM=${totalMemGB}GB," `
"FreeDisk=${freeGB}GB" -ForegroundColor Green
Write-Host "System requirements met: CPU cores=$cpuCount, RAM=${totalMemGB}GB, FreeDisk=${freeGB}GB" -ForegroundColor Green
Write-Host "Pulling related images..." -ForegroundColor Green
docker compose pull
$Spinner = @('|', '/', '-', '\')
$Colors = @('White', 'Gray')
$Delay = 100
Write-Host "Building the project's images..." -ForegroundColor Green
docker compose build
function Invoke-Spinner
{
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$Arguments,
[Parameter(Mandatory)][string]$Message
)
Write-Host -NoNewLine -ForegroundColor Cyan ("{0}… " -f $Message)
$si = New-Object System.Diagnostics.ProcessStartInfo
$si.FileName = "docker"
$si.Arguments = "$Arguments --ansi never"
$si.RedirectStandardOutput = $true
$si.RedirectStandardError = $true
$si.UseShellExecute = $false
$p = [System.Diagnostics.Process]::Start($si)
$i = 0
while (-not $p.HasExited)
{
$frame = $Spinner[$i % $Spinner.Length]
$col = $Colors[$i % $Colors.Length]
Write-Host -NoNewLine -ForegroundColor $col $frame
Start-Sleep -Milliseconds $Delay
Write-Host -NoNewline "`b"
$i++
}
$p.WaitForExit()
Write-Host -ForegroundColor Green ""
}
Invoke-Spinner -Arguments "compose pull" -Message "Pulling related images"
Invoke-Spinner -Arguments "compose build" -Message "Building the project's images"

View file

@ -1,5 +1,28 @@
$ErrorActionPreference = 'Stop'
if (-not (Test-Path -Path ".\evibes" -PathType Container))
{
Write-Host "❌ Please run this script from the project's root (where the 'evibes' directory lives)." -ForegroundColor Red
exit 1
}
$purple = "`e[38;2;121;101;209m"
$reset = "`e[0m"
$artPath = Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Definition) '..\ASCII_ART_EVIBES'
if (-not (Test-Path $artPath))
{
Write-Host "❌ Could not find ASCII art at $artPath" -ForegroundColor Red
exit 1
}
$art = Get-Content -Raw -Path $artPath
$art -split "`r?`n" | ForEach-Object {
Write-Host "$purple$_$reset"
}
Write-Host "`nby WISELESS TEAM`n" -ForegroundColor Gray
$Spinner = @('|', '/', '-', '\')
$Colors = @('White', 'Gray')
$Delay = 100
@ -8,53 +31,37 @@ function Invoke-Spinner
{
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$Arguments,
[Parameter(Mandatory)]
[string]$Message
[Parameter(Mandatory)][string]$Arguments,
[Parameter(Mandatory)][string]$Message
)
Write-Host -NoNewLine -ForegroundColor Cyan ("{0}... " -f $Message)
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = "docker"
$startInfo.Arguments = $Arguments + " --ansi never"
$startInfo.RedirectStandardOutput = $true
$startInfo.RedirectStandardError = $true
$startInfo.UseShellExecute = $false
$proc = [System.Diagnostics.Process]::Start($startInfo)
Write-Host -NoNewLine -ForegroundColor Cyan ("{0}… " -f $Message)
$si = New-Object System.Diagnostics.ProcessStartInfo
$si.FileName = "docker"
$si.Arguments = "$Arguments --ansi never"
$si.RedirectStandardOutput = $true
$si.RedirectStandardError = $true
$si.UseShellExecute = $false
$p = [System.Diagnostics.Process]::Start($si)
$i = 0
while (-not $proc.HasExited)
while (-not $p.HasExited)
{
$frame = $Spinner[$i % $Spinner.Length]
$color = $Colors[$i % $Colors.Length]
Write-Host -NoNewLine -ForegroundColor $color $frame
$col = $Colors[$i % $Colors.Length]
Write-Host -NoNewLine -ForegroundColor $col $frame
Start-Sleep -Milliseconds $Delay
Write-Host -NoNewLine "`b"
Write-Host -NoNewline "`b"
$i++
}
$proc.WaitForExit()
$p.WaitForExit()
Write-Host -ForegroundColor Green ""
}
Write-Host ""
Invoke-Spinner -Arguments "compose down" `
-Message "Stopping services (down)"
Invoke-Spinner -Arguments "compose build" `
-Message "Rebuilding services"
Invoke-Spinner -Arguments "compose up -d" `
-Message "Starting services"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py migrate --no-input" `
-Message "Applying database migrations"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py collectstatic --no-input" `
-Message "Collecting static files"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py set_default_caches" `
-Message "Setting default caches"
Invoke-Spinner -Arguments "system prune -f" `
-Message "Cleaning up unused Docker data"
Invoke-Spinner -Arguments "compose down" -Message "Stopping services"
Invoke-Spinner -Arguments "compose build" -Message "Rebuilding services"
Invoke-Spinner -Arguments "compose up -d" -Message "Starting services"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py migrate --no-input" -Message "Applying database migrations"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py collectstatic --no-input" -Message "Collecting static files"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py set_default_caches" -Message "Setting default caches"
Invoke-Spinner -Arguments "system prune -f" -Message "Cleaning up unused Docker data"
Write-Host "`nAll done! eVibes is up and running." -ForegroundColor White

View file

@ -2,6 +2,29 @@
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
if (-not (Test-Path -Path ".\evibes" -PathType Container))
{
Write-Host "❌ Please run this script from the project's root (where the 'evibes' directory lives)." -ForegroundColor Red
exit 1
}
$purple = "`e[38;2;121;101;209m"
$reset = "`e[0m"
$artPath = Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Definition) '..\ASCII_ART_EVIBES'
if (-not (Test-Path $artPath))
{
Write-Host "❌ Could not find ASCII art at $artPath" -ForegroundColor Red
exit 1
}
$art = Get-Content -Raw -Path $artPath
$art -split "`r?`n" | ForEach-Object {
Write-Host "$purple$_$reset"
}
Write-Host "`nby WISELESS TEAM`n" -ForegroundColor Gray
Write-Host "Verifying all images are present…" -ForegroundColor Green
$config = docker compose config --format json | ConvertFrom-Json
@ -26,6 +49,43 @@ foreach ($prop in $config.services.PSObject.Properties)
Write-Host " • Found image: $image"
}
Write-Host "All images present, starting services…" -ForegroundColor Green
docker compose up --no-build --detach --wait | Out-Null
Write-Host "Containers are up and healthy." -ForegroundColor Green
$Spinner = @('|', '/', '-', '\')
$Colors = @('White', 'Gray')
$Delay = 100
function Invoke-Spinner
{
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$Arguments,
[Parameter(Mandatory)][string]$Message
)
Write-Host -NoNewLine -ForegroundColor Cyan ("{0}… " -f $Message)
$si = New-Object System.Diagnostics.ProcessStartInfo
$si.FileName = "docker"
$si.Arguments = "$Arguments --ansi never"
$si.RedirectStandardOutput = $true
$si.RedirectStandardError = $true
$si.UseShellExecute = $false
$p = [System.Diagnostics.Process]::Start($si)
$i = 0
while (-not $p.HasExited)
{
$frame = $Spinner[$i % $Spinner.Length]
$col = $Colors[$i % $Colors.Length]
Write-Host -NoNewLine -ForegroundColor $col $frame
Start-Sleep -Milliseconds $Delay
Write-Host -NoNewLine "`b"
$i++
}
$p.WaitForExit()
Write-Host -ForegroundColor Green ""
}
Invoke-Spinner -Arguments "compose up --no-build --detach --wait" -Message "Starting services"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py migrate --no-input" -Message "Applying migrations"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py collectstatic --no-input" -Message "Collecting static files"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py set_default_caches" -Message "Setting default caches"
Invoke-Spinner -Arguments "compose exec app poetry run python manage.py set_default_caches" -Message "Cleaning up"
Write-Host "All done! eVibes is up and running." -ForegroundColor Green

View file

@ -0,0 +1,67 @@
#!/usr/bin/env pwsh
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
if (-not (Test-Path -Path ".\evibes" -PathType Container))
{
Write-Host "❌ Please run this script from the project's root (where the 'evibes' directory lives)." -ForegroundColor Red
exit 1
}
$purple = "`e[38;2;121;101;209m"
$reset = "`e[0m"
$artPath = Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Definition) '..\ASCII_ART_EVIBES'
if (-not (Test-Path $artPath))
{
Write-Host "❌ Could not find ASCII art at $artPath" -ForegroundColor Red
exit 1
}
$art = Get-Content -Raw -Path $artPath
$art -split "`r?`n" | ForEach-Object {
Write-Host "$purple$_$reset"
}
Write-Host "`nby WISELESS TEAM`n" -ForegroundColor Gray
$Spinner = @('|', '/', '-', '\')
$Colors = @('White', 'Gray')
$Delay = 100
function Invoke-Spinner
{
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$Arguments,
[Parameter(Mandatory)][string]$Message
)
Write-Host -NoNewLine -ForegroundColor Cyan ("{0}… " -f $Message)
$si = New-Object System.Diagnostics.ProcessStartInfo
$si.FileName = "docker"
$si.Arguments = "$Arguments --ansi never"
$si.RedirectStandardOutput = $true
$si.RedirectStandardError = $true
$si.UseShellExecute = $false
$p = [System.Diagnostics.Process]::Start($si)
$i = 0
while (-not $p.HasExited)
{
$frame = $Spinner[$i % $Spinner.Length]
$col = $Colors[$i % $Colors.Length]
Write-Host -NoNewLine -ForegroundColor $col $frame
Start-Sleep -Milliseconds $Delay
Write-Host -NoNewline "`b"
$i++
}
$p.WaitForExit()
Write-Host -ForegroundColor Green ""
}
Invoke-Spinner -Arguments "compose down" -Message "Killing services"
Invoke-Spinner -Arguments "system prune -f" -Message "Cleaning up Docker data"
Write-Host -ForegroundColor Cyan "Removing related files..."
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue ./services_data
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue ./media
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue ./static
Write-Host -ForegroundColor Red "Bye-bye, hope you return later!"