Files
geo/app/fastlane/Fastfile
pierre 2f5946a184 feat: Version 3.5.2 - Configuration Stripe et gestion des immeubles
- Configuration complète Stripe pour les 3 environnements (DEV/REC/PROD)
  * DEV: Clés TEST Pierre (mode test)
  * REC: Clés TEST Client (mode test)
  * PROD: Clés LIVE Client (mode live)
- Ajout de la gestion des bases de données immeubles/bâtiments
  * Configuration buildings_database pour DEV/REC/PROD
  * Service BuildingService pour enrichissement des adresses
- Optimisations pages et améliorations ergonomie
- Mises à jour des dépendances Composer
- Nettoyage des fichiers obsolètes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 18:26:27 +01:00

382 lines
13 KiB
Ruby

# Fastfile pour GEOSECTOR Flutter App
# Version: 2.0
# Date: 2025-10-26
# Auteur: Pierre (avec l'aide de Claude)
#
# Usage depuis le Mac mini (après transfert depuis Debian):
# cd /Users/pierre/dev/geosector/app_346
# fastlane android build # Build seulement (test local)
# fastlane android release # Build + Upload vers Play Store
# fastlane ios build # Build iOS seulement (test local)
# fastlane ios release # Build + Upload vers TestFlight
default_platform(:android)
# =============================================================================
# ANDROID
# =============================================================================
platform :android do
desc "Build Android AAB (bundle) en mode release - sans upload"
lane :build do
UI.header("🤖 Build Android Bundle")
# Étape 1 : Nettoyer le projet
UI.message("🧹 [1/6] Nettoyage du projet...")
sh("cd .. && flutter clean")
UI.success("Projet nettoyé")
# Étape 2 : Récupérer les dépendances
UI.message("📦 [2/6] Récupération des dépendances...")
sh("cd .. && flutter pub get")
UI.success("Dépendances récupérées")
# Étape 3 : Patch nfc_manager
UI.message("🔧 [3/6] Application du patch nfc_manager...")
sh("cd .. && ./fastlane/scripts/commun/fix-nfc-manager.sh")
UI.success("Patch nfc_manager appliqué")
# Étape 4 : Analyser le code (non bloquant)
UI.message("🔍 [4/6] Analyse du code...")
begin
sh("cd .. && flutter analyze --no-fatal-infos --no-fatal-warnings")
UI.success("Analyse du code terminée")
rescue => ex
UI.important("⚠️ Des warnings détectés, mais on continue...")
end
# Étape 5 : Build du bundle AAB
UI.message("🏗️ [5/6] Build du bundle Android (RELEASE)...")
sh("cd .. && flutter build appbundle --release")
UI.success("Bundle AAB généré")
# Étape 6 : Copier le bundle avec version
UI.message("📋 [6/6] Copie du bundle avec version...")
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_code = version_info.split('+').last
final_name = "geosector-#{version_code}.aab"
sh("cd .. && cp build/app/outputs/bundle/release/app-release.aab #{final_name}")
bundle_size = sh("cd .. && du -h #{final_name} | cut -f1").strip
UI.success("✅ Build Android terminé avec succès!")
UI.success("📦 Bundle: #{final_name}")
UI.success("📊 Taille: #{bundle_size}")
end
desc "Build Android AAB + Upload vers Google Play Console (Internal Testing)"
lane :release do
UI.header("🚀 Build & Deploy Android vers Play Store")
# Étape 1 : Nettoyer le projet
UI.message("🧹 [1/7] Nettoyage du projet...")
sh("cd .. && flutter clean")
UI.success("Projet nettoyé")
# Étape 2 : Récupérer les dépendances
UI.message("📦 [2/7] Récupération des dépendances...")
sh("cd .. && flutter pub get")
UI.success("Dépendances récupérées")
# Étape 3 : Patch nfc_manager
UI.message("🔧 [3/7] Application du patch nfc_manager...")
sh("cd .. && ./fastlane/scripts/commun/fix-nfc-manager.sh")
UI.success("Patch nfc_manager appliqué")
# Étape 4 : Analyser le code (non bloquant)
UI.message("🔍 [4/7] Analyse du code...")
begin
sh("cd .. && flutter analyze --no-fatal-infos --no-fatal-warnings")
UI.success("Analyse du code terminée")
rescue => ex
UI.important("⚠️ Des warnings détectés, mais on continue...")
end
# Étape 5 : Build du bundle AAB
UI.message("🏗️ [5/7] Build du bundle Android (RELEASE)...")
sh("cd .. && flutter build appbundle --release")
UI.success("Bundle AAB généré")
# Étape 6 : Récupérer les informations de version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_name = version_info.split('+').first
version_code = version_info.split('+').last
UI.message("📋 Version: #{version_name} (#{version_code})")
# Étape 7 : Upload vers Google Play Console
UI.message("📤 [6/7] Upload vers Google Play Console...")
upload_to_play_store(
json_key: '../android/google-play-api-key.json', # Credentials Google Play API
track: 'internal', # Track: internal, alpha, beta, ou production
aab: '../build/app/outputs/bundle/release/app-release.aab',
skip_upload_apk: true, # On n'upload que l'AAB
skip_upload_metadata: true, # On ne met pas à jour les métadonnées
skip_upload_images: true, # On ne met pas à jour les images
skip_upload_screenshots: true, # On ne met pas à jour les screenshots
release_status: 'completed', # completed = publié immédiatement sur le track
version_code: version_code.to_i, # Version code explicite
package_name: 'fr.geosector.app3' # Package name explicite
)
UI.success("✅ Déploiement Android terminé avec succès!")
UI.success("📦 Version: #{version_name} (Build #{version_code})")
UI.success("🎯 Track: Internal Testing")
UI.success("🌐 URL: https://play.google.com/console")
end
desc "Upload un AAB existant vers Google Play Console"
lane :upload do
UI.header("📤 Upload AAB vers Play Store")
# Vérifier que le bundle existe
aab_path = '../build/app/outputs/bundle/release/app-release.aab'
if File.exist?(aab_path)
# Récupérer la version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_code = version_info.split('+').last
UI.message("📦 Upload du bundle existant...")
upload_to_play_store(
json_key: '../android/google-play-api-key.json',
track: 'internal',
aab: aab_path,
skip_upload_apk: true,
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true,
release_status: 'completed',
version_code: version_code.to_i,
package_name: 'fr.geosector.app3'
)
UI.success("✅ Upload terminé!")
else
UI.user_error!("❌ Bundle introuvable: #{aab_path}")
UI.message("💡 Lancez d'abord: fastlane android build")
end
end
end
# =============================================================================
# iOS
# =============================================================================
platform :ios do
desc "Build iOS IPA en mode release - sans upload"
lane :build do
UI.header("🍎 Build iOS IPA")
# Étape 1 : Vérifier le cache local (préparé sur Debian)
UI.message("📦 [1/6] Vérification du cache local...")
cache_path = File.expand_path("../.pub-cache-local")
if !Dir.exist?(cache_path)
UI.user_error!("❌ Cache local introuvable: #{cache_path}")
UI.message("💡 Exécutez './deploy-app.sh' sur Debian pour préparer le projet")
end
ENV['PUB_CACHE'] = cache_path
ENV['GRADLE_USER_HOME'] = File.expand_path("../.gradle-local")
UI.success("Cache local configuré: #{cache_path}")
UI.important("⚠️ flutter pub get et patchs déjà appliqués sur Debian")
# Étape 2 : Nettoyer les artefacts de build
UI.message("🧹 [2/6] Nettoyage des artefacts...")
sh("cd .. && rm -rf build .dart_tool ios/Pods ios/.symlinks")
UI.success("Artefacts nettoyés")
# Étape 3 : Installation des pods
UI.message("📦 [3/6] Installation des CocoaPods...")
sh("cd ../ios && pod install")
UI.success("CocoaPods installés")
# Étape 4 : Analyser le code (non bloquant)
UI.message("🔍 [4/6] Analyse du code...")
begin
sh("cd .. && flutter analyze --no-fatal-infos --no-fatal-warnings")
UI.success("Analyse du code terminée")
rescue => ex
UI.important("⚠️ Des warnings détectés, mais on continue...")
end
# Étape 5 : Build Flutter iOS
UI.message("🏗️ [5/6] Build Flutter iOS (RELEASE)...")
sh("cd .. && flutter build ios --release --no-codesign")
UI.success("Build Flutter iOS généré")
# Étape 6 : Archive Xcode (gym)
UI.message("📦 [6/6] Archive Xcode et export IPA...")
build_ios_app(
workspace: "./Runner.xcworkspace",
scheme: "Runner",
export_method: "app-store",
export_options: {
method: "app-store",
teamID: "6WT84NWCTC",
uploadBitcode: false,
uploadSymbols: true,
compileBitcode: false,
signingStyle: "automatic",
destination: "export",
provisioningProfiles: {
"fr.geosector.app3" => "match AppStore fr.geosector.app3"
}
},
output_directory: "../build/ios/ipa",
output_name: "Runner.ipa",
clean: false,
skip_profile_detection: true
)
UI.success("IPA généré")
# Afficher les informations de version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
ipa_size = sh("cd .. && du -h build/ios/ipa/Runner.ipa | cut -f1").strip
UI.success("✅ Build iOS terminé avec succès!")
UI.success("📦 IPA: build/ios/ipa/Runner.ipa")
UI.success("📊 Version: #{version_info}")
UI.success("📊 Taille: #{ipa_size}")
end
desc "Build iOS IPA + Upload vers TestFlight"
lane :release do
UI.header("🚀 Build & Deploy iOS vers TestFlight")
# Étape 1 : Vérifier le cache local (préparé sur Debian)
UI.message("📦 [1/7] Vérification du cache local...")
cache_path = File.expand_path("../.pub-cache-local")
if !Dir.exist?(cache_path)
UI.user_error!("❌ Cache local introuvable: #{cache_path}")
UI.message("💡 Exécutez './deploy-app.sh' sur Debian pour préparer le projet")
end
ENV['PUB_CACHE'] = cache_path
ENV['GRADLE_USER_HOME'] = File.expand_path("../.gradle-local")
UI.success("Cache local configuré: #{cache_path}")
UI.important("⚠️ flutter pub get et patchs déjà appliqués sur Debian")
# Étape 2 : Nettoyer les artefacts de build
UI.message("🧹 [2/7] Nettoyage des artefacts...")
sh("cd .. && rm -rf build .dart_tool ios/Pods ios/.symlinks")
UI.success("Artefacts nettoyés")
# Étape 3 : Installation des pods
UI.message("📦 [3/7] Installation des CocoaPods...")
sh("cd ../ios && pod install")
UI.success("CocoaPods installés")
# Étape 4 : Récupérer les informations de version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_name = version_info.split('+').first
version_code = version_info.split('+').last
UI.message("📋 Version: #{version_name} (#{version_code})")
# Étape 5 : Analyser le code (non bloquant)
UI.message("🔍 [4/7] Analyse du code...")
begin
sh("cd .. && flutter analyze --no-fatal-infos --no-fatal-warnings")
UI.success("Analyse du code terminée")
rescue => ex
UI.important("⚠️ Des warnings détectés, mais on continue...")
end
# Étape 6 : Build Flutter iOS
UI.message("🏗️ [5/7] Build Flutter iOS (RELEASE)...")
sh("cd .. && flutter build ios --release --no-codesign")
UI.success("Build Flutter iOS généré")
# Étape 7 : Archive Xcode
UI.message("📦 [6/7] Archive Xcode...")
build_ios_app(
workspace: "./Runner.xcworkspace",
scheme: "Runner",
export_method: "app-store",
export_options: {
method: "app-store",
teamID: "6WT84NWCTC",
uploadBitcode: false,
uploadSymbols: true,
compileBitcode: false,
signingStyle: "automatic",
provisioningProfiles: {
"fr.geosector.app3" => "match AppStore fr.geosector.app3"
}
},
output_directory: "../build/ios/ipa",
output_name: "Runner.ipa",
clean: false,
skip_profile_detection: true
)
UI.success("IPA généré")
# Étape 7 : Upload vers TestFlight
UI.message("📤 [7/7] Upload vers TestFlight...")
upload_to_testflight(
apple_id: "contact@d6soft.com",
app_identifier: "fr.geosector.app3",
team_id: "6WT84NWCTC",
ipa: "../build/ios/ipa/Runner.ipa",
skip_waiting_for_build_processing: true,
skip_submission: true,
distribute_external: false
)
UI.success("✅ Déploiement iOS terminé avec succès!")
UI.success("📦 Version: #{version_name} (Build #{version_code})")
UI.success("🎯 Track: TestFlight (Internal)")
UI.success("🌐 URL: https://appstoreconnect.apple.com")
end
desc "Upload un IPA existant vers TestFlight"
lane :upload do
UI.header("📤 Upload IPA vers TestFlight")
# Vérifier que l'IPA existe
ipa_path = '../build/ios/ipa/Runner.ipa'
if File.exist?(ipa_path)
# Récupérer la version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_name = version_info.split('+').first
version_code = version_info.split('+').last
UI.message("📦 Upload de l'IPA existant...")
upload_to_testflight(
apple_id: "contact@d6soft.com",
app_identifier: "fr.geosector.app3",
team_id: "6WT84NWCTC",
ipa: ipa_path,
skip_waiting_for_build_processing: true,
skip_submission: true,
distribute_external: false
)
UI.success("✅ Upload terminé!")
UI.success("📦 Version: #{version_name} (Build #{version_code})")
else
UI.user_error!("❌ IPA introuvable: #{ipa_path}")
UI.message("💡 Lancez d'abord: fastlane ios build")
end
end
end