#!/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/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 " 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