Mobilný CICD zážitok: jeden štandard rýchlej dráhy pre mnoho mobilných aplikácií

Mobilný CICD zážitok: jeden štandard rýchlej dráhy pre mnoho mobilných aplikácií
Chcel by som hovoriť o nepretržitej integrácii a poskytovaní mobilných aplikácií pomocou fastlane. Ako implementujeme CI/CD do všetkých mobilných aplikácií, ako sme sa k tomu dostali a čo sa nakoniec stalo.

Na nástroji je už na sieti dostatok materiálu, ktorý nám na začiatku tak chýbal, takže schválne nebudem nástroj podrobne popisovať, ale odkážem len na to, čo sme vtedy mali:

Článok sa skladá z dvoch častí:

  • Pozadie vzniku mobilného CI/CD v spoločnosti
  • Technické riešenie pre zavedenie CI/CD pre N-aplikácie

Prvá časť je skôr nostalgia za starými časmi a druhá skúsenosť, ktorú môžete aplikovať na seba.

Takto sa to historicky stalo

Rok 2015

Práve sme začali vyvíjať mobilné aplikácie, potom sme nevedeli nič o kontinuálnej integrácii, o DevOps a iných módnych veciach. Každú aktualizáciu aplikácie spustil samotný vývojár zo svojho stroja. A ak je to pre Android celkom jednoduché - zostavené, podpísané .apk a nahrali ho do Google Developer Console, potom nám pre iOS vtedajší distribučný nástroj cez Xcode zanechal skvelé večery – pokusy o stiahnutie archívu často končili chybami a museli sme to skúsiť znova. Ukázalo sa, že najpokročilejší vývojár nepíše kód niekoľkokrát do mesiaca, ale radšej vydá aplikáciu.

Rok 2016

Vyrástli sme, už sme mali myšlienky, ako oslobodiť vývojárov z celého dňa na vydanie a objavila sa aj druhá aplikácia, ktorá nás len posunula viac k automatizácii. V tom istom roku sme prvýkrát nainštalovali Jenkinsa a napísali sme veľa strašidelných skriptov, veľmi podobných tým, ktoré fastlane ukazuje vo svojej dokumentácii.

$ 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"

Žiaľ, doteraz len naši vývojári vedeli, ako tieto skripty fungujú a prečo je potrebný tento nekonečný balík kľúčov, a keď sa opäť niečo pokazilo, dostali „nádherné večery“ na analýzu protokolov.

Rok 2017

Tento rok sme sa dozvedeli, že existuje niečo ako fastlane. Nebolo toľko informácií ako teraz - ako začať, ako ho používať. A samotný nástroj bol v tom čase ešte hrubý: neustále chyby nás len sklamali a bolo ťažké uveriť v magickú automatizáciu, ktorú sľubovali.

Avšak hlavné nástroje zahrnuté v jadre fastlane sú gym и pilot, podarilo sa nám to naštartovať.

Naše skripty boli trochu vylepšené.

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

Boli vylepšené, už len preto, že nie všetky potrebné parametre xcodebuild, musíte uviesť - gym nezávisle pochopí, kde a čo leží. A pre jemnejšie doladenie môžete zadať rovnaké klávesy ako v xcodebuild, prehľadnejšie je len pomenovanie kláves.

Tentoraz sa vďaka posilňovni a vstavanému formátovaču xcpretty stali protokoly zostavenia oveľa čitateľnejšie. To začalo šetriť čas pri oprave poškodených zostáv a niekedy na to mohol tím uvoľnenia prísť sám.

Bohužiaľ, meranie rýchlosti montáže xcodebuild и gym Neurobili sme to, ale budeme dôverovať dokumentácii – zrýchlenie až o 30 %.

Jediný proces pre všetky aplikácie

Rok 2018 a súčasnosť

Do roku 2018 sa proces vytvárania a zavádzania aplikácií úplne presunul do Jenkins, vývojári prestali uvoľňovať zo svojich strojov a právo na vydanie mal iba tím, ktorý ich vydal.

Už sme chceli zlepšiť spúšťanie testov a statickej analýzy a naše skripty rástli a rástli. Rástol a menil sa spolu s našimi aplikáciami. V tom čase to bolo asi 10 aplikácií. Vzhľadom na to, že máme dve platformy, je to asi 20 „živých“ skriptov.

Zakaždým, keď sme chceli do skriptu pridať nový krok, museli sme jednotlivé časti skopírovať a vložiť do všetkých skriptov shellu. Možno sme mohli pracovať opatrnejšie, ale často sa takéto zmeny končili preklepmi, ktoré sa zmenili na večery, aby tím pre vydanie opravoval skripty a zisťoval, ktorý chytrák pridal tento príkaz a čo vlastne robí. Vo všeobecnosti sa nedá povedať, že by skripty na montáž pre jednu platformu boli aspoň trochu podobné. Aj keď určite urobili to isté.

Na spustenie procesu novej aplikácie bolo potrebné stráviť deň výberom „čerstvej“ verzie týchto skriptov, odladiť ju a povedať, že „áno, funguje“.

V lete 2018 sme sa opäť pozreli smerom k stále sa rozvíjajúcej rýchlej ceste.

Úloha č. 1: zhrňte všetky kroky skriptu a prepíšte ich do Fastfile

Keď sme začínali, naše skripty vyzerali ako handrička pozostávajúca zo všetkých krokov a barlí v jednom skripte v Jenkins. Ešte sme neprešli na plynovod a rozdelenie po etapách.

Pozreli sme sa na to, čo máme, a identifikovali sme 4 kroky, ktoré zodpovedajú popisu nášho CI/CD:

  • build - inštalácia závislostí, zostavenie archívu,
  • test – spustenie testov vývojárskych jednotiek, výpočet pokrytia,
  • sonar - spustí všetky lintery a odošle správy do SonarQube,
  • nasadiť — odoslanie artefaktu do alfa (TestFlight).

A ak nejdete do detailov a vynecháte kľúče používané pri akciách, získate tento 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

V skutočnosti sa náš prvý Fastfile ukázal ako obludný, berúc do úvahy niektoré barličky, ktoré sme ešte potrebovali, a množstvo parametrov, ktoré sme nahradili:

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

Vo vyššie uvedenom príklade je potrebné špecifikovať iba časť parametrov, ktoré musíme špecifikovať: sú to parametre zostavy - schéma, konfigurácia, názvy profilov poskytovania, ako aj parametre distribúcie - Apple ID účtu vývojára, heslo, ID aplikácie atď. na. Ako prvé priblíženie sme všetky tieto kľúče vložili do špeciálnych súborov - Gymfile, Matchfile и Appfile.

Teraz v Jenkins môžete volať krátke príkazy, ktoré nerozmazávajú pohľad a sú ľahko čitateľné okom:

# fastlane ios <lane_name>

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

Hurá, máme sa skvele

Čo si dostal? Jasné príkazy pre každý krok. Vyčistené skripty, prehľadne usporiadané do rýchlych súborov. S radosťou sme bežali za vývojármi a požiadali ich, aby pridali všetko, čo potrebujú, do svojich úložísk.

Časom sme si ale uvedomili, že sa stretneme s rovnakými ťažkosťami – stále by sme mali 20 montážnych skriptov, ktoré by si tak či onak začali žiť vlastným životom, bolo by náročnejšie ich upravovať, keďže by sa skripty presúvali do repozitárov, a nemali sme tam prístup. A vo všeobecnosti nebude možné vyriešiť našu bolesť týmto spôsobom.

Mobilný CICD zážitok: jeden štandard rýchlej dráhy pre mnoho mobilných aplikácií

Úloha #2: získajte jeden Fastfile pre N aplikácií

Teraz sa zdá, že riešenie problému nie je také ťažké - nastavte premenné a poďme na to. Áno, v skutočnosti sa tak problém vyriešil. Ale v momente, keď sme to pokazili, nemali sme ani odborné znalosti v oblasti fastlane, ani v Ruby, v ktorom sa fastlane píše, ani užitočné príklady na sieti – každý, kto vtedy písal o fastlane, bol obmedzený na príklad pre jednu aplikáciu pre jeden vývojár.

Fastlane dokáže spracovať premenné prostredia a už sme to vyskúšali nastavením hesla Keychain:

ENV['KEYCHAIN_PASSWORD']

Po pohľade na naše skripty sme identifikovali spoločné časti:

#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

Teraz, aby sme mohli začať používať tieto kľúče v súboroch fastlane, museli sme prísť na to, ako ich tam doručiť. Fastlane má na to riešenie: načítavanie premenných cez dotenv. Dokumentácia hovorí, že ak je pre vás dôležité načítať kľúče na rôzne účely, vytvorte niekoľko konfiguračných súborov v adresári fastlane .env, .env.default, .env.development.

A potom sme sa rozhodli využiť túto knižnicu trochu inak. Umiestňme do úložiska vývojárov nie rýchle skripty a ich meta informácie, ale jedinečné kľúče tejto aplikácie v súbore .env.appName.

sami Fastfile, Appfile, Matchfile и Gymfile, ukryli sme ho do samostatného úložiska. Bol tam skrytý ďalší súbor s kľúčmi hesiel z iných služieb - .env.
Môžete vidieť príklad tu.

Mobilný CICD zážitok: jeden štandard rýchlej dráhy pre mnoho mobilných aplikácií

Na CI sa volanie príliš nezmenilo, bol pridaný konfiguračný kľúč pre konkrétnu aplikáciu:

# 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

Pred spustením príkazov načítame naše úložisko skriptami. Nevyzerá tak pekne:

git clone [email protected]/FastlaneCICD.git fastlane_temp

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

Toto riešenie zatiaľ opustilo, hoci Fastlane má riešenie na stiahnutie Fastfile cez akčná import_from_git, ale funguje to len pre Fastfile, ale nie pre iné súbory. Ak chcete „naozaj krásne“, môžete napísať svoje vlastné action.

Podobná sada bola vyrobená pre Android aplikácie a ReactNative, súbory sú v rovnakom úložisku, ale v rôznych vetvách iOS, android и react_native.

Keď chce release team pridať nejaký nový krok, zmeny v skripte sa zaznamenávajú cez MR v git, už nie je potrebné hľadať vinníkov pokazených skriptov a vôbec, teraz sa to musíte pokúsiť prelomiť.

Teraz je to isté

Predtým sme trávili čas údržbou všetkých skriptov, ich aktualizáciou a opravou všetkých dôsledkov aktualizácií. Bolo veľkým sklamaním, keď príčinou chýb a výpadkov vo vydaniach boli jednoduché preklepy, ktoré bolo také ťažké sledovať v spleti skriptov shellu. Teraz sú takéto chyby obmedzené na minimum. Zmeny sa zavedú do všetkých aplikácií naraz. A vloženie novej aplikácie do procesu trvá 15 minút – nastavte kanál šablón na CI a pridajte kľúče do úložiska vývojára.

Zdá sa, že pointa s Fastfile pre Android a podpisom aplikácie zostáva nevysvetlená, ak bude článok zaujímavý, napíšem pokračovanie. Rád uvidím vaše otázky alebo návrhy „ako by ste vyriešili tento problém“ v komentároch alebo v telegrame baškirovej.

Zdroj: hab.com

Pridať komentár