Mobilno CICD iskustvo: jedan brzi standard za mnoge mobilne aplikacije

Mobilno 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 što se na kraju dogodilo.

Na mreži već ima dovoljno materijala o alatu koji nam je nedostajao u startu, pa namjerno neću detaljno opisivati ​​alat, već ću se osvrnuti samo na ono što smo tada imali:

Članak se sastoji od dva dijela:

  • Pozadina pojave mobilnog CI/CD-a u tvrtki
  • Tehničko rješenje za uvođenje CI/CD za N-aplikacije

Prvi dio je više nostalgija za starim danima, a drugi je iskustvo koje možete primijeniti na sebe.

Tako se to povijesno dogodilo

Godina 2015

Tek smo počeli razvijati mobilne aplikacije, tada nismo znali ništa o kontinuiranoj integraciji, o DevOpsu i ostalim pomodnim stvarima. Svako ažuriranje aplikacije uveo je programer sam sa svog računala. A ako je za Android prilično jednostavno - sastavljeno, potpisano .apk i uploadali ga na Google Developer Console, zatim nam je za iOS tadašnji alat za distribuciju preko Xcodea ostavio odlične večeri – pokušaji preuzimanja arhive često su završavali pogreškama i morali smo pokušavati ponovno. Pokazalo se da najnapredniji programer ne piše kod nekoliko puta mjesečno, već izdaje aplikaciju.

Godina 2016

Odrasli smo, već smo razmišljali o tome kako programere osloboditi cijelog dana za izdanje, a pojavila se i druga aplikacija koja nas je samo više gurnula prema automatizaciji. Iste godine smo prvi put instalirali Jenkinsa i napisali hrpu strašnih skripti, vrlo sličnih onima koje fastlane prikazuje 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 te skripte rade i zašto je potreban taj beskrajni hrp ključeva, a kad bi se opet nešto pokvarilo, dobili su “prekrasne večeri” za analizu zapisa.

Godina 2017

Ove godine smo saznali da postoji nešto poput fastlanea. Nije bilo toliko informacija kao sada - kako ga pokrenuti, kako ga koristiti. A sam alat je u to vrijeme još bio sirov: stalne greške samo su nas razočarale i bilo je teško povjerovati u čarobnu automatizaciju koju su obećavali.

Međutim, glavni uslužni programi uključeni u jezgru fastlanea 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, trebate navesti - gym samostalno će razumjeti gdje i što leži. A za više finog podešavanja, možete navesti iste tipke kao u xcodebuild, samo je imenovanje tipki jasnije.

Ovaj put, zahvaljujući teretani i ugrađenom formateru xcpretty, zapisnici izgradnje postali su mnogo čitljiviji. To je počelo uštedjeti vrijeme na popravljanju pokvarenih sklopova, a ponekad je tim za izdavanje mogao sam to shvatiti.

Nažalost, mjerenja brzine montaže xcodebuild и gym Mi to nismo učinili, ali ćemo vjerovati dokumentaciji - do 30% ubrzanja.

Jedinstveni proces za sve aplikacije

Godina 2018. i danas

Do 2018. proces izgradnje i izvođenja aplikacija potpuno se preselio u Jenkins, programeri su prestali izdavati sa svojih strojeva, a samo je tim za izdavanje imao pravo izdavanja.

Već smo željeli poboljšati pokretanje testova i statičke analize, a naše su skripte rasle i rasle. Rasla je 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 kad smo htjeli dodati novi korak u skriptu, morali smo kopirati i zalijepiti dijelove u sve skripte ljuske. Možda smo mogli raditi pažljivije, ali često su takve izmjene završavale greškama pri upisu, što se pretvaralo u večeri za tim za izdanje da popravi skripte i otkrije koji je pametnjaković dodao ovu naredbu i što ona zapravo radi. Općenito, ne može se reći da su skripte za montažu za jednu platformu bile barem donekle slične. Iako su sigurno učinili istu stvar.

Da bi se pokrenuo proces za novu aplikaciju, bilo je potrebno potrošiti jedan dan da se izabere “svježa” verzija ovih skripti, ispravi pogreška i kaže da “da, radi”.

U ljeto 2018. ponovno smo se okrenuli prema fastlaneu koji je još uvijek u razvoju.

Zadatak #1: sažeti sve korake skripte i prepisati ih u Fastfile

Kad smo počeli, naše su skripte izgledale kao krpa za noge koja se sastoji od svih stepenica i štaka u jednoj shell skripti u Jenkinsu. Nismo još prešli na cjevovod i podjelu po fazama.

Pogledali smo što imamo i identificirali 4 koraka koji odgovaraju opisu našeg CI/CD-a:

  • build - instaliranje ovisnosti, sastavljanje arhive,
  • test — izvođenje jediničnih testova programera, izračunavanje pokrivenosti,
  • sonar - pokreće sve lintere i šalje izvješća SonarQubeu,
  • deploy — slanje artefakta u alpha (TestFlight).

A ako ne idete 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 štake koje su nam još trebale 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 specificirati: to su parametri izgradnje - shema, konfiguracija, nazivi Provision Profile, kao i parametri distribucije - Apple ID računa razvojnog programera, lozinka, ID aplikacije itd. na. Kao prvu aproksimaciju, sve ove ključeve stavljamo u posebne datoteke - Gymfile, Matchfile и Appfile.

Sada u Jenkinsu možete pozivati ​​kratke naredbe koje ne zamagljuju pogled i lako su čitljive okom:

# fastlane ios <lane_name>

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

Hura, super smo

Što si dobio? Jasne naredbe za svaki korak. Očišćene skripte, uredno složene u fastlane datoteke. Radujući se, otrčali smo do programera tražeći od njih da dodaju sve što im je potrebno u njihova spremišta.

Ali s vremenom smo shvatili da ćemo se susresti s istim poteškoćama - i dalje bismo imali 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 repozitorije, a tamo nismo imali pristupa. I, općenito, neće biti moguće riješiti našu bol na ovaj način.

Mobilno CICD iskustvo: jedan brzi standard za mnoge mobilne aplikacije

Zadatak #2: dobiti 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. No, u trenutku kad smo ga zeznuli, nismo imali ekspertizu ni za sam fastlane, ni za Ruby u kojem piše fastlane, niti korisne primjere na mreži - svi koji su tada pisali o fastlaneu bili su ograničeni na primjer za jednu aplikaciju za jedan programer.

Fastlane može rukovati varijablama okruženja, a to smo već isprobali postavljanjem lozinke za privjesak ključeva:

ENV['KEYCHAIN_PASSWORD']

Nakon što smo pogledali naše skripte, identificirali 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 koristiti te ključeve u datotekama fastlanea, morali smo smisliti kako ih tamo isporučiti. Fastlane ima rješenje za to: učitavanje varijabli preko dotenv. Dokumentacija kaže da ako vam je važno učitati ključeve za različite svrhe, napravite nekoliko konfiguracijskih datoteka u direktoriju fastlane .env, .env.default, .env.development.

A onda smo odlučili ovu knjižnicu koristiti malo drugačije. Postavimo u repozitorij programera ne fastlane skripte i njihove meta informacije, već jedinstvene ključeve ove aplikacije u datoteci .env.appName.

sebe Fastfile, Appfile, Matchfile и Gymfile, sakrili smo ga u zasebno spremište. Tamo je bila skrivena dodatna datoteka s ključevima zaporki s drugih usluga - .env.
Možete vidjeti primjer здесь.

Mobilno CICD iskustvo: jedan brzi standard za mnoge mobilne aplikacije

Na CI-ju se poziv nije puno promijenio; dodan 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, svoje spremište učitavamo 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

Za sada sam ostavio ovo rješenje, iako Fastlane ima rješenje za preuzimanje Fastfilea putem akcijski 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 skup napravljen je za Android aplikacije i ReactNative, datoteke su u istom repozitoriju, ali u različitim granama iOS, android и react_native.

Kada tim za izdanje želi dodati neki novi korak, promjene u skripti se bilježe preko MR-a u git-u, više nema potrebe tražiti krivce za pokvarene skripte i općenito, sada je morate pokušati razbiti.

Sada je to sigurno to

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 za pogreške i zastoje u izdanjima bile jednostavne tipfelere koje je bilo tako teško pratiti u zbrci skripti ljuske. Sada su takve pogreške svedene na minimum. Promjene se uvode u sve aplikacije odjednom. I potrebno je 15 minuta da se nova aplikacija stavi u proces - postavite cjevovod predloška na CI i dodajte ključeve u repozitorij razvojnog programera.

Čini se da je poanta s Fastfileom za Android i potpisom aplikacije ostala nerazjašnjena, ako je članak zanimljiv, napisat ću nastavak. Bit će mi drago vidjeti vaša pitanja ili prijedloge "kako biste vi riješili ovaj problem" u komentarima ili na Telegramu bashkirova.

Izvor: www.habr.com

Dodajte komentar