ProHoster > blog > amministrazione > Esperienza CICD mobile: uno standard fastlane per molte applicazioni mobili
Esperienza CICD mobile: uno standard fastlane per molte applicazioni mobili
Vorrei parlare di integrazione continua e distribuzione di app mobili tramite fastlane. Come implementiamo CI/CD su tutte le applicazioni mobili, come ci siamo arrivati e cosa è successo alla fine.
In rete c'è già abbastanza materiale sullo strumento, cosa che all'inizio ci mancava, quindi volutamente non descriverò lo strumento in dettaglio, ma mi riferirò solo a ciò che avevamo allora:
Soluzione tecnica per l'implementazione di CI/CD per applicazioni N
La prima parte è più nostalgia per i vecchi tempi, mentre la seconda è un'esperienza che puoi applicare a te stesso.
Così è successo storicamente
2015 anno
Abbiamo appena iniziato a sviluppare applicazioni mobili, quindi non sapevamo nulla di integrazione continua, di DevOps e altre cose alla moda. Ogni aggiornamento dell'applicazione è stato implementato dallo sviluppatore stesso dal suo computer. E se per Android è abbastanza semplice: assemblato, firmato .apk e lo abbiamo caricato nella Console per gli sviluppatori di Google, poi per iOS l'allora strumento di distribuzione tramite Xcode ci ha lasciato delle serate fantastiche: i tentativi di scaricare l'archivio spesso finivano con errori e abbiamo dovuto riprovare. Si è scoperto che lo sviluppatore più avanzato non scrive il codice più volte al mese, ma piuttosto rilascia l'applicazione.
2016 anno
Siamo cresciuti, pensavamo già a come liberare gli sviluppatori da un'intera giornata per il rilascio, ed è apparsa anche una seconda applicazione, che ci ha solo spinto maggiormente verso l'automazione. Nello stesso anno abbiamo installato Jenkins per la prima volta e scritto una serie di script spaventosi, molto simili a quelli mostrati da Fastlane nella sua documentazione.
Sfortunatamente, fino ad ora solo i nostri sviluppatori sapevano come funzionano questi script e perché è necessaria questa pila infinita di chiavi, e quando qualcosa si è rotto di nuovo, hanno avuto delle “serate meravigliose” per analizzare i log.
2017 anno
Quest'anno abbiamo imparato che esiste una cosa chiamata fastlane. Non c'erano tante informazioni quante ce ne sono adesso: come avviarne uno, come usarlo. E lo strumento stesso a quel tempo era ancora rozzo: gli errori costanti non facevano altro che deluderci ed era difficile credere nella magica automazione che promettevano.
Tuttavia, le principali utilità incluse nel core Fastlane lo sono gym и pilot, siamo riusciti ad avviarlo.
I nostri script sono stati leggermente migliorati.
Sono stati migliorati, se non altro perché non tutti i parametri necessari per xcodebuild, devi indicare - gym capirà in modo indipendente dove e cosa si trova. E per una regolazione più precisa, puoi specificare le stesse chiavi di in xcodebuild, solo la denominazione dei tasti è più chiara.
Questa volta, grazie a Gym e al formattatore xcpretty integrato, i registri di compilazione sono diventati molto più leggibili. Ciò ha iniziato a far risparmiare tempo nella riparazione di assiemi danneggiati e talvolta il team di rilascio è riuscito a capirlo da solo.
Sfortunatamente, le misurazioni della velocità di assemblaggio xcodebuild и gym Non l'abbiamo fatto, ma ci fideremo della documentazione: fino al 30% di velocità in più.
Processo unico per tutte le applicazioni
Anno 2018 e presenti
Nel 2018, il processo di creazione e implementazione delle applicazioni è stato completamente spostato su Jenkins, gli sviluppatori hanno smesso di rilasciare dalle loro macchine e solo il team di rilascio aveva il diritto di rilasciare.
Volevamo già migliorare il lancio dei test e dell'analisi statica, e i nostri script crescevano sempre di più. Cresciuto e cambiato insieme alle nostre applicazioni. All’epoca le applicazioni erano circa 10. Considerando che abbiamo due piattaforme, si tratta di circa 20 script “vivi”.
Ogni volta che volevamo aggiungere un nuovo passaggio allo script, dovevamo copiare e incollare i pezzi in tutti gli script di shell. Forse avremmo potuto lavorare con più attenzione, ma spesso tali modifiche finivano con errori di battitura, che si trasformavano in serate in cui il team di rilascio passava a correggere gli script e scoprire quale ragazzo intelligente ha aggiunto questo comando e cosa fa effettivamente. In generale, non si può dire che gli script per l'assemblaggio per una piattaforma fossero almeno in qualche modo simili. Anche se sicuramente hanno fatto la stessa cosa.
Per avviare il processo per una nuova applicazione, era necessario dedicare un giorno alla selezione di una versione “fresca” di questi script, eseguirne il debug e dire che “sì, funziona”.
Nell’estate del 2018 abbiamo guardato ancora una volta alla fastlane ancora in fase di sviluppo.
Attività n. 1: riepilogare tutte le istruzioni di script e riscriverle in Fastfile
Quando abbiamo iniziato, i nostri script sembravano una coperta composta da tutti i passaggi e le stampelle in un unico script di shell in Jenkins. Non siamo ancora passati alla pipeline e alla divisione per fasi.
Abbiamo esaminato ciò che abbiamo e identificato 4 passaggi che si adattano alla descrizione del nostro CI/CD:
build: installazione delle dipendenze, assemblaggio dell'archivio,
test: esecuzione di test unitari per sviluppatori, calcolo della copertura,
sonar: avvia tutti i linter e invia report a SonarQube,
deploy: invio di un artefatto ad alpha (TestFlight).
E se non entri nei dettagli, omettendo i tasti usati nelle azioni, otterrai questo Fastfile:
default_platform(:ios)
platform :ios do
before_all do
unlock
end
desc "Build stage"
lane :build do
match
prepare_build
gym
end
desc "Prepare build stage: carthage and cocoapods"
lane :prepare_build do
pathCartfile = ""
Dir.chdir("..") do
pathCartfile = File.join(Dir.pwd, "/Cartfile")
end
if File.exist?(pathCartfile)
carthage
end
pathPodfile = ""
Dir.chdir("..") do
pathPodfile = File.join(Dir.pwd, "/Podfile")
end
if File.exist?(pathPodfile)
cocoapods
end
end
desc "Test stage"
lane :test do
scan
xcov
end
desc "Sonar stage (after run test!)"
lane :run_sonar do
slather
lizard
swiftlint
sonar
end
desc "Deploy to testflight stage"
lane :deploy do
pilot
end
desc "Unlock keychain"
private_lane :unlock do
pass = ENV['KEYCHAIN_PASSWORD']
unlock_keychain(
password: pass
)
end
end
In effetti, il nostro primo Fastfile si è rivelato mostruoso, considerando alcune delle stampelle di cui avevamo ancora bisogno e il numero di parametri che abbiamo sostituito:
lane :build do
carthage(
command: "update",
use_binaries: false,
platform: "ios",
cache_builds: true)
cocoapods(
clean: true,
podfile: "./Podfile",
use_bundle_exec: false)
gym(
workspace: "MyApp.xcworkspace",
configuration: "Release",
scheme: "MyApp",
clean: true,
output_directory: "/build",
output_name: "my-app.ipa")
end
lane :deploy do
pilot(
username: "[email protected]",
app_identifier: "com.example.app",
dev_portal_team_id: "TEAM_ID_NUMBER_DEV",
team_id: "ITS_TEAM_ID")
end
Nell'esempio sopra, solo una parte dei parametri che dobbiamo specificare: questi sono i parametri di build - schema, configurazione, nomi dei profili di fornitura, nonché parametri di distribuzione - ID Apple dell'account sviluppatore, password, ID dell'applicazione e così via SU. In prima approssimazione, inseriamo tutte queste chiavi in file speciali: Gymfile, Matchfile и Appfile.
Ora in Jenkins puoi richiamare comandi brevi che non offuscano la vista e siano facilmente leggibili a occhio nudo:
Cosa hai preso? Comandi chiari per ogni passaggio. Script ripuliti, disposti ordinatamente in file fastlane. Rallegrandoci, siamo corsi dagli sviluppatori chiedendo loro di aggiungere tutto ciò di cui avevano bisogno nei loro repository.
Ma ci siamo resi conto in tempo che avremmo incontrato le stesse difficoltà: avremmo ancora 20 script di assembly che in un modo o nell'altro avrebbero iniziato a vivere la propria vita, sarebbe stato più difficile modificarli, poiché gli script si sarebbero spostati nei repository, e non abbiamo avuto accesso lì. E, in generale, non sarà possibile risolvere il nostro dolore in questo modo.
Attività n.2: ottieni un singolo Fastfile per N applicazioni
Ora sembra che risolvere il problema non sia così difficile: imposta le variabili e andiamo. Sì, in effetti, è così che è stato risolto il problema. Ma nel momento in cui abbiamo sbagliato tutto, non avevamo né esperienza nella fastlane stessa, né in Ruby, in cui è scritto fastlane, né esempi utili sulla rete: tutti quelli che scrivevano su fastlane allora si limitavano a un esempio per un'applicazione per uno sviluppatore.
Fastlane può gestire variabili d'ambiente e lo abbiamo già provato impostando la password del portachiavi:
ENV['KEYCHAIN_PASSWORD']
Dopo aver esaminato i nostri script, abbiamo identificato le parti comuni:
#for build, test and deploy
APPLICATION_SCHEME_NAME=appScheme
APPLICATION_PROJECT_NAME=app.xcodeproj
APPLICATION_WORKSPACE_NAME=app.xcworkspace
APPLICATION_NAME=appName
OUTPUT_IPA_NAME=appName.ipa
#app info
APP_BUNDLE_IDENTIFIER=com.example.appName
[email protected]
TEAM_ID=ABCD1234
FASTLANE_ITC_TEAM_ID=123456789
Ora, per iniziare a utilizzare queste chiavi nei file fastlane, dovevamo capire come consegnarle lì. Fastlane ha una soluzione per questo: caricamento delle variabili tramite dotenv. La documentazione dice che se per te è importante caricare le chiavi per scopi diversi, crea diversi file di configurazione nella directory fastlane .env, .env.default, .env.development.
E poi abbiamo deciso di utilizzare questa libreria in modo leggermente diverso. Inseriamo nel repository degli sviluppatori non gli script fastlane e le relative meta informazioni, ma le chiavi univoche di questa applicazione nel file .env.appName.
se stessi Fastfile, Appfile, Matchfile и Gymfile, lo abbiamo nascosto in un repository separato. Lì era nascosto un file aggiuntivo con chiavi password di altri servizi: .env.
Puoi vedere un esempio qui.
Su CI la chiamata non è cambiata molto; è stata aggiunta una chiave di configurazione per un'applicazione specifica:
Per ora abbiamo lasciato questa soluzione, anche se Fastlane ha una soluzione per scaricare Fastfile tramite azioneimport_from_git, ma funziona solo per Fastfile, ma non per altri file. Se vuoi “davvero bello”, puoi scriverne uno tuo action.
Un set simile è stato creato per le applicazioni Android e ReactNative, i file si trovano nello stesso repository, ma in rami diversi iOS, android и react_native.
Quando il team di rilascio vuole aggiungere qualche nuovo passaggio, le modifiche allo script vengono registrate tramite MR in git, non c'è più bisogno di cercare i colpevoli degli script non funzionanti e, in generale, ora devi provare a romperli.
Questo è certo
In precedenza, dedicavamo del tempo alla manutenzione di tutti gli script, all'aggiornamento e alla correzione di tutte le conseguenze degli aggiornamenti. È stato molto deludente quando le ragioni degli errori e dei tempi di inattività nei rilasci erano semplici errori di battitura di cui era così difficile tenere traccia nel caos degli script di shell. Ora tali errori sono ridotti al minimo. Le modifiche vengono implementate in tutte le applicazioni contemporaneamente. Inoltre, sono necessari 15 minuti per inserire una nuova applicazione nel processo: impostare una pipeline di modelli su CI e aggiungere le chiavi al repository dello sviluppatore.
Sembra che il problema con Fastfile per Android e la firma dell'applicazione rimanga inspiegato, se l'articolo è interessante scriverò il seguito. Sarò felice di vedere le tue domande o suggerimenti "come risolveresti questo problema" nei commenti o su Telegram Bashkirova.