Mobile CICD iskustvo: jedan brzi standard za mnoge mobilne aplikacije
Želio bih govoriti o kontinuiranoj integraciji i isporuci mobilnih aplikacija koje koriste fastlane. Kako implementiramo CI/CD na sve mobilne aplikacije, kako smo do toga došli i šta se na kraju dogodilo.
Na mreži već postoji dovoljno materijala o alatu, koji nam je toliko nedostajao u startu, tako da namjerno neću detaljno opisivati alat, već ću se osvrnuti samo na ono što smo tada imali:
Tehničko rješenje za uvođenje CI/CD-a za N-aplikacije
Prvi dio je više nostalgija za starim danima, a drugi je iskustvo koje možete primijeniti na sebe.
Ovako se to istorijski desilo
Godina 2015
Tek smo počeli da razvijamo mobilne aplikacije, tada nismo znali ništa o kontinuiranoj integraciji, o DevOps-u i drugim modernim stvarima. Svako ažuriranje aplikacije razvijao je sam programer sa svoje mašine. A ako je za Android prilično jednostavno - sastavljeno, potpisano .apk i uploadovao je na Google Developer Console, zatim za iOS tadašnji alat za distribuciju preko Xcode-a ostavio nam je sjajne večeri - pokušaji preuzimanja arhive često su završavali greškama i morali smo pokušati ponovo. Pokazalo se da najnapredniji programer ne piše kod nekoliko puta mjesečno, već pušta aplikaciju.
Godina 2016
Odrasli smo, već smo razmišljali o tome kako osloboditi programere cijelog dana za izdanje, a pojavila se i druga aplikacija koja nas je samo više gurnula ka automatizaciji. Iste godine smo prvi put instalirali Jenkinsa i napisali gomilu strašnih skripti, vrlo sličnih onima koje fastlane pokazuje u svojoj dokumentaciji.
Nažalost, do sada su samo naši programeri znali kako ove skripte funkcionišu i zašto je potreban ovaj beskrajni snop ključeva, a kada bi se nešto ponovo pokvarilo, dobili su “prekrasne večeri” za analizu logova.
Godina 2017
Ove godine smo saznali da postoji takva stvar kao što je fastlane. Nije bilo toliko informacija kao sada – kako je pokrenuti, kako je koristiti. A sam alat je u to vrijeme još uvijek bio grub: stalne greške su nas samo razočarale i bilo je teško povjerovati u magičnu automatizaciju koju su obećavali.
Međutim, glavni uslužni programi uključeni u fastlane jezgro su gym и pilot, uspjeli smo ga pokrenuti.
Oni su poboljšani, makar samo zato što nisu svi parametri potrebni za xcodebuild, morate naznačiti - gym samostalno će razumjeti gdje i šta leži. A za više finog podešavanja, možete odrediti iste tipke kao u xcodebuild, samo je imenovanje ključeva jasnije.
Ovog puta, zahvaljujući teretani i ugrađenom xcpretty formateru, zapisnici izgradnje postali su mnogo čitljiviji. Ovo je počelo uštedjeti vrijeme na popravljanju pokvarenih sklopova, a ponekad je tim za izdavanje mogao to sam shvatiti.
Nažalost, mjerenja brzine montaže xcodebuild и gym Nismo to učinili, ali ćemo vjerovati dokumentaciji - do 30% ubrzanja.
Jedinstveni proces za sve aplikacije
2018. godina i danas
Do 2018. godine, proces izgradnje i puštanja aplikacija u potpunosti se preselio na Jenkins, programeri su prestali da objavljuju sa svojih mašina, a pravo izdavanja imao je samo tim za izdavanje.
Već smo željeli poboljšati pokretanje testova i statičke analize, a naše skripte su rasle i rasle. Rasla i mijenjala se zajedno s našim aplikacijama. Tada je bilo oko 10 aplikacija.S obzirom da imamo dvije platforme, to je oko 20 “živih” skripti.
Svaki put kada smo htjeli dodati novi korak skripti, morali smo kopirati i zalijepiti dijelove u sve shell skripte. Možda smo mogli raditi pažljivije, ali često su se takve promjene završavale greškama u kucanju, koje su se pretvarale u večeri za tim za izdavanje da popravi skripte i otkrije koji je pametnjaković dodao ovu komandu i šta ona zapravo radi. Općenito, ne može se reći da su skripte za sklapanje za jednu platformu bile barem donekle slične. Iako su oni sigurno radili istu stvar.
Da bi se pokrenuo proces za novu aplikaciju, bilo je potrebno potrošiti jedan dan da odaberete „svježu“ verziju ovih skripti, otklonite je grešku i kažete „da, radi“.
U ljeto 2018. ponovo smo se osvrnuli na brzu traku koja se još uvijek razvija.
Zadatak #1: sumirajte sve korake skripte i prepišite ih u Fastfile
Kada smo počeli, naše skripte su izgledale kao krpa za noge koja se sastoji od svih stepenica i štaka u jednoj školjki skripte u Dženkinsu. Još nismo prešli na cjevovod i podjelu po etapu.
Pogledali smo šta imamo i identifikovali 4 koraka koji odgovaraju opisu našeg CI/CD-a:
test — izvođenje jediničnih testova programera, izračunavanje pokrivenosti,
sonar - pokreće sve lintere i šalje izvještaje na SonarQube,
deploy — slanje artefakta alfa (TestFlight).
A ako ne ulazite u detalje, izostavljajući tipke koje se koriste u akcijama, dobit ćete ovaj 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
Zapravo, naš prvi Fastfile ispao je monstruozan, s obzirom na neke od štaka koje su nam još uvijek bile potrebne i broj parametara koje smo zamijenili:
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
U gornjem primjeru, samo dio parametara koje trebamo navesti: to su parametri izgradnje - shema, konfiguracija, nazivi profila za proviziju, kao i parametri distribucije - Apple ID računa programera, lozinka, ID aplikacije itd. on. Kao prvu aproksimaciju, sve ove ključeve stavljamo u posebne fajlove - Gymfile, Matchfile и Appfile.
Sada u Jenkinsu možete pozivati kratke komande koje ne zamućuju pogled i lako su čitljive okom:
šta si dobio? Jasne komande za svaki korak. Očišćene skripte, uredno raspoređene u fastlane fajlove. Radujući se, otrčali smo kod programera tražeći od njih da dodaju sve što im je potrebno u svoja spremišta.
Ali s vremenom smo shvatili da ćemo naići na iste poteškoće - i dalje ćemo imati 20 asemblerskih skripti koje bi na ovaj ili onaj način počele živjeti vlastitim životom, bilo bi ih teže uređivati, jer bi se skripte preselile u spremišta, i nismo imali pristup tamo. I, generalno, na ovaj način neće biti moguće riješiti našu bol.
Zadatak #2: nabavite jedan Fastfile za N aplikacija
Sada se čini da rješavanje problema nije tako teško - postavite varijable i idemo. Da, zapravo, tako je problem riješen. Ali u trenutku kada smo to zeznuli, nismo imali ni stručnost za sam fastlane, ni za Ruby, u kojem je napisan fastlane, niti korisne primjere na mreži - svi koji su tada pisali o fastlaneu bili su ograničeni na primjer za jednu aplikaciju za jednog programera.
Fastlane može upravljati varijablama okruženja, a mi smo to već isprobali postavljanjem lozinke za privjesak ključeva:
ENV['KEYCHAIN_PASSWORD']
Nakon što smo pogledali naše skripte, identifikovali smo zajedničke dijelove:
#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
Sada, da bismo počeli da koristimo ove ključeve u fastlane fajlovima, morali smo da smislimo kako da ih tamo isporučimo. Fastlane ima rješenje za ovo: učitavanje varijabli preko dotenv. Dokumentacija kaže da ako vam je važno da učitate ključeve za različite svrhe, kreirajte nekoliko konfiguracijskih datoteka u fastlane direktoriju .env, .env.default, .env.development.
A onda smo odlučili da ovu biblioteku koristimo malo drugačije. Stavimo u spremište programera ne skripte za brzu traku i njihove meta informacije, već jedinstvene ključeve ove aplikacije u datoteci .env.appName.
Oni sami Fastfile, Appfile, Matchfile и Gymfile, sakrili smo ga u posebno spremište. Tamo je sakriven dodatni fajl sa ključevima lozinki sa drugih servisa - .env.
Možete vidjeti primjer ovdje.
Na CI se poziv nije mnogo promijenio; dodat je konfiguracijski ključ za određenu aplikaciju:
Ostavio sam ovo rješenje za sada, iako Fastlane ima rješenje za preuzimanje Fastfilea putem akcijaimport_from_git, ali radi samo za Fastfile, ali ne i za druge datoteke. Ako želite "stvarno lijepo", možete napisati svoje action.
Sličan set je napravljen za Android aplikacije i ReactNative, fajlovi su u istom spremištu, ali u različitim granama iOS, android и react_native.
Kada tim za izdavanje želi dodati neki novi korak, promjene u skripti se snimaju putem MR-a u git-u, više nema potrebe tražiti krivce za pokvarene skripte, i općenito, sada morate pokušati to razbiti.
To je to sigurno
Ranije smo provodili vrijeme održavajući sve skripte, ažurirajući ih i popravljajući sve posljedice ažuriranja. Bilo je vrlo razočaravajuće kada su razlozi grešaka i zastoja u izdanjima bile jednostavne greške u kucanju koje je bilo tako teško pratiti u zbrci shell skripti. Sada su takve greške svedene na minimum. Promjene se uvode u sve aplikacije odjednom. A potrebno je 15 minuta da se nova aplikacija stavi u proces - postavite cevovod predložaka na CI i dodajte ključeve u spremište programera.
Čini se da stvar sa Fastfileom za Android i potpisom aplikacije ostaje neobjašnjena; ako je članak zanimljiv, napisat ću nastavak. Bit će mi drago vidjeti vaša pitanja ili prijedloge “kako biste riješili ovaj problem” u komentarima ili na Telegramu baškirova.