Files
geo/app/deploy-ios-full-auto.sh
Pierre 232940b1eb feat: Version 3.6.2 - Correctifs tâches #17-20
- #17: Amélioration gestion des secteurs et statistiques
- #18: Optimisation services API et logs
- #19: Corrections Flutter widgets et repositories
- #20: Fix création passage - détection automatique ope_users.id vs users.id

Suppression dossier web/ (migration vers app Flutter)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 14:11:15 +01:00

499 lines
18 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Script de déploiement iOS automatisé pour GEOSECTOR
# Version: 1.0
# Date: 2025-12-05
# Auteur: Pierre (avec l'aide de Claude)
#
# Usage:
# ./deploy-ios-full-auto.sh # Utilise ../VERSION
# ./deploy-ios-full-auto.sh 3.6.0 # Version spécifique
# ./deploy-ios-full-auto.sh 3.6.0 --skip-build # Skip Flutter build si déjà fait
set -euo pipefail
# =====================================
# Configuration
# =====================================
# Couleurs pour les messages
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Configuration Mac mini
MAC_MINI_HOST="minipi4" # Nom défini dans ~/.ssh/config
MAC_BASE_DIR="/Users/pierre/dev/geosector"
# Timestamp pour logs et archives
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="./logs/deploy-ios-${TIMESTAMP}.log"
mkdir -p ./logs
# Variables globales pour le rapport
STEP_START_TIME=0
TOTAL_START_TIME=$(date +%s)
ERRORS_COUNT=0
WARNINGS_COUNT=0
# =====================================
# Fonctions utilitaires
# =====================================
log() {
echo -e "$1" | tee -a "${LOG_FILE}"
}
log_step() {
STEP_START_TIME=$(date +%s)
log "\n${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
log "${CYAN}$1${NC}"
log "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}
log_substep() {
log "${MAGENTA}$1${NC}"
}
log_info() {
log "${BLUE} ${NC}$1"
}
log_success() {
local elapsed=$(($(date +%s) - STEP_START_TIME))
log "${GREEN}${NC} $1 ${CYAN}(${elapsed}s)${NC}"
}
log_warning() {
((WARNINGS_COUNT++))
log "${YELLOW}${NC}$1"
}
log_error() {
((ERRORS_COUNT++))
log "${RED}${NC} $1"
}
log_fatal() {
log_error "$1"
log "\n${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
log "${RED}DÉPLOIEMENT ÉCHOUÉ${NC}"
log "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
log_error "Consultez le log: ${LOG_FILE}"
exit 1
}
# Fonction pour exécuter une commande et capturer les erreurs
safe_exec() {
local cmd="$1"
local error_msg="$2"
if ! eval "$cmd" >> "${LOG_FILE}" 2>&1; then
log_fatal "$error_msg"
fi
}
# Fonction pour exécuter une commande SSH avec gestion d'erreurs
ssh_exec() {
local cmd="$1"
local error_msg="$2"
if ! ssh "$MAC_MINI_HOST" "$cmd" >> "${LOG_FILE}" 2>&1; then
log_fatal "$error_msg"
fi
}
# =====================================
# En-tête
# =====================================
clear
log "${BLUE}╔════════════════════════════════════════════════════════╗${NC}"
log "${BLUE}║ ║${NC}"
log "${BLUE}${GREEN}🍎 DÉPLOIEMENT iOS AUTOMATISÉ${BLUE}${NC}"
log "${BLUE}${CYAN}GEOSECTOR - Full Automation${BLUE}${NC}"
log "${BLUE}║ ║${NC}"
log "${BLUE}╚════════════════════════════════════════════════════════╝${NC}"
log ""
log_info "Démarrage: $(date '+%Y-%m-%d %H:%M:%S')"
log_info "Log file: ${LOG_FILE}"
log ""
# =====================================
# Étape 1 : Gestion de la version
# =====================================
log_step "ÉTAPE 1/8 : Gestion de la version"
# Déterminer la version à utiliser
if [ "${1:-}" != "" ] && [[ ! "${1}" =~ ^-- ]]; then
VERSION="$1"
log_info "Version fournie en argument: ${VERSION}"
else
# Lire depuis ../VERSION
if [ ! -f ../VERSION ]; then
log_fatal "Fichier ../VERSION introuvable et aucune version fournie"
fi
VERSION=$(cat ../VERSION | tr -d '\n\r ' | tr -d '[:space:]')
log_info "Version lue depuis ../VERSION: ${VERSION}"
fi
# Vérifier le format de version
if ! [[ $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
log_fatal "Format de version invalide: ${VERSION} (attendu: x.x.x)"
fi
# Calculer le build number
BUILD_NUMBER=$(echo $VERSION | tr -d '.')
FULL_VERSION="${VERSION}+${BUILD_NUMBER}"
log_success "Version configurée"
log_info " Version name: ${GREEN}${VERSION}${NC}"
log_info " Build number: ${GREEN}${BUILD_NUMBER}${NC}"
log_info " Full version: ${GREEN}${FULL_VERSION}${NC}"
# =====================================
# Étape 2 : Mise à jour pubspec.yaml
# =====================================
log_step "ÉTAPE 2/8 : Mise à jour pubspec.yaml"
# Backup du pubspec.yaml
cp pubspec.yaml pubspec.yaml.backup
# Mise à jour de la version
sed -i "s/^version: .*/version: $FULL_VERSION/" pubspec.yaml
# Vérifier la mise à jour
UPDATED_VERSION=$(grep "^version:" pubspec.yaml | sed 's/version: //' | tr -d ' ')
if [ "$UPDATED_VERSION" != "$FULL_VERSION" ]; then
log_fatal "Échec de la mise à jour de pubspec.yaml (attendu: $FULL_VERSION, obtenu: $UPDATED_VERSION)"
fi
log_success "pubspec.yaml mis à jour"
# =====================================
# Étape 3 : Préparation du projet
# =====================================
SKIP_BUILD=false
if [[ "${2:-}" == "--skip-build" ]]; then
SKIP_BUILD=true
log_warning "Mode --skip-build activé, Flutter build sera ignoré"
fi
if [ "$SKIP_BUILD" = false ]; then
log_step "ÉTAPE 3/8 : Préparation du projet Flutter"
log_substep "Configuration du cache local"
export PUB_CACHE="$PWD/.pub-cache-local"
export GRADLE_USER_HOME="$PWD/.gradle-local"
mkdir -p "$PUB_CACHE" "$GRADLE_USER_HOME"
log_info " Cache Pub: $PUB_CACHE"
log_info " Cache Gradle: $GRADLE_USER_HOME"
log_substep "Nettoyage du projet"
safe_exec "flutter clean" "Échec du nettoyage Flutter"
log_substep "Récupération des dépendances"
safe_exec "flutter pub get" "Échec de flutter pub get"
log_substep "Application du patch nfc_manager"
safe_exec "./fastlane/scripts/commun/fix-nfc-manager.sh" "Échec du patch nfc_manager"
log_substep "Application du patch permission_handler (si nécessaire)"
if [ -f "./fastlane/scripts/commun/fix-permission-handler.sh" ]; then
safe_exec "./fastlane/scripts/commun/fix-permission-handler.sh" "Échec du patch permission_handler"
fi
log_substep "Génération des fichiers Hive"
safe_exec "dart run build_runner build --delete-conflicting-outputs" "Échec de la génération de code"
log_success "Projet préparé (dépendances + patchs + génération de code)"
log_info " ⚠️ Build iOS sera fait sur le Mac mini via Fastlane"
else
log_step "ÉTAPE 3/8 : Préparation du projet (BUILD SKIPPED)"
log_substep "Configuration du cache local uniquement"
export PUB_CACHE="$PWD/.pub-cache-local"
export GRADLE_USER_HOME="$PWD/.gradle-local"
if [ ! -d "$PUB_CACHE" ]; then
log_warning "Cache local introuvable, le build pourrait échouer sur le Mac mini"
fi
log_success "Cache configuré (build Flutter ignoré)"
fi
# =====================================
# Étape 4 : Vérification de la connexion Mac mini
# =====================================
log_step "ÉTAPE 4/8 : Connexion au Mac mini"
log_substep "Test de connexion SSH à ${MAC_MINI_HOST}"
if ! ssh "$MAC_MINI_HOST" "echo 'Connection OK'" >> "${LOG_FILE}" 2>&1; then
log_fatal "Impossible de se connecter au Mac mini (${MAC_MINI_HOST})"
fi
log_success "Connexion SSH établie"
# Vérifier l'environnement Mac
log_substep "Vérification de l'environnement Mac"
MAC_INFO=$(ssh "$MAC_MINI_HOST" "sw_vers -productVersion && xcodebuild -version | head -1 && flutter --version | head -1" 2>/dev/null || echo "N/A")
log_info "$(echo "$MAC_INFO" | head -1 | xargs -I {} echo " macOS: {}")"
log_info "$(echo "$MAC_INFO" | sed -n '2p' | xargs -I {} echo " Xcode: {}")"
log_info "$(echo "$MAC_INFO" | sed -n '3p' | xargs -I {} echo " Flutter: {}")"
# =====================================
# Étape 5 : Transfert vers Mac mini
# =====================================
log_step "ÉTAPE 5/8 : Transfert du projet vers Mac mini"
DEST_DIR="${MAC_BASE_DIR}/app_${BUILD_NUMBER}"
log_substep "Création du dossier de destination: ${DEST_DIR}"
ssh_exec "mkdir -p ${DEST_DIR}" "Impossible de créer le dossier ${DEST_DIR} sur le Mac mini"
log_substep "Transfert rsync (peut prendre 2-5 minutes)"
TRANSFER_START=$(date +%s)
rsync -avz --progress \
--exclude='build/' \
--exclude='.dart_tool/' \
--exclude='ios/Pods/' \
--exclude='ios/.symlinks/' \
--exclude='macos/Pods/' \
--exclude='linux/flutter/ephemeral/' \
--exclude='windows/flutter/ephemeral/' \
--exclude='android/build/' \
--exclude='*.aab' \
--exclude='*.apk' \
--exclude='logs/' \
--exclude='*.log' \
./ "${MAC_MINI_HOST}:${DEST_DIR}/" >> "${LOG_FILE}" 2>&1 || log_fatal "Échec du transfert rsync"
TRANSFER_TIME=$(($(date +%s) - TRANSFER_START))
log_success "Transfert terminé"
log_info " Destination: ${DEST_DIR}"
log_info " Durée: ${TRANSFER_TIME}s"
# =====================================
# Étape 6 : Build et Archive avec Fastlane
# =====================================
log_step "ÉTAPE 6/8 : Build et Archive iOS avec Fastlane"
log_info "Cette étape peut prendre 15-25 minutes"
log_info "Fastlane va :"
log_info " 1. Nettoyer les artefacts"
log_info " 2. Installer les CocoaPods"
log_info " 3. Analyser le code"
log_info " 4. Build Flutter iOS"
log_info " 5. Archive Xcode (gym)"
log_info " 6. Export IPA"
log_info ""
log_substep "Lancement de: cd ${DEST_DIR} && fastlane ios build"
FASTLANE_START=$(date +%s)
# Créer un fichier temporaire pour capturer la sortie Fastlane
FASTLANE_LOG="/tmp/fastlane-ios-${TIMESTAMP}.log"
# Exécuter Fastlane en temps réel avec affichage des étapes importantes
ssh -t "$MAC_MINI_HOST" "cd ${DEST_DIR} && /opt/homebrew/bin/fastlane ios build" 2>&1 | tee -a "${LOG_FILE}" | tee "${FASTLANE_LOG}" | while IFS= read -r line; do
# Afficher les lignes importantes
if echo "$line" | grep -qE "(🧹|📦|🔧|🔍|🏗️|✓|✗|Error|error:|ERROR|Build succeeded|Build failed)"; then
echo -e "${CYAN} ${line}${NC}"
fi
done
# Vérifier le code de retour de Fastlane
FASTLANE_EXIT_CODE=${PIPESTATUS[0]}
FASTLANE_TIME=$(($(date +%s) - FASTLANE_START))
if [ $FASTLANE_EXIT_CODE -ne 0 ]; then
log_error "Fastlane a échoué (code: ${FASTLANE_EXIT_CODE})"
log_error "Analyse des erreurs..."
# Extraire les erreurs du log Fastlane
if [ -f "${FASTLANE_LOG}" ]; then
log ""
log "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
log "${RED}ERREURS DÉTECTÉES :${NC}"
log "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
grep -i "error:\|Error:\|ERROR:\|❌\|✗" "${FASTLANE_LOG}" | head -20 | while IFS= read -r error_line; do
log "${RED} ${error_line}${NC}"
done
log "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
fi
log_fatal "Build iOS échoué via Fastlane. Consultez ${FASTLANE_LOG} pour plus de détails."
fi
log_success "Build et Archive iOS réussis"
log_info " Durée totale Fastlane: ${FASTLANE_TIME}s ($((FASTLANE_TIME/60))m $((FASTLANE_TIME%60))s)"
# Vérifier que l'IPA existe
log_substep "Vérification de l'IPA généré"
IPA_EXISTS=$(ssh "$MAC_MINI_HOST" "test -f ${DEST_DIR}/build/ios/ipa/Runner.ipa && echo 'YES' || echo 'NO'")
if [ "$IPA_EXISTS" != "YES" ]; then
log_fatal "IPA non trouvé dans ${DEST_DIR}/build/ios/ipa/Runner.ipa"
fi
IPA_SIZE=$(ssh "$MAC_MINI_HOST" "du -h ${DEST_DIR}/build/ios/ipa/Runner.ipa | cut -f1")
log_info " IPA trouvé: ${GREEN}${IPA_SIZE}${NC}"
# =====================================
# Étape 7 : Upload vers TestFlight (optionnel)
# =====================================
log_step "ÉTAPE 7/8 : Upload vers TestFlight"
log ""
log_info "${YELLOW}Voulez-vous uploader l'IPA vers TestFlight maintenant ?${NC}"
log_info " [Y] Oui - Upload automatique via fastlane ios upload"
log_info " [N] Non - Je ferai l'upload manuellement plus tard"
log ""
read -p "$(echo -e ${CYAN}Votre choix [Y/n]: ${NC})" -n 1 -r UPLOAD_CHOICE
echo
log ""
if [[ $UPLOAD_CHOICE =~ ^[Yy]$ ]] || [ -z "$UPLOAD_CHOICE" ]; then
log_substep "Lancement de: fastlane ios upload"
log_info "Upload vers TestFlight (peut prendre 5-10 minutes)"
UPLOAD_START=$(date +%s)
ssh -t "$MAC_MINI_HOST" "cd ${DEST_DIR} && /opt/homebrew/bin/fastlane ios upload" 2>&1 | tee -a "${LOG_FILE}"
UPLOAD_EXIT_CODE=${PIPESTATUS[0]}
UPLOAD_TIME=$(($(date +%s) - UPLOAD_START))
if [ $UPLOAD_EXIT_CODE -ne 0 ]; then
log_error "Upload TestFlight échoué (code: ${UPLOAD_EXIT_CODE})"
log_warning "L'IPA est disponible sur le Mac mini, vous pouvez réessayer manuellement"
log_info " Commande: ssh $MAC_USER@$MAC_MINI_IP \"cd ${DEST_DIR} && fastlane ios upload\""
else
log_success "Upload TestFlight réussi"
log_info " Durée: ${UPLOAD_TIME}s"
log_info " URL: ${CYAN}https://appstoreconnect.apple.com${NC}"
fi
else
log_info "Upload ignoré. Pour uploader manuellement plus tard :"
log_info " ${CYAN}ssh $MAC_MINI_HOST \"cd ${DEST_DIR} && /opt/homebrew/bin/fastlane ios upload\"${NC}"
fi
# =====================================
# Étape 8 : Nettoyage et archivage
# =====================================
log_step "ÉTAPE 8/8 : Nettoyage et archivage"
log_substep "Voulez-vous archiver le dossier de build ?"
log_info " [Y] Oui - Créer une archive ${DEST_DIR}.tar.gz"
log_info " [N] Non - Garder le dossier tel quel (défaut)"
log ""
read -p "$(echo -e ${CYAN}Votre choix [y/N]: ${NC})" -n 1 -r ARCHIVE_CHOICE
echo
log ""
if [[ $ARCHIVE_CHOICE =~ ^[Yy]$ ]]; then
log_substep "Création de l'archive..."
ssh_exec "cd ${MAC_BASE_DIR} && tar -czf app_${BUILD_NUMBER}.tar.gz app_${BUILD_NUMBER}" \
"Échec de la création de l'archive"
ARCHIVE_SIZE=$(ssh "$MAC_MINI_HOST" "du -h ${MAC_BASE_DIR}/app_${BUILD_NUMBER}.tar.gz | cut -f1")
log_success "Archive créée"
log_info " Archive: ${MAC_BASE_DIR}/app_${BUILD_NUMBER}.tar.gz (${ARCHIVE_SIZE})"
log_substep "Suppression du dossier de build"
ssh_exec "rm -rf ${DEST_DIR}" "Échec de la suppression du dossier"
log_success "Dossier de build supprimé"
else
log_info "Dossier conservé: ${DEST_DIR}"
fi
# Restaurer le pubspec.yaml original (optionnel)
log_substep "Restauration de pubspec.yaml local"
mv pubspec.yaml.backup pubspec.yaml
log_info " pubspec.yaml local restauré à son état initial"
# =====================================
# Rapport final
# =====================================
TOTAL_TIME=$(($(date +%s) - TOTAL_START_TIME))
TOTAL_MINUTES=$((TOTAL_TIME / 60))
TOTAL_SECONDS=$((TOTAL_TIME % 60))
log ""
log "${GREEN}╔════════════════════════════════════════════════════════╗${NC}"
log "${GREEN}║ ║${NC}"
log "${GREEN}║ ✓ DÉPLOIEMENT iOS TERMINÉ AVEC SUCCÈS ║${NC}"
log "${GREEN}║ ║${NC}"
log "${GREEN}╚════════════════════════════════════════════════════════╝${NC}"
log ""
log "${CYAN}📊 RAPPORT DE DÉPLOIEMENT${NC}"
log "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
log ""
log " ${BLUE}Version déployée:${NC} ${GREEN}${VERSION} (Build ${BUILD_NUMBER})${NC}"
log " ${BLUE}Destination:${NC} ${DEST_DIR}"
log " ${BLUE}IPA généré:${NC} ${GREEN}${IPA_SIZE}${NC}"
log " ${BLUE}Durée totale:${NC} ${GREEN}${TOTAL_MINUTES}m ${TOTAL_SECONDS}s${NC}"
log ""
if [ $WARNINGS_COUNT -gt 0 ]; then
log " ${YELLOW}⚠ Avertissements:${NC} ${WARNINGS_COUNT}"
fi
if [ $ERRORS_COUNT -gt 0 ]; then
log " ${RED}✗ Erreurs:${NC} ${ERRORS_COUNT}"
fi
log ""
log "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
log ""
log "${BLUE}📱 PROCHAINES ÉTAPES${NC}"
log "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
log ""
if [[ $UPLOAD_CHOICE =~ ^[Yy]$ ]] || [ -z "$UPLOAD_CHOICE" ]; then
if [ $UPLOAD_EXIT_CODE -eq 0 ]; then
log " 1. ${GREEN}${NC} IPA uploadé sur TestFlight"
log " 2. Accéder à App Store Connect:"
log " ${CYAN}https://appstoreconnect.apple.com${NC}"
log " 3. Attendre le traitement Apple (5-15 min)"
log " 4. Configurer la conformité export si demandée"
log " 5. Ajouter des testeurs internes"
log " 6. Installer via TestFlight sur iPhone"
else
log " 1. ${YELLOW}${NC} Upload TestFlight a échoué"
log " 2. Réessayer manuellement:"
log " ${CYAN}ssh $MAC_USER@$MAC_MINI_IP \"cd ${DEST_DIR} && fastlane ios upload\"${NC}"
fi
else
log " 1. L'IPA est prêt sur le Mac mini"
log " 2. Pour uploader vers TestFlight:"
log " ${CYAN}ssh $MAC_USER@$MAC_MINI_IP \"cd ${DEST_DIR} && fastlane ios upload\"${NC}"
log " 3. Ou distribuer l'IPA manuellement via Xcode"
fi
log ""
log "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
log ""
log " ${BLUE}Log complet:${NC} ${LOG_FILE}"
log " ${BLUE}Fin:${NC} $(date '+%Y-%m-%d %H:%M:%S')"
log ""
# Nettoyer le log Fastlane temporaire
rm -f "${FASTLANE_LOG}"
exit 0