0ebb39150f
- Add SKIP_MIGRATION environment variable to control automatic Prisma migrations in backend - Update Dockerfile to conditionally run migrations based on SKIP_MIGRATION flag - Enhance deploy.sh with: - Better error handling using set -euo pipefail - New --skip-migration flag to bypass automatic migration startup - Improved documentation and help text - New helper functions for waiting on services and database - Better status reporting for migration results - Update compose.yml to include SKIP_MIGRATION environment variable
231 lines
8.4 KiB
Bash
Executable File
231 lines
8.4 KiB
Bash
Executable File
#!/bin/bash
|
||
# deploy.sh – Bygg och starta om recipe-app
|
||
# Kör från: /opt/containers/recipe-app/
|
||
# Kräver: .env-fil i samma mapp
|
||
#
|
||
# Användning:
|
||
# ./deploy.sh – bygg allt (backend + flutter + importer)
|
||
# ./deploy.sh --backend – bygg bara backend (snabbast, ~2-3 min)
|
||
# ./deploy.sh --flutter – bygg bara flutter web-app
|
||
# ./deploy.sh --importer – bygg bara importer-microservice
|
||
# ./deploy.sh --seed – kör full seed på databasen (opt-in)
|
||
# ./deploy.sh --migrate – kör Prisma-migrationer explicit (opt-in)
|
||
# ./deploy.sh --skip-migration – hoppa över automatisk startup-migrering i recipe-api
|
||
# ./deploy.sh --clean-database – kör underhålls-SQL som rensar data men behåller kategorier
|
||
# ./deploy.sh --pull-always – kontrollera uppdateringar för basimages
|
||
# ./deploy.sh --backend --seed – kombinera flaggor fritt (git pull körs alltid)
|
||
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
cd "$SCRIPT_DIR"
|
||
START_TS="$(date +%s)"
|
||
|
||
# ── Flaggor ──────────────────────────────────────────────────────────────────
|
||
BUILD_BACKEND=false
|
||
BUILD_FLUTTER=false
|
||
BUILD_IMPORTER=false
|
||
RUN_SEED=false
|
||
RUN_MIGRATE=false
|
||
RUN_CLEAN_DATABASE=false
|
||
SKIP_MIGRATION=false
|
||
PULL_IMAGES=false # --pull=false är standard (snabbt)
|
||
BUILD_ALL=true # om inga specifika tjänster anges, bygg allt
|
||
|
||
# ── Hjälpfunktioner ───────────────────────────────────────────────────────────
|
||
info() { echo "[INFO] $*"; }
|
||
warn() { echo "[WARN] $*"; }
|
||
fatal() { echo "[ERROR] $*"; exit 1; }
|
||
|
||
require_cmd() {
|
||
command -v "$1" >/dev/null 2>&1 || fatal "Kommando saknas: $1"
|
||
}
|
||
|
||
read_env_value() {
|
||
local key="$1"
|
||
local line
|
||
line=$(grep -E "^${key}=" .env | tail -n 1 || true)
|
||
line="${line#*=}"
|
||
line="${line%\"}"
|
||
line="${line#\"}"
|
||
line="${line%\'}"
|
||
line="${line#\'}"
|
||
printf '%s' "$line"
|
||
}
|
||
|
||
wait_for_backend_prisma() {
|
||
info "Väntar på att backend är redo för Prisma-kommandon..."
|
||
for i in $(seq 1 30); do
|
||
if docker exec recipe-api sh -lc "test -f /app/prisma/schema.prisma" >/dev/null 2>&1; then
|
||
return 0
|
||
fi
|
||
info " ...försök $i/30"
|
||
sleep 2
|
||
done
|
||
return 1
|
||
}
|
||
|
||
wait_for_db() {
|
||
local root_password="$1"
|
||
info "Väntar på att databasen är redo..."
|
||
for i in $(seq 1 30); do
|
||
if docker exec recipe-db mariadb-admin ping -h 127.0.0.1 -uroot -p"$root_password" --silent 2>/dev/null; then
|
||
return 0
|
||
fi
|
||
info " ...försök $i/30"
|
||
sleep 2
|
||
done
|
||
return 1
|
||
}
|
||
|
||
run_prisma_migrate_deploy() {
|
||
local output
|
||
info "Kör Prisma-migrationer (deploy)..."
|
||
info " ▶ Kör: npx prisma migrate deploy"
|
||
|
||
if ! output=$(docker exec recipe-api sh -lc "cd /app && npx prisma migrate deploy --schema prisma/schema.prisma" 2>&1); then
|
||
echo "$output"
|
||
fatal "Prisma migration misslyckades."
|
||
fi
|
||
|
||
echo "$output"
|
||
|
||
if echo "$output" | grep -qi "No pending migrations"; then
|
||
info "Migration-status: inga väntande migrationer."
|
||
elif echo "$output" | grep -qi "Applying migration"; then
|
||
info "Migration-status: minst en migration applicerades."
|
||
else
|
||
warn "Migration-status: kunde inte avgöra om nya migrationer applicerades."
|
||
fi
|
||
|
||
info "Migrationer slutförda utan fel."
|
||
}
|
||
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
--backend) BUILD_BACKEND=true; BUILD_ALL=false ;;
|
||
--flutter) BUILD_FLUTTER=true; BUILD_ALL=false ;;
|
||
--importer) BUILD_IMPORTER=true; BUILD_ALL=false ;;
|
||
--seed) RUN_SEED=true ;;
|
||
--migrate) RUN_MIGRATE=true; BUILD_BACKEND=true; BUILD_ALL=false ;;
|
||
--skip-migration) SKIP_MIGRATION=true ;;
|
||
--clean-database) RUN_CLEAN_DATABASE=true; BUILD_BACKEND=true; BUILD_ALL=false ;;
|
||
--pull-always) PULL_IMAGES=true ;;
|
||
--help|-h)
|
||
sed -n '/^# Användning:/,/^[^#]/p' "$0" | grep '^#' | sed 's/^# \?//'
|
||
exit 0
|
||
;;
|
||
*) fatal "Okänd flagga: $arg (--help för hjälp)" ;;
|
||
esac
|
||
done
|
||
|
||
if [ "$BUILD_ALL" = true ]; then
|
||
BUILD_BACKEND=true
|
||
BUILD_FLUTTER=true
|
||
BUILD_IMPORTER=true
|
||
fi
|
||
|
||
# Om explicit migration begärs, stäng av automigrering i containern för att undvika dubbelkörning.
|
||
if [ "$RUN_MIGRATE" = true ]; then
|
||
SKIP_MIGRATION=true
|
||
fi
|
||
|
||
# ── Validering ────────────────────────────────────────────────────────────────
|
||
[ -f ".env" ] || fatal ".env saknas. Kör: cp .env.example .env && nano .env"
|
||
|
||
require_cmd git
|
||
require_cmd docker
|
||
|
||
if [ "$BUILD_BACKEND" = true ] || [ "$RUN_SEED" = true ] || [ "$RUN_CLEAN_DATABASE" = true ] || [ "$RUN_MIGRATE" = true ]; then
|
||
require_cmd grep
|
||
fi
|
||
|
||
export SKIP_MIGRATION
|
||
COMPOSE_CMD=(docker compose -f compose.yml -f compose.flutter.yml)
|
||
|
||
# ── Git pull ──────────────────────────────────────────────────────────────────
|
||
info "Hämtar senaste kod (recipe-app)..."
|
||
git pull origin main
|
||
|
||
if [ -d "$SCRIPT_DIR/../microservice-importer/.git" ]; then
|
||
info "Hämtar senaste kod (microservice-importer)..."
|
||
(cd "$SCRIPT_DIR/../microservice-importer" && git pull origin main)
|
||
else
|
||
warn "microservice-importer repo hittades inte på förväntad path, hoppar över git pull där."
|
||
fi
|
||
|
||
# ── Bygger valda tjänster ─────────────────────────────────────────────────────
|
||
SERVICES=()
|
||
[ "$BUILD_BACKEND" = true ] && SERVICES+=(recipe-api)
|
||
[ "$BUILD_FLUTTER" = true ] && SERVICES+=(recipe-flutter)
|
||
[ "$BUILD_IMPORTER" = true ] && SERVICES+=(importer-api)
|
||
|
||
if [ "${#SERVICES[@]}" -eq 0 ]; then
|
||
info "Bygger: alla tjänster..."
|
||
else
|
||
info "Bygger: ${SERVICES[*]}"
|
||
fi
|
||
|
||
if [ "$PULL_IMAGES" = true ]; then
|
||
info "(kontrollerar uppdateringar för basimages...)"
|
||
"${COMPOSE_CMD[@]}" build "${SERVICES[@]}"
|
||
else
|
||
"${COMPOSE_CMD[@]}" build --pull=false "${SERVICES[@]}"
|
||
fi
|
||
|
||
info "Startar tjänster..."
|
||
"${COMPOSE_CMD[@]}" up -d
|
||
|
||
# ── Prisma migreringar och databasrensning (opt-in) ─────────────────────────
|
||
if [ "$RUN_MIGRATE" = true ] || [ "$RUN_CLEAN_DATABASE" = true ]; then
|
||
CLEAN_SQL_FILE="backend/prisma/maintenance/clean-database.sql"
|
||
|
||
wait_for_backend_prisma || fatal "Backend blev inte redo för Prisma-kommandon i tid."
|
||
|
||
if [ "$RUN_MIGRATE" = true ]; then
|
||
run_prisma_migrate_deploy
|
||
fi
|
||
|
||
if [ "$RUN_CLEAN_DATABASE" = true ]; then
|
||
[ -f "$CLEAN_SQL_FILE" ] || fatal "Saknar $CLEAN_SQL_FILE"
|
||
|
||
MARIADB_ROOT_PASSWORD="$(read_env_value MARIADB_ROOT_PASSWORD)"
|
||
MARIADB_DATABASE="$(read_env_value MARIADB_DATABASE)"
|
||
|
||
[ -n "$MARIADB_ROOT_PASSWORD" ] || fatal "MARIADB_ROOT_PASSWORD saknas i .env"
|
||
[ -n "$MARIADB_DATABASE" ] || fatal "MARIADB_DATABASE saknas i .env"
|
||
|
||
info "Kör databasrensning från $CLEAN_SQL_FILE ..."
|
||
docker exec -i recipe-db mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" "$MARIADB_DATABASE" < "$CLEAN_SQL_FILE"
|
||
info "Databasrensning klar (kategorier bevarade enligt SQL-filen)."
|
||
fi
|
||
|
||
info "Uppdaterar Prisma Client..."
|
||
docker exec recipe-api sh -lc "cd /app && npx prisma generate --schema prisma/schema.prisma"
|
||
fi
|
||
|
||
# ── Seed (opt-in) ─────────────────────────────────────────────────────────────
|
||
if [ "$RUN_SEED" = true ]; then
|
||
MARIADB_ROOT_PASSWORD="$(read_env_value MARIADB_ROOT_PASSWORD)"
|
||
MARIADB_DATABASE="$(read_env_value MARIADB_DATABASE)"
|
||
|
||
[ -n "$MARIADB_ROOT_PASSWORD" ] || fatal "MARIADB_ROOT_PASSWORD saknas i .env"
|
||
[ -n "$MARIADB_DATABASE" ] || fatal "MARIADB_DATABASE saknas i .env"
|
||
|
||
wait_for_db "$MARIADB_ROOT_PASSWORD" || fatal "Databasen blev inte redo i tid."
|
||
|
||
if [ -f "db/seeds/seed_all.sql" ]; then
|
||
docker exec -i recipe-db mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" "$MARIADB_DATABASE" < db/seeds/seed_all.sql
|
||
info "Full seed klar."
|
||
else
|
||
warn "Ingen db/seeds/seed_all.sql hittades — hoppar över seed."
|
||
fi
|
||
fi
|
||
|
||
info "Status:"
|
||
"${COMPOSE_CMD[@]}" ps
|
||
|
||
END_TS="$(date +%s)"
|
||
DURATION="$((END_TS - START_TS))"
|
||
info "Deploy klart på ${DURATION}s."
|