lecoffre_node/scripts/startup-sequence.sh

716 lines
22 KiB
Bash
Executable File

#!/bin/bash
# Script de démarrage amélioré pour lecoffre_node
# Utilise les healthchecks du docker-compose.yml pour une séquence optimisée
# Intègre la validation des dépendances externes
set -e
# Couleurs pour les logs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
EXTERNAL_SIGNER_HOST="dev3.4nkweb.com"
EXTERNAL_SIGNER_PORT="9090"
PUBLIC_FRONT_URL="https://dev4.4nkweb.com/lecoffre"
PUBLIC_IHM_URL="https://dev4.4nkweb.com"
# Projets avec Docker (images à construire)
DOCKER_PROJECTS=("sdk_relay" "sdk_storage" "sdk_signer" "ihm_client" "lecoffre-front" "lecoffre-back-mini")
# Projets sans Docker (libraries/packages)
LIBRARY_PROJECTS=("sdk_client" "sdk_common" "sdk-signer-client")
# Fonction de logging
log() {
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}
log_success() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] ✅${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] ⚠️${NC} $1"
}
log_error() {
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ❌${NC} $1"
}
# Fonction de validation des dépendances externes
validate_external_dependencies() {
log "Validation des dépendances externes..."
local all_ok=true
# Test du signer distant
log "Test de connectivité vers le signer distant ($EXTERNAL_SIGNER_HOST:$EXTERNAL_SIGNER_PORT)..."
if timeout 10 bash -c "</dev/tcp/$EXTERNAL_SIGNER_HOST/$EXTERNAL_SIGNER_PORT" 2>/dev/null; then
log_success "Signer distant accessible"
else
log_error "Signer distant non accessible"
all_ok=false
fi
# Test des URLs publiques
log "Test de connectivité vers les URLs publiques..."
if curl -s --connect-timeout 10 --max-time 15 "$PUBLIC_FRONT_URL" >/dev/null 2>&1; then
log_success "LeCoffre Front accessible"
else
log_warning "LeCoffre Front non accessible (peut être normal si pas encore démarré)"
fi
if curl -s --connect-timeout 10 --max-time 15 "$PUBLIC_IHM_URL" >/dev/null 2>&1; then
log_success "IHM Client accessible"
else
log_warning "IHM Client non accessible (peut être normal si pas encore démarré)"
fi
return $([ "$all_ok" = true ] && echo 0 || echo 1)
}
# Fonction pour attendre qu'un service soit prêt
wait_for_service() {
local service_name=$1
local health_url=$2
local timeout=${3:-300}
echo "⏳ Attente de $service_name..."
local start_time=$(date +%s)
while [ $(($(date +%s) - start_time)) -lt $timeout ]; do
if curl -f -s "$health_url" > /dev/null 2>&1; then
echo "$service_name est prêt"
return 0
fi
sleep 5
done
echo "❌ Timeout: $service_name n'est pas prêt après ${timeout}s"
return 1
}
# Fonction pour synchroniser les configurations
sync_configurations() {
log "Synchronisation des configurations centralisées..."
if [[ -f "./scripts/sync-configs.sh" ]]; then
if ./scripts/sync-configs.sh; then
log_success "Configurations synchronisées"
else
log_warning "Échec de la synchronisation des configurations"
fi
else
log_warning "Script de synchronisation non trouvé"
fi
}
# Fonction pour mettre à jour les dépendances d'un projet
update_project_dependencies() {
local project="$1"
local project_path="/home/debian/$project"
log "Mise à jour des dépendances pour $project"
if [[ ! -d "$project_path" ]]; then
log_error "Projet non trouvé: $project_path"
return 1
fi
cd "$project_path"
# Rust projects
if [[ -f "Cargo.toml" ]]; then
log "Mise à jour des dépendances Rust..."
if cargo update; then
log_success "Dépendances Rust mises à jour"
else
log_warning "Échec de la mise à jour des dépendances Rust"
fi
fi
# Node.js projects
if [[ -f "package.json" ]]; then
log "Mise à jour des dépendances Node.js..."
if npm update; then
log_success "Dépendances Node.js mises à jour"
else
log_warning "Échec de la mise à jour des dépendances Node.js"
fi
fi
}
# Fonction pour vérifier les fichiers ignore d'un projet
check_project_ignore_files() {
local project="$1"
local project_path="/home/debian/$project"
log "Vérification des fichiers ignore pour $project"
if [[ ! -d "$project_path" ]]; then
log_error "Projet non trouvé: $project_path"
return 1
fi
cd "$project_path"
# Vérifier .gitignore
if [[ ! -f ".gitignore" ]]; then
log_warning ".gitignore manquant pour $project"
else
log_success ".gitignore présent"
fi
# Vérifier .dockerignore (pour les projets avec Docker)
if [[ " ${DOCKER_PROJECTS[@]} " =~ " ${project} " ]]; then
if [[ ! -f ".dockerignore" ]]; then
log_warning ".dockerignore manquant pour $project"
else
log_success ".dockerignore présent"
fi
fi
# Vérifier .cursorignore
if [[ ! -f ".cursorignore" ]]; then
log_warning ".cursorignore manquant pour $project"
else
log_success ".cursorignore présent"
fi
}
# Fonction pour nettoyer les fichiers non suivis d'un projet
clean_project_untracked() {
local project="$1"
local project_path="/home/debian/$project"
log "Nettoyage des fichiers non suivis pour $project"
if [[ ! -d "$project_path" ]]; then
log_error "Projet non trouvé: $project_path"
return 1
fi
cd "$project_path"
# Lister les fichiers non suivis
local untracked_files
untracked_files=$(git ls-files --others --exclude-standard 2>/dev/null || true)
if [[ -n "$untracked_files" ]]; then
log_info "Fichiers non suivis détectés:"
echo "$untracked_files" | while read -r file; do
echo " - $file"
done
# Supprimer les fichiers non suivis
if git clean -fd; then
log_success "Fichiers non suivis supprimés"
else
log_warning "Échec du nettoyage des fichiers non suivis"
fi
else
log_success "Aucun fichier non suivi"
fi
}
# Fonction pour compiler un projet
compile_project() {
local project="$1"
local project_path="/home/debian/$project"
log "Compilation de $project"
if [[ ! -d "$project_path" ]]; then
log_error "Projet non trouvé: $project_path"
return 1
fi
cd "$project_path"
# Rust projects
if [[ -f "Cargo.toml" ]]; then
log "Compilation Rust..."
if cargo build --release; then
log_success "Compilation Rust réussie"
else
log_error "Échec de la compilation Rust"
return 1
fi
# WebAssembly pour sdk_client
if [[ "$project" == "sdk_client" ]]; then
log "Build WebAssembly..."
if wasm-pack build --target bundler --release; then
log_success "Build WebAssembly réussi"
else
log_error "Échec du build WebAssembly"
return 1
fi
fi
fi
# Node.js projects
if [[ -f "package.json" ]]; then
if grep -q '"build"' package.json; then
log "Build Node.js..."
if npm run build; then
log_success "Build Node.js réussi"
else
log_error "Échec du build Node.js"
return 1
fi
fi
fi
# TypeScript projects
if [[ -f "tsconfig.json" ]]; then
log "Vérification TypeScript..."
if npx tsc --noEmit; then
log_success "Vérification TypeScript réussie"
else
log_warning "Erreurs TypeScript détectées"
fi
fi
}
# Fonction pour exécuter les tests d'un projet
test_project() {
local project="$1"
local project_path="/home/debian/$project"
log "Exécution des tests pour $project"
if [[ ! -d "$project_path" ]]; then
log_error "Projet non trouvé: $project_path"
return 1
fi
cd "$project_path"
# Rust projects
if [[ -f "Cargo.toml" ]]; then
log "Tests Rust..."
if cargo test; then
log_success "Tests Rust réussis"
else
log_warning "Certains tests Rust ont échoué"
fi
fi
# Node.js projects
if [[ -f "package.json" ]]; then
if grep -q '"test"' package.json; then
log "Tests Node.js..."
if npm test; then
log_success "Tests Node.js réussis"
else
log_warning "Certains tests Node.js ont échoué"
fi
fi
fi
}
# Fonction pour déployer un projet
deploy_project() {
local project="$1"
local project_path="/home/debian/$project"
log "Déploiement de $project"
if [[ ! -d "$project_path" ]]; then
log_error "Projet non trouvé: $project_path"
return 1
fi
cd "$project_path"
# Synchroniser les configurations si c'est un projet Docker
if [[ " ${DOCKER_PROJECTS[@]} " =~ " ${project} " ]]; then
if [[ -f "/home/debian/lecoffre_node/scripts/sync-configs.sh" ]]; then
log "Synchronisation des configurations..."
if /home/debian/lecoffre_node/scripts/sync-configs.sh "$project"; then
log_success "Configurations synchronisées"
else
log_warning "Échec de la synchronisation des configurations"
fi
fi
fi
# Mettre à jour les dépendances
update_project_dependencies "$project"
# Vérifier les fichiers ignore
check_project_ignore_files "$project"
# Nettoyer les fichiers non suivis
clean_project_untracked "$project"
# Compiler le projet
if ! compile_project "$project"; then
log_error "Échec de la compilation de $project"
return 1
fi
# Exécuter les tests
test_project "$project"
# Push vers la branche ext
log "Push vers la branche ext..."
if git checkout ext; then
log_success "Basculement vers la branche ext"
else
log_error "Échec du basculement vers la branche ext"
return 1
fi
if git add .; then
log_success "Ajout des modifications"
else
log_error "Échec de l'ajout des modifications"
return 1
fi
if git commit -m "ci: docker_tag=ext - Mise à jour automatique des dépendances et compilation"; then
log_success "Commit des modifications"
else
log_warning "Aucune modification à committer"
fi
if git push origin ext; then
log_success "Push vers la branche ext réussi"
else
log_error "Échec du push vers la branche ext"
return 1
fi
# Construire et pousser l'image Docker si c'est un projet Docker
if [[ " ${DOCKER_PROJECTS[@]} " =~ " ${project} " ]]; then
log "Construction de l'image Docker..."
if docker build -t "git.4nkweb.com/4nk/$project:ext" .; then
log_success "Image Docker construite"
# Pousser l'image si demandé
if [[ "${PUSH_DOCKER_IMAGES:-false}" == "true" ]]; then
log "Push de l'image Docker..."
if docker push "git.4nkweb.com/4nk/$project:ext"; then
log_success "Image Docker poussée"
else
log_error "Échec du push de l'image Docker"
return 1
fi
fi
else
log_error "Échec de la construction de l'image Docker"
return 1
fi
fi
log_success "Déploiement de $project terminé"
}
# Fonction pour vérifier l'état du scan
check_scan_status() {
local sdk_relay_url="http://127.0.0.1:8091"
echo "🔍 Vérification de l'état du scan..."
local response=$(curl -s "$sdk_relay_url" 2>/dev/null || echo "{}")
local scan_complete=$(echo "$response" | grep -o '"scan_complete":[^,]*' | cut -d: -f2 | tr -d ' "')
if [ "$scan_complete" = "true" ]; then
echo "✅ Scan terminé avec succès"
return 0
elif [ "$scan_complete" = "false" ]; then
echo "⚠️ Scan en cours, mais service disponible"
return 0
else
echo "❓ État du scan inconnu"
return 1
fi
}
# Fonction principale de démarrage
start_services() {
log "🚀 Démarrage de lecoffre_node avec séquence optimisée"
# Validation des dépendances externes avant démarrage
if ! validate_external_dependencies; then
log_error "Dépendances externes non disponibles. Arrêt du démarrage."
log "Utilisez './scripts/startup-sequence.sh restart' pour redémarrer après réparation"
exit 1
fi
# Préparation de l'environnement avant démarrage
log "🔧 Préparation de l'environnement..."
# Synchroniser les configurations centralisées
if [ -f "./scripts/sync-configs.sh" ]; then
log "📋 Synchronisation des configurations..."
./scripts/sync-configs.sh
fi
# Préparation du build si nécessaire
if [ -f "./scripts/pre-build.sh" ]; then
log "🏗️ Préparation du build..."
./scripts/pre-build.sh
fi
# Démarrage simplifié utilisant les healthchecks du docker-compose.yml
log "📦 Démarrage de tous les services avec healthchecks..."
docker compose up -d
log "⏳ Attente que tous les services soient prêts (utilise les healthchecks)..."
log " - sdk_relay: 60s start_period + healthcheck"
log " - ihm_client: 30s start_period + healthcheck"
log " - lecoffre-back: 30s start_period + healthcheck"
log " - lecoffre-front: 30s start_period + healthcheck"
# Attendre que tous les services soient healthy
log "🔍 Vérification de l'état des services..."
sleep 10
# Vérifier l'état du scan de sdk_relay
check_scan_status
# Étape 5: Vérification finale
log "🔍 Vérification finale de tous les services..."
services=(
"tor:9050"
"bitcoin:8332"
"blindbit:8000"
"sdk_storage:8081"
"sdk_relay:8091"
"sdk_signer:8092"
"ihm_client:3003"
"lecoffre-back:8080"
"lecoffre-front:3004"
)
all_ready=true
for service in "${services[@]}"; do
name=$(echo $service | cut -d: -f1)
port=$(echo $service | cut -d: -f2)
if curl -f -s "http://127.0.0.1:$port" > /dev/null 2>&1; then
log_success "$name est accessible"
else
log_warning "$name n'est pas accessible"
all_ready=false
fi
done
if [ "$all_ready" = true ]; then
log_success "Tous les services sont prêts !"
log "📊 État des services:"
docker compose ps
else
log_warning "Certains services ne sont pas prêts"
log "📋 Logs des services problématiques:"
docker compose logs --tail=20
exit 1
fi
}
# Fonction de redémarrage intelligent
restart_services() {
log "Redémarrage intelligent des services..."
# Arrêter les services qui dépendent d'externes
log "Arrêt des services dépendants..."
docker stop lecoffre-back lecoffre-front ihm_client 2>/dev/null || true
# Attendre que les dépendances externes soient disponibles
log "Attente de la disponibilité des dépendances externes..."
local max_attempts=30
local attempt=0
while [ $attempt -lt $max_attempts ]; do
if validate_external_dependencies; then
log_success "Dépendances externes disponibles"
break
fi
attempt=$((attempt + 1))
log "Tentative $attempt/$max_attempts - Attente 10s..."
sleep 10
done
if [ $attempt -eq $max_attempts ]; then
log_error "Dépendances externes non disponibles après $max_attempts tentatives"
return 1
fi
# Redémarrer les services
log "Redémarrage des services..."
docker start lecoffre-back lecoffre-front ihm_client
# Attendre que les services soient prêts
log "Attente de la disponibilité des services..."
sleep 15
log_success "Redémarrage terminé !"
}
# Gestion des arguments
case "${1:-start}" in
"start")
start_services
;;
"restart")
restart_services
;;
"validate")
validate_external_dependencies
;;
"monitor")
log "📊 Démarrage du monitoring continu..."
while true; do
sleep 60
log "🔄 Vérification périodique..."
check_scan_status
done
;;
"deploy")
log "🚀 Déploiement de tous les projets..."
# Synchroniser les configurations centralisées
sync_configurations
success_count=0
total_count=0
# Déployer les projets sans Docker
log "📚 Déploiement des projets library..."
for project in "${LIBRARY_PROJECTS[@]}"; do
total_count=$((total_count + 1))
if deploy_project "$project"; then
success_count=$((success_count + 1))
fi
done
# Déployer les projets avec Docker
log "🐳 Déploiement des projets Docker..."
for project in "${DOCKER_PROJECTS[@]}"; do
total_count=$((total_count + 1))
if deploy_project "$project"; then
success_count=$((success_count + 1))
fi
done
# Déployer lecoffre_node
log "🏗️ Déploiement du projet principal..."
total_count=$((total_count + 1))
cd "/home/debian/lecoffre_node"
if git checkout ext && git add . && git commit -m "ci: docker_tag=ext - Mise à jour des configurations centralisées" && git push origin ext; then
success_count=$((success_count + 1))
log_success "Déploiement de lecoffre_node terminé"
else
log_error "Échec du déploiement de lecoffre_node"
fi
# Résumé
log "📊 Résumé du déploiement:"
log " Projets déployés avec succès: $success_count/$total_count"
if [[ $success_count -eq $total_count ]]; then
log_success "🎉 Tous les projets ont été déployés avec succès!"
else
log_error "❌ Certains projets ont échoué"
exit 1
fi
;;
"deploy-project")
if [[ -z "${2:-}" ]]; then
log_error "Usage: $0 deploy-project <project_name>"
echo "Projets disponibles:"
echo " Docker: ${DOCKER_PROJECTS[*]}"
echo " Library: ${LIBRARY_PROJECTS[*]}"
exit 1
fi
local project="$2"
log "🚀 Déploiement du projet: $project"
if deploy_project "$project"; then
log_success "Déploiement de $project terminé avec succès!"
else
log_error "Échec du déploiement de $project"
exit 1
fi
;;
"update-deps")
log "📦 Mise à jour des dépendances de tous les projets..."
for project in "${DOCKER_PROJECTS[@]}" "${LIBRARY_PROJECTS[@]}"; do
update_project_dependencies "$project"
done
log_success "Mise à jour des dépendances terminée"
;;
"check-ignore")
log "🔍 Vérification des fichiers ignore de tous les projets..."
for project in "${DOCKER_PROJECTS[@]}" "${LIBRARY_PROJECTS[@]}"; do
check_project_ignore_files "$project"
done
log_success "Vérification des fichiers ignore terminée"
;;
"clean-untracked")
log "🧹 Nettoyage des fichiers non suivis de tous les projets..."
for project in "${DOCKER_PROJECTS[@]}" "${LIBRARY_PROJECTS[@]}"; do
clean_project_untracked "$project"
done
log_success "Nettoyage des fichiers non suivis terminé"
;;
"compile-all")
log "🔨 Compilation de tous les projets..."
for project in "${DOCKER_PROJECTS[@]}" "${LIBRARY_PROJECTS[@]}"; do
compile_project "$project"
done
log_success "Compilation de tous les projets terminée"
;;
"test-all")
log "🧪 Exécution des tests de tous les projets..."
for project in "${DOCKER_PROJECTS[@]}" "${LIBRARY_PROJECTS[@]}"; do
test_project "$project"
done
log_success "Tests de tous les projets terminés"
;;
*)
echo "Usage: $0 [COMMAND]"
echo ""
echo "COMMANDS:"
echo " start - Démarrage complet avec validation (défaut)"
echo " restart - Redémarrage intelligent après réparation"
echo " validate - Validation des dépendances externes uniquement"
echo " monitor - Monitoring continu"
echo ""
echo " deploy - Déploiement complet de tous les projets"
echo " deploy-project - Déploiement d'un projet spécifique"
echo " update-deps - Mise à jour des dépendances de tous les projets"
echo " check-ignore - Vérification des fichiers ignore"
echo " clean-untracked - Nettoyage des fichiers non suivis"
echo " compile-all - Compilation de tous les projets"
echo " test-all - Exécution des tests de tous les projets"
echo ""
echo "EXAMPLES:"
echo " $0 deploy # Déploie tous les projets"
echo " $0 deploy-project ihm_client # Déploie seulement ihm_client"
echo " $0 update-deps # Met à jour toutes les dépendances"
echo " PUSH_DOCKER_IMAGES=true $0 deploy # Déploie avec push des images Docker"
exit 1
;;
esac