-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeploy.sh
More file actions
executable file
·201 lines (179 loc) · 9.26 KB
/
Copy pathdeploy.sh
File metadata and controls
executable file
·201 lines (179 loc) · 9.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# be.CLEAR — Script de build et déploiement Docker
#
# Usage : ./deploy.sh [--instance=NOM] [--no-migrate] [--no-search-setup] [--clean]
#
# Multi-instance : chaque instance est isolée (containers, volumes, réseau, ports).
# ./deploy.sh --instance=be-clear-1 → charge .env.be-clear-1
# ./deploy.sh → charge .env (instance par défaut)
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
# ─── Couleurs ────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
info() { echo -e "${CYAN}[INFO]${RESET} $*"; }
success() { echo -e "${GREEN}[OK]${RESET} $*"; }
warn() { echo -e "${YELLOW}[WARN]${RESET} $*"; }
error() { echo -e "${RED}[ERR]${RESET} $*" >&2; exit 1; }
# ─── Arguments ───────────────────────────────────────────────────────────────
INSTANCE="beclear"
DO_MIGRATE=true
DO_SEARCH=true
DO_CLEAN=false
for arg in "$@"; do
case $arg in
--instance=*) INSTANCE="${arg#*=}" ;;
--no-migrate) DO_MIGRATE=false ;;
--no-search-setup) DO_SEARCH=false ;;
--clean) DO_CLEAN=true ;;
--help|-h)
echo "Usage: $0 [--instance=NOM] [--no-migrate] [--no-search-setup] [--clean]"
echo ""
echo " --instance=NOM Nom de l'instance (défaut : beclear)"
echo " Charge le fichier .env.NOM (ou .env si absent)"
echo " --no-migrate Ne pas lancer les migrations Alembic"
echo " --no-search-setup Ne pas (re)configurer l'index Meilisearch"
echo " --clean Supprimer les anciens containers/volumes avant de démarrer"
echo ""
echo "Exemples :"
echo " $0 # instance par défaut (beclear)"
echo " $0 --instance=be-clear-1 # instance nommée, charge .env.be-clear-1"
echo " $0 --instance=be-clear-2 --clean"
exit 0
;;
*) warn "Argument inconnu : $arg (ignoré)" ;;
esac
done
# ─── Fichier .env de l'instance ──────────────────────────────────────────────
if [ "$INSTANCE" = "beclear" ]; then
ENV_FILE=".env"
else
ENV_FILE=".env.${INSTANCE}"
fi
# ─── En-tête ─────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}be.CLEAR — Déploiement Docker${RESET}"
echo -e " Instance : ${CYAN}${INSTANCE}${RESET}"
echo -e " Env file : ${CYAN}${ENV_FILE}${RESET}"
echo "─────────────────────────────────────────────"
# ─── Prérequis ───────────────────────────────────────────────────────────────
command -v docker &>/dev/null || error "Docker n'est pas installé ou pas dans le PATH."
docker compose version &>/dev/null || error "Le plugin 'docker compose' (v2) est requis."
# ─── Fichier .env ────────────────────────────────────────────────────────────
if [ ! -f "$ENV_FILE" ]; then
if [ -f .env.example ]; then
warn "${ENV_FILE} absent — copie depuis .env.example"
cp .env.example "$ENV_FILE"
error "Éditez ${ENV_FILE} (mots de passe, clés JWT, ports…) puis relancez le script."
else
error "Fichier ${ENV_FILE} introuvable et .env.example absent."
fi
fi
success "${ENV_FILE} trouvé"
# Charge les variables pour pouvoir les lire dans le script
set -o allexport
# shellcheck source=.env
source "$ENV_FILE"
set +o allexport
# Vérification des variables critiques
REQUIRED_VARS=(POSTGRES_USER POSTGRES_PASSWORD POSTGRES_DB MEILISEARCH_MASTER_KEY SECRET_KEY)
for var in "${REQUIRED_VARS[@]}"; do
val="${!var:-}"
if [ -z "$val" ] || [[ "$val" == changeme* ]]; then
error "Variable $var non définie ou toujours à la valeur par défaut dans ${ENV_FILE}."
fi
done
success "Variables d'environnement validées"
# Ports effectifs (après lecture du .env)
F_PORT="${FRONTEND_PORT:-3000}"
B_PORT="${BACKEND_PORT:-8000}"
M_PORT="${MEILI_PORT:-7700}"
# ─── Alias docker compose avec projet + env file ─────────────────────────────
DC="docker compose -p ${INSTANCE} --env-file ${ENV_FILE}"
# ─── Nettoyage optionnel ──────────────────────────────────────────────────────
if $DO_CLEAN; then
warn "Option --clean : suppression des containers et volumes de l'instance ${INSTANCE}..."
read -r -p " Confirmer la suppression des données ? [o/N] " confirm
if [[ "$confirm" =~ ^[oO]$ ]]; then
$DC down -v --remove-orphans
success "Nettoyage effectué"
else
info "Nettoyage annulé"
fi
fi
# ─── Build des images ─────────────────────────────────────────────────────────
info "Build des images Docker..."
$DC build --parallel
success "Images construites"
# ─── Démarrage des services ───────────────────────────────────────────────────
info "Démarrage des services..."
$DC up -d
success "Services démarrés"
# ─── Attente que le backend soit prêt ────────────────────────────────────────
info "Attente du backend (max 60s)..."
BACKEND_URL="http://localhost:${B_PORT}/docs"
ELAPSED=0
until curl -sf "$BACKEND_URL" &>/dev/null; do
sleep 3
ELAPSED=$((ELAPSED + 3))
if [ $ELAPSED -ge 60 ]; then
warn "Le backend ne répond pas après 60s — consultez les logs :"
warn " $DC logs backend"
break
fi
echo -n "."
done
echo ""
if curl -sf "$BACKEND_URL" &>/dev/null; then
success "Backend opérationnel"
fi
# ─── Migrations Alembic ───────────────────────────────────────────────────────
if $DO_MIGRATE; then
info "Vérification des migrations Alembic..."
$DC exec -T backend alembic upgrade head
success "Migrations vérifiées"
fi
# ─── Configuration Meilisearch ────────────────────────────────────────────────
if $DO_SEARCH; then
info "Configuration de l'index Meilisearch..."
MEILI_URL="http://localhost:${M_PORT}"
MEILI_KEY="$MEILISEARCH_MASTER_KEY"
ELAPSED=0
until curl -sf "$MEILI_URL/health" &>/dev/null; do
sleep 2
ELAPSED=$((ELAPSED + 2))
[ $ELAPSED -ge 30 ] && error "Meilisearch ne répond pas après 30s."
done
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$MEILI_URL/indexes" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $MEILI_KEY" \
-d '{"uid":"objets","primaryKey":"id"}')
[ "$HTTP_CODE" == "202" ] || [ "$HTTP_CODE" == "409" ] \
|| warn "Création de l'index — code HTTP inattendu : $HTTP_CODE"
curl -sf -X PATCH "$MEILI_URL/indexes/objets/settings" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $MEILI_KEY" \
-d '{
"searchableAttributes": ["nom","description","values_text","cla_nom"],
"filterableAttributes": ["entity_type","cla_nom"]
}' > /dev/null
success "Index Meilisearch configuré"
fi
# ─── Résumé ───────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}${GREEN}Déploiement terminé avec succès !${RESET}"
echo "─────────────────────────────────────────────"
echo -e " Instance ${CYAN}${INSTANCE}${RESET}"
echo -e " Frontend ${CYAN}http://localhost:${F_PORT}${RESET}"
echo -e " Backend ${CYAN}http://localhost:${B_PORT}/docs${RESET}"
echo -e " Recherche ${CYAN}http://localhost:${M_PORT}${RESET}"
echo ""
echo " Logs : $DC logs -f"
echo " Arrêt : $DC down"
echo " Migration : $DC exec backend alembic upgrade head"
echo ""