DevOps & iOS Environments

Gestione Multi-Ambiente (Dev, Staging, Prod) in Firebase per Progetti iOS SwiftUI

Eseguire test di sviluppo ed inviare notifiche push di prova sullo stesso progetto Firebase utilizzato dagli utenti reali in produzione è una ricetta per il disastro. La soluzione corretta consiste nel creare progetti Firebase separati (es. MyApp-Dev e MyApp-Prod) e selezionare dinamicamente il file GoogleService-Info.plist appropriato durante la compilazione in Xcode.

1. Organizzazione delle Cartelle in Xcode

Nel tuo progetto Xcode crea una cartella denominata Firebase contenente le sotto-cartelle per ciascun ambiente di destinazione:

MyProject/
├── Firebase/
│   ├── Development/
│   │   └── GoogleService-Info.plist
│   └── Production/
│       └── GoogleService-Info.plist

2. Build Phase Script per lo Switch Automatico

In Xcode seleziona il Target dell'app -> Build Phases -> aggiungi una nuova Run Script Phase posizionata PRIMA della fase Compile Sources:

# Script di selezione GoogleService-Info.plist in base alla Build Configuration
if [ "${CONFIGURATION}" == "Debug" ]; then
    echo "Configurazione Debug: utilizzo GoogleService-Info.plist (Development)"
    cp "${PROJECT_DIR}/MyProject/Firebase/Development/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
else
    echo "Configurazione Release: utilizzo GoogleService-Info.plist (Production)"
    cp "${PROJECT_DIR}/MyProject/Firebase/Production/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
fi

3. Inizializzazione Dinamica in Swift (Metodo Programmatico)

In alternativa allo script Xcode, è possibile caricare programmaticamente le opzioni di configurazione specificando il percorso del file plist desiderato:

import SwiftUI
import FirebaseCore

@main
struct MultiEnvApp: App {
    init() {
        #if DEBUG
        let fileName = "GoogleService-Info-Dev"
        #else
        let fileName = "GoogleService-Info-Prod"
        #endif
        
        if let filePath = Bundle.main.path(forResource: fileName, ofType: "plist"),
           let options = FirebaseOptions(contentsOfFile: filePath) {
            FirebaseApp.configure(options: options)
            print("Firebase inizializzato correttamente con l'ambiente: \(fileName)")
        } else {
            FirebaseApp.configure()
        }
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Conclusione

La separazione rigorosa degli ambienti garantisce che i test di sviluppo non impattino mai i dati analitici né l'integrità del database di produzione. Per configurare pipeline CI/CD e multi-ambiente per le tue app iOS, scrivi a diallooyunus@gmail.com.

Yunus Diallo (DialloDev)

Fondatore di Dywtal Digital a Parma (Italia), sviluppatore iOS ed esperto in pratiche DevOps & CI/CD per il mondo mobile.