Mobile CICD iskustvo: jedan brzi standard za mnoge mobilne aplikacije

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:

Članak se sastoji iz dva dela:

  • Pozadina nastanka mobilnih CI/CD u kompaniji
  • 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.

$ xcodebuild clean archive -archivePath build/MyApp 
    -scheme MyApp

$ xcodebuild -exportArchive 
                        -exportFormat ipa 
                        -archivePath "build/MyApp.xcarchive" 
                        -exportPath "build/MyApp.ipa" 
                        -exportProvisioningProfile "ProvisioningProfileName"

$ cd /Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/

$ ./altool —upload-app 
-f {abs path to your project}/build/{release scheme}.ipa  
-u "[email protected]" 
-p "PASS_APPLE_ID"

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.

Naše skripte su malo poboljšane.

$ fastlane gym  —-workspace "Example.xcworkspace" 
                --scheme "AppName" 
                —-buildlog_path "/tmp" 
                -—clean

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:

  • build - instaliranje zavisnosti, sastavljanje arhive,
  • 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:

# fastlane ios <lane_name>

$ fastlane ios build
$ fastlane ios test
$ fastlane ios run_sonar
$ fastlane ios deploy

Ura, super smo

š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.

Mobile CICD iskustvo: jedan brzi standard za mnoge mobilne aplikacije

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.

Mobile CICD iskustvo: jedan brzi standard za mnoge mobilne aplikacije

Na CI se poziv nije mnogo promijenio; dodat je konfiguracijski ključ za određenu aplikaciju:

# fastlane ios <lane_name> --env appName

$ fastlane ios build --env appName
$ fastlane ios test --env appName
$ fastlane ios run_sonar --env appName
$ fastlane ios deploy --env appName

Prije pokretanja naredbi, učitavamo naše spremište sa skriptama. Ne izgleda tako lijepo:

git clone [email protected]/FastlaneCICD.git fastlane_temp

cp ./fastlane_temp/fastlane/* ./fastlane/
cp ./fastlane_temp/fastlane/.env fastlane/.env

Ostavio sam ovo rješenje za sada, iako Fastlane ima rješenje za preuzimanje Fastfilea putem akcija import_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.

izvor: www.habr.com

Dodajte komentar