Spiegazione dell'integrazione continua di iOS con Xcode Server

Pubblicato: 2022-03-11

introduzione

Prima di Xcode 9, l'utilizzo degli strumenti di integrazione continua di Apple era un processo noioso e complesso che richiedeva l'acquisto e l'installazione di un'app macOS Server aggiuntiva. Ciò ha portato molti sviluppatori ad abbandonare l'idea dell'integrazione continua per i loro progetti iOS o a ricorrere a soluzioni di terze parti, con livelli di successo molto diversi.

Tuttavia, dopo il rilascio di Xcode 9.0 a settembre 2017, il processo è stato notevolmente semplificato, inclusa l'opzione della firma automatica del codice, ed è ora completamente integrato in Xcode. Pertanto, non richiede app o strumenti aggiuntivi.

Mentre le soluzioni di terze parti come Fastlane, Bluepill, ecc. sono di grande aiuto e possono fare molto lavoro per te, questo articolo esplorerà le capacità dell'utilizzo degli strumenti Xcode e Apple da soli per le tue esigenze di integrazione continua. Utilizzeremo anche la firma manuale del codice poiché spesso sembra essere un problema per molte persone e anche la firma automatica tende a non essere la soluzione ottimale quando si tratta di più configurazioni di build.

Nota: questo articolo è basato su Xcode 9.4.1 e si concentra sullo sviluppo di app iOS, ma gran parte di esso è applicabile a Xcode 10 (attualmente disponibile come build beta 5) e allo sviluppo di app macOS.

Configurazione del server Xcode

Oltre a semplificare l'effettivo processo di integrazione, Xcode 9 ha anche semplificato il processo di configurazione di Xcode Server.

Avvia l'app Xcode sul tuo computer macOS che è stato designato come server CI e apri le Preferenze.

Passa all'ultima scheda, denominata Server e bot .

Strumenti di integrazione continua: screenshot della scheda Server e bot

Attiva le funzionalità di Xcode Server facendo clic sull'interruttore nell'angolo in alto a destra. Quindi, ti verrà chiesto di selezionare un utente per eseguire ed eseguire script di build su questa macchina. Probabilmente è una buona idea avere un utente dedicato proprio per questo scopo, invece di usarne uno preesistente.

Tieni presente che questo utente deve essere connesso al sistema affinché qualsiasi bot Xcode possa essere eseguito. Dopo aver effettuato l'accesso, dovresti vedere un cerchio verde accanto al nome utente.

Xcode Server e Bot dopo l'accesso riuscito

Questo è tutto! Diamo un'occhiata più da vicino ai robot Xcode.

Come configurare i bot Xcode

Ora sei pronto per iniziare a configurare i bot Xcode per l'esecuzione su questo server. Questo può essere fatto su qualsiasi macchina di sviluppo connessa alla stessa rete del server.

Apri Xcode sulla tua macchina di sviluppo e fai clic su Xcode > Preferenze dal menu in alto. Quindi, vai alla scheda Account e fai clic sull'icona + nell'angolo in basso a sinistra. Seleziona Xcode Server dalla finestra di dialogo che appare.

Screenshot della selezione del tipo di account

Per creare un bot, apri semplicemente il tuo progetto in Xcode e scegli l'opzione Prodotto > Crea Bot... dal menu in alto. La configurazione del bot prevede una serie di passaggi e li esploreremo nelle prossime sezioni.

Automazione della distribuzione delle app

Una delle applicazioni più frequenti dell'automazione della build di app iOS è la configurazione di un bot per caricare un'app su una piattaforma di distribuzione iOS come TestFlight, Fabric ecc.

Come ho spiegato in precedenza, questo articolo esplorerà solo il caricamento su App Store Connect e il download direttamente dal tuo server Xcode, poiché quelli sono gli strumenti nativi di Apple per la distribuzione di app iOS.

Distribuzione App Store Connect utilizzando Xcode

Prima di configurare un bot, assicurati di disporre di un record dell'app App Store Connect che corrisponda all'ID bundle del progetto di sviluppo dell'app. Vale anche la pena notare che ogni build deve avere un identificatore univoco costituito dalla versione e dal numero di build. Esploreremo come garantire che queste condizioni siano soddisfatte quando discuteremo delle impostazioni del bot Xcode in seguito.

Passaggio 1: l'impostazione della configurazione di build corretta è il passaggio cruciale per ottenere ciò che desideri. Assicurati di selezionare lo schema e la configurazione che producono l'app che desideri caricare su App Store Connect. Ciò include assicurarsi che la configurazione della build utilizzi l'ID bundle appropriato registrato nel portale per sviluppatori Apple del tuo team (utilizzato per la firma del codice) e nel portale App Store Connect (utilizzato per caricare automaticamente l'app) .

Passaggio 2: mentre siamo ancora nella scheda "Configurazione", dobbiamo specificare le opzioni di esportazione. Esploreremo l'elenco delle proprietà delle opzioni di esportazione, quindi assicurati che "Usa elenco opzioni di esportazione personalizzate" sia selezionato.

Passaggio 3: ora è il momento di creare l'elenco delle proprietà delle opzioni di esportazione. Un elenco completo delle chiavi da utilizzare in questo file è disponibile se si immette xcodebuild --help , ma esploreremo quelle utilizzate in questa configurazione del bot qui:

  • compileBitcode – Bitcode è il formato di output provvisorio di Apple per il codice sorgente dell'app. In altre parole, è il formato in cui il codice sorgente viene convertito prima di essere compilato in codice macchina per un'architettura specifica. Mira ad avere un unico contenitore di codice che può essere ulteriormente ottimizzato se viene effettuata un'ottimizzazione nel set di istruzioni e anche a poterlo compilare in future architetture da questo stesso formato. Tuttavia, ciò non ha alcun effetto sulla tua applicazione. Sta a te decidere se abilitarlo o meno.
  • method : questo argomento specifica il tipo di prodotto che stai esportando. Apple distingue i prodotti in base al pubblico designato: lo sviluppo consente di installarlo solo sui dispositivi specificati nel profilo di provisioning, l'azienda consente a tutti di installarlo, ma devono fidarsi esplicitamente di questo profilo di sviluppo prima di eseguire l'app e l' app store è per distribuendolo all'App Store o all'App Store Connect, quindi utilizzeremo questo valore.
  • provisioningProfiles – Questo è autoesplicativo. Ma ci sono un paio di cose da notare qui: I profili di provisioning nell'elenco delle proprietà delle opzioni di esportazione sono un dizionario in cui una chiave corrisponde all'ID bundle di un prodotto e il valore corrisponde al nome del profilo di provisioning utilizzato per la firma del codice.
  • signingCertificate – Un altro argomento autoesplicativo. Il valore di questo campo può essere un nome di certificato completo o un hash SHA-1.
  • teamID – Un altro argomento autoesplicativo. Questo è l'identificatore lungo 10 caratteri che Apple ha rilasciato alla tua organizzazione quando ti sei registrato al programma Apple Developer.
  • uploadBitcode – Se caricare o meno il bitcode (se hai scelto di compilarlo) in modo che possa essere utilizzato in AppStore Connect per generare nuove build ottimizzate o build per architetture future.
  • uploadSymbols : carica i simboli di debug in modo da poter ottenere un rapporto di arresto anomalo significativo anziché solo un dump della memoria e uno stack di assembly.

Quindi ora, l'elenco delle proprietà delle opzioni di esportazione potrebbe assomigliare a questo:

 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>compileBitcode</key> <false/> <key>method</key> <string>app-store</string> <key>provisioningProfiles</key> <dict> <key>com.bundle.id</key> <string>ProvisioningProfileName</string> </dict> <key>signingCertificate</key> <string>Signing Certificate Exact Name or SHA-1 hash value</string> <key>teamID</key> <string>??????????</string> <key>uploadBitcode</key> <false/> <key>uploadSymbols</key> <true/> </dict> </plist>

Passaggio 4: scegli il .plist che hai creato come elenco delle proprietà delle opzioni di esportazione.

Passaggio 5: la successiva è la scheda "Programma", configurala in base alle tue preferenze.

Passaggio 6: nella scheda Firma, assicurati di deselezionare l'opzione "Consenti a Xcode Server di gestire i miei certificati e profili" e di caricare un certificato di firma e un profilo di provisioning corrispondenti da solo, nella pagina Certificati e profili .

Passaggio 7: la scheda Dispositivi dovrebbe essere lasciata così com'è poiché stiamo caricando l'app anziché testarla.

Passaggio 8: la scheda Argomenti consente di impostare in modo esplicito argomenti xcodebuild o variabili di ambiente che possono essere utilizzate nella compilazione o negli script di pre-integrazione e post-integrazione.

Passaggio 9: infine, raggiungiamo la scheda Trigger , che è anche l'ultima scheda nella configurazione del bot di integrazione continua Xcode. Questo è lo strumento più potente nell'arsenale di Xcode Server. Per cominciare, mi piace aggiungere i seguenti due comandi come script di pre-integrazione:

 #!/bin/sh set printenv

Il primo stampa tutte le variabili utilizzate da Xcode Server e i relativi valori nell'esecuzione dell'integrazione corrente. Il secondo stampa tutte le variabili d'ambiente ei loro valori. Come previsto, questo può essere utile per il debug degli script, quindi lo chiamo giustamente "informazioni di debug".

Ricorda che abbiamo menzionato che dobbiamo assicurarci che ogni build caricata su App Store Connect debba avere una versione di build univoca e una coppia di numeri di build. Possiamo usare lo strumento integrato PlistBuddy, ma abbiamo anche bisogno di un modo per avere un numero di build univoco. Una cosa che è sempre presente durante l'integrazione di Xcode Server, ed è anche convenientemente univoca, è il numero di integrazione, poiché viene incrementato automaticamente. Creeremo un altro script di pre-integrazione, denominato "set build number" con i seguenti contenuti per assicurarci di avere ogni volta un numero di build univoco:

 #!/bin/sh buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}") buildNumber=$XCS_INTEGRATION_NUMBER /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"

Se stai utilizzando CocoaPods e hai scelto di non eseguire il commit della directory Pods nel tuo DVCS, dovresti anche includere uno script di pre-integrazione con i seguenti contenuti:

 #!/bin/sh cd $XCS_PRIMARY_REPO_DIR pod install

Passaggio 10: abbiamo quasi finito, ma non abbiamo specificato da nessuna parte che vogliamo caricare la build su AppStore Connect o su quale account. A tal fine, aggiungeremo uno script di post-integrazione e un altro strumento integrato, chiamato Application Loader. Inserisci quanto segue nello script:

 #!/bin/sh /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool --upload-app -f $XCS_PRODUCT -u $TESTFLIGHT_USERNAME -p $TESTFLIGHT_PASSWORD

$XCS_PRODUCT è una variabile del server Xcode e contiene il percorso dell'app che è stata creata nell'esecuzione dell'integrazione corrente. Tuttavia, $TESTFLIGHT_USERNAME e $TESTFLIGHT_PASSWORD non sono né variabili di sistema né Xcode Server. Questi devono essere impostati da te e avere il valore del tuo ID Apple e password. Sfortunatamente, Apple ha interrotto il supporto per la generazione di una chiave API per il caricamento di build di AppStore Connect. Poiché si tratta di informazioni riservate, è consigliabile configurarle direttamente sul server Mac (supponendo che sia il tuo) come variabile di ambiente anziché nella configurazione del bot di Xcode Server.

Distribuzione del server Xcode

Il bot di distribuzione di Xcode Server utilizza effettivamente la stessa configurazione di quella per la distribuzione di App Store Connect, ad eccezione degli script di post-integrazione. Tuttavia, scaricare l'applicazione e installarla può essere comunque complicato. Devi comunque assicurarti che il profilo di provisioning con cui hai firmato la tua app consenta l'installazione dell'app sul dispositivo che stai utilizzando.

Con quello in atto, dovrai aprire Safari sul tuo dispositivo iOS e accedere alla dashboard web di Xcode Server del tuo server. Ad esempio, se il nome del tuo server è "server Mac", puoi trovarlo in "nome-server-mac.local/xcode" se sei sulla stessa rete del server. Lì troverai un elenco di tutti i tuoi robot Xcode e le statistiche delle loro integrazioni più recenti.

Seleziona quello che ha creato l'app che desideri scaricare. Nella schermata seguente, avrai due pulsanti: Installa e Profilo . Se è la prima volta che scarichi da questo server, devi fare clic su Profilo per aggiungere il suo certificato all'elenco delle fonti attendibili. Successivamente, fai clic sul pulsante Installa nella stessa pagina e verrai accolto con la finestra di dialogo di conferma di iOS "Sei sicuro di voler installare * sul tuo dispositivo?" Confermalo facendo clic su e la tua app sarà installata ed eseguibile dalla schermata principale.

Screenshot delle opzioni di installazione dell'app

Per iOS 10.3 e versioni successive , un motivo per cui potrebbe non riuscire con "Impossibile connettersi a *.local" è che il certificato autofirmato deve essere considerato attendibile manualmente nelle Impostazioni del dispositivo di test.

Segui questi passi:

Passaggio 1: installa i certificati autofirmati dalla pagina dei robot del server Xcode sul tuo iPhone.

Passaggio 2: vai su Impostazioni dell'iPhone > Generali > Informazioni su > Impostazioni di attendibilità del certificato .

Passaggio 3: trova i certificati autofirmati del tuo server nella sezione ABILITA FULL TRUST FOR ROOT CERTIFICATES e attiva l'interruttore.

Passaggio 4: torna alla pagina di integrazione del bot su Xcode Server, fai clic su Installa .

Test automatico dell'app del server Xcode

Un altro ottimo utilizzo di Xcode Server è il test automatico delle app, che si tratti di test dell'unità o dell'interfaccia utente. Per fare ciò, devi avere l'obiettivo appropriato impostato per il tuo progetto. Ovvero, è necessario disporre di un target che esegua i test dell'unità o dell'interfaccia utente, a seconda dell'obiettivo.

Il processo di configurazione è lo stesso del precedente, ma selezioneremo diverse opzioni. La prima grande differenza è nella scheda Configurazione . Ovviamente, controlleremo le caselle "Analizza" e "Testing" poiché questo è il nostro obiettivo principale. Consiglierei inoltre di non archiviare né esportare il prodotto con questo bot. È possibile eseguire sia il test che la distribuzione con la stessa configurazione del bot. Tuttavia, questi due scenari differiscono nell'output e nella pianificazione. La distribuzione viene spesso eseguita alla fine del ciclo.

Che tu stia lavorando in Scrum o Kanban o in qualche altro framework, dovrebbe esserci un ciclo predefinito guidato dal tempo o guidato dagli eventi al termine del quale dovresti aver esportato e utilizzabile il prodotto. D'altra parte, dovresti eseguire il tuo bot di test su ogni commit, poiché è la tua prima linea di difesa contro le regressioni. Poiché il bot di test viene ovviamente eseguito più spesso, l'unione di questi due bot in uno solo potrebbe esaurire rapidamente lo spazio su disco sul server. E ci vorrebbe anche più tempo per completare ogni integrazione.

Detto questo, ci spostiamo nella scheda "Programma" e ne abbiamo già parlato nel paragrafo precedente. Quindi, il prossimo argomento di interesse è la firma del codice. Si noti che, anche se la destinazione del test potrebbe indicare che non necessita di un profilo di provisioning nella pagina delle impostazioni del progetto, è necessario configurarlo per utilizzare lo stesso team e lo stesso certificato di firma dell'applicazione host. Questo è necessario se desideri testare la tua app su un dispositivo iOS anziché solo su un simulatore. Se questo è il tuo caso, devi anche assicurarti che il dispositivo iOS utilizzato per il test non venga bloccato a causa dell'inattività poiché ciò potrebbe causare il blocco indefinito dell'esecuzione dell'integrazione senza avvisarti.

Ora siamo nella scheda "Dispositivi" che non ha bisogno di spiegazioni specifiche. Seleziona semplicemente uno, più o tutti i dispositivi (iOS e simulatore) su cui vuoi testare il tuo codice. Puoi anche verificare se eseguire test su più dispositivi in ​​parallelo o in sequenza. Per configurarlo dovresti considerare le esigenze del tuo progetto (se stai prendendo di mira un set specifico di dispositivi o tutti i dispositivi iOS supportati) e anche le risorse hardware del server.

Nella scheda Argomenti . non è necessario specificare nulla in modo esplicito, poiché utilizzeremo solo variabili di ambiente integrate.

Infine, nella scheda Trigger , introdurremo uno script di pre-integrazione e uno di post-integrazione. Il primo è lì solo per aiutarci a eseguire il debug nel caso in cui dovessimo riscontrare alcuni problemi. In realtà è quello che abbiamo già usato:

 #!/bin/sh set printenv

Il secondo è quello che ci avviserà nel caso in cui uno o più dei nostri test falliscano nell'integrazione corrente. Assicurati che sia impostato per essere eseguito solo in caso di test non riusciti. E inserisci quanto segue:

 #!/bin/sh echo "$XCS_TEST_FAILURE_COUNT test(s) failed for $XCS_BOT_NAME bot on build $XCS_INTEGRATION_NUMBER" echo "You can see bot integration at:" echo "https://$HOSTNAME/xcode/bots/$XCS_BOT_TINY_ID/integrations/$XCS_INTEGRATION_TINY_ID"

Ci sono un paio di cose che dovrebbero essere spiegate qui. Innanzitutto, le variabili $HOSTNAME memorizzano il valore del seguente formato: nome-computer.local. Ovviamente, il collegamento funzionerebbe solo se riuscissi a raggiungere quel server tramite la rete locale. Inoltre, molto probabilmente riceverai un avviso di sicurezza dal tuo browser quando visiti questo link, poiché si tratta di una connessione https a una destinazione che non può essere considerata attendibile. Infine, questo è solo un punto di partenza per il tuo script "Test fallito". Puoi inviare un'e-mail all'intero team di sviluppo o aprire un problema JIRA tramite una richiesta API o qualsiasi altra cosa che ritieni sia la più appropriata e produttiva.

Avvolgendo

Si spera che questo articolo ti abbia incoraggiato a dedicare del tempo a esplorare le funzionalità di Xcode Server al di fuori della semplice creazione di un'app. Anche se questo post potrebbe non averti aiutato esattamente nel modo in cui volevi o ti aspettavi, l'obiettivo era quello di introdurti a un modo aperto di utilizzare gli ambienti integrati e le variabili di Xcode Server per ottenere un livello di automazione più elevato.

Ci sono molti servizi di terze parti là fuori che abilitano più funzionalità e possono fare molto più lavoro per te, inclusi Fabric, Bluepill e Fastlane. Ma, inevitabilmente, affidarsi a una terza parte introduce una nuova dipendenza nel progetto e richiede un'installazione e una configurazione a volte semplici, a volte complesse. Le tecniche qui descritte richiedono solo strumenti già installati su ogni Mac, quindi non richiede tempo di installazione oltre a configurare gli stessi bot che eseguiranno le tue build automatizzate!