Mobilna izkušnja CICD: en standard hitrega traku za številne mobilne aplikacije

Mobilna izkušnja CICD: en standard hitrega traku za številne mobilne aplikacije
Rad bi govoril o neprekinjeni integraciji in dostavi za mobilne aplikacije, ki uporabljajo fastlane. Kako implementiramo CI/CD na vse mobilne aplikacije, kako smo prišli do tega in kaj se je zgodilo na koncu.

Na omrežju je že dovolj gradiva o orodju, ki nam ga je na začetku tako primanjkovalo, zato orodja namenoma ne bom podrobneje opisoval, ampak se bom skliceval le na tisto, kar smo takrat imeli:

Članek je sestavljen iz dveh delov:

  • Ozadje za nastanek mobilnih CI/CD v podjetju
  • Tehnična rešitev za uvedbo CI/CD za N-aplikacije

Prvi del je bolj nostalgija po starih časih, drugi pa izkušnja, ki jo lahko prenesete nase.

Tako se je zgodovinsko zgodilo

Leto 2015

Komaj smo začeli razvijati mobilne aplikacije, takrat še nismo vedeli ničesar o kontinuirani integraciji, o DevOps in drugih modnih stvareh. Vsako posodobitev aplikacije je uvedel razvijalec sam s svojega računalnika. In če je za Android precej preprosto - sestavljeno, podpisano .apk in ga naložil v Googlovo konzolo za razvijalce, nato pa nam je za iOS takratno distribucijsko orodje prek Xcode pustilo odlične večere – poskusi prenosa arhiva so se pogosto končali z napakami in morali smo poskusiti znova. Izkazalo se je, da najnaprednejši razvijalec ne piše kode večkrat na mesec, temveč izda aplikacijo.

Leto 2016

Zrasli smo, razmišljali smo že o tem, kako razvijalcem sprostiti cel dan za objavo, pojavila pa se je tudi druga aplikacija, ki nas je le bolj potisnila v avtomatizacijo. Istega leta smo prvič namestili Jenkinsa in napisali kup strašljivih skriptov, zelo podobnih tistim, ki jih fastlane prikazuje v svoji 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 so do sedaj samo naši razvijalci vedeli, kako te skripte delujejo in zakaj je ta neskončen kup ključev potreben, in ko se je spet kaj zalomilo, so dobili »čudovite večere« za analizo dnevnikov.

Leto 2017

Letos smo izvedeli, da obstaja nekaj takega, kot je fastlane. Ni bilo toliko informacij kot zdaj - kako ga začeti, kako ga uporabiti. In samo orodje je bilo takrat še surovo: stalne napake so nas samo razočarale in težko je bilo verjeti v čarobno avtomatizacijo, ki so jo obljubljali.

Vendar pa so glavni pripomočki, vključeni v jedro fastlane gym и pilot, uspelo nam je začeti.

Naši skripti so bili nekoliko izboljšani.

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

Izboljšani so bili, čeprav samo zato, ker niso vsi parametri, potrebni za xcodebuild, morate navesti - gym bo samostojno razumel, kje in kaj leži. Za bolj natančno nastavitev pa lahko določite iste tipke kot v xcodebuild, bolj jasno je le poimenovanje tipk.

Tokrat so po zaslugi gyma in vgrajenega oblikovalnika xcpretty dnevniki gradnje postali veliko bolj berljivi. To je začelo prihraniti čas pri popravljanju pokvarjenih sklopov in včasih je ekipa za izdajo lahko to ugotovila sama.

Na žalost meritve hitrosti montaže xcodebuild и gym Tega nismo storili, vendar bomo zaupali dokumentaciji - do 30% pospešitev.

En sam postopek za vse aplikacije

Letnik 2018 in danes

Do leta 2018 se je postopek gradnje in uvajanja aplikacij v celoti preselil v Jenkins, razvijalci so prenehali izdajati s svojih strojev in samo ekipa za izdajo je imela pravico do izdaje.

Želeli smo izboljšati zagon testov in statične analize, naši skripti pa so rasli in rasli. Rastel in se spreminjal skupaj z našimi aplikacijami. Takrat je bilo aplikacij okoli 10. Glede na to, da imamo dve platformi, je to okoli 20 »živih« skript.

Vsakič, ko smo želeli skriptu dodati nov korak, smo morali dele kopirati in prilepiti v vse lupinske skripte. Morda bi lahko delali bolj previdno, a pogosto so se takšne spremembe končale s tipkarskimi napakami, ki so se spremenile v večere, ko je ekipa za izdajo popravila skripte in ugotovila, kateri pametnjakovič je dodal ta ukaz in kaj dejansko počne. Na splošno ni mogoče reči, da so bili skripti za montažo za eno platformo vsaj nekoliko podobni. Čeprav so zagotovo naredili isto.

Da bi začeli postopek za novo aplikacijo, je bilo treba porabiti en dan, da smo izbrali "svežo" različico teh skriptov, jo odpravili in rekli, da "ja, deluje."

Poleti 2018 smo se ponovno ozrli proti še razvijajočemu se fastlanu.

Naloga #1: povzeti vse korake skripta in jih prepisati v Fastfile

Ko smo začeli, so bili naši scenariji videti kot krpa za noge, sestavljena iz vseh korakov in bergel v enem skriptu lupine v Jenkinsu. Nismo še prešli na cevovod in delitev po stopnjah.

Pogledali smo, kaj imamo, in identificirali 4 korake, ki ustrezajo opisu našega CI/CD:

  • gradnja - namestitev odvisnosti, sestavljanje arhiva,
  • test — izvajanje testov razvijalskih enot, izračun pokritosti,
  • sonar - zažene vse linterje in pošlje poročila SonarQube,
  • uvedba — pošiljanje artefakta v alfa (TestFlight).

In če se ne spuščate v podrobnosti in izpustite tipke, ki se uporabljajo v dejanjih, boste dobili ta 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

Pravzaprav se je naš prvi Fastfile izkazal za pošastnega, glede na nekaj bergel, ki smo jih še potrebovali, in število parametrov, ki smo jih zamenjali:

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

V zgornjem primeru moramo določiti samo del parametrov: to so parametri gradnje - shema, konfiguracija, imena profila za zagotavljanje, kot tudi parametri distribucije - Apple ID računa razvijalca, geslo, ID aplikacije itd. na. Kot prvi približek smo vse te ključe spravili v posebne datoteke - Gymfile, Matchfile и Appfile.

Zdaj lahko v Jenkinsu pokličete kratke ukaze, ki ne zameglijo pogleda in so zlahka berljivi z očesom:

# fastlane ios <lane_name>

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

Hura, super smo

Kaj si dobil? Jasni ukazi za vsak korak. Očiščeni skripti, lepo urejeni v datotekah fastlane. Veseli smo tekli do razvijalcev in jih prosili, naj dodajo vse, kar potrebujejo, v svoje repozitorije.

Toda pravočasno smo ugotovili, da bomo naleteli na enake težave - še vedno bi imeli 20 montažnih skript, ki bi tako ali drugače začele živeti svoje življenje, težje bi jih bilo urejati, saj bi se skripte preselile v repozitorije, in tja nismo imeli dostopa. In na splošno naše bolečine na ta način ne bo mogoče rešiti.

Mobilna izkušnja CICD: en standard hitrega traku za številne mobilne aplikacije

Naloga #2: pridobite eno datoteko Fastfile za N aplikacij

Zdaj se zdi, da reševanje problema ni tako težko - nastavite spremenljivke in pojdimo. Ja, pravzaprav je bil problem rešen tako. Toda v trenutku, ko smo ga zajebali, nismo imeli niti ekspertize o samem fastlaneu, niti o Rubyju, v katerem piše fastlane, niti uporabnih primerov na omrežju - vsi, ki so takrat pisali o fastlanu, so bili omejeni na primer za eno aplikacijo za en razvijalec.

Fastlane lahko obravnava spremenljivke okolja in to smo že poskusili z nastavitvijo gesla Keychain:

ENV['KEYCHAIN_PASSWORD']

Po ogledu naših skriptov smo prepoznali skupne dele:

#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

Zdaj, da bi začeli uporabljati te ključe v datotekah fastlane, smo morali ugotoviti, kako jih dostaviti tja. Fastlane ima za to rešitev: nalaganje spremenljivk prek dotenv. V dokumentaciji piše, da če je pomembno, da naložite ključe za različne namene, ustvarite več konfiguracijskih datotek v imeniku fastlane .env, .env.default, .env.development.

In potem smo se odločili, da bomo to knjižnico uporabili malo drugače. V repozitorij razvijalcev ne postavimo skriptov fastlane in njihovih meta informacij, temveč edinstvene ključe te aplikacije v datoteki .env.appName.

Sami Fastfile, Appfile, Matchfile и Gymfile, smo ga skrili v ločeno skladišče. Tam je bila skrita dodatna datoteka s ključi gesel drugih storitev - .env.
Lahko vidite primer tukaj.

Mobilna izkušnja CICD: en standard hitrega traku za številne mobilne aplikacije

Na CI se klic ni veliko spremenil; dodan je konfiguracijski ključ za določeno aplikacijo:

# 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 izvajanjem ukazov naložimo naše skladišče s skripti. Ne izgleda tako lepo:

git clone [email protected]/FastlaneCICD.git fastlane_temp

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

To rešitev sem za zdaj pustil, čeprav ima Fastlane rešitev za prenos Fastfile prek ukrepanje import_from_git, vendar deluje samo za Fastfile, ne pa tudi za druge datoteke. Če želite "res lepo", lahko napišete svoje action.

Podoben nabor je bil narejen za aplikacije za Android in ReactNative, datoteke so v istem repozitoriju, vendar v različnih vejah iOS, android и react_native.

Ko ekipa za izdajo želi dodati kakšen nov korak, se spremembe v skriptu zabeležijo preko MR v git, ni več treba iskati krivcev za pokvarjene skripte in nasploh ga je zdaj treba poskusiti razbiti.

Zdaj je to zagotovo to

Prej smo porabili čas za vzdrževanje vseh skriptov, njihovo posodabljanje in popravljanje vseh posledic posodobitev. Bilo je zelo razočaranje, ko so bili razlogi za napake in izpade v izdajah preproste tipkarske napake, ki jim je bilo tako težko slediti v zmešnjavi lupinskih skriptov. Zdaj so takšne napake zmanjšane na minimum. Spremembe se uvedejo v vse aplikacije hkrati. In potrebujete 15 minut, da vstavite novo aplikacijo v postopek - nastavite cevovod predloge na CI in dodajte ključe v skladišče razvijalca.

Zdi se, da je bistvo s Fastfile za Android in podpisom aplikacije ostalo nepojasnjeno, če bo članek zanimiv, bom napisal nadaljevanje. Vesel bom vaših vprašanj ali predlogov "kako bi rešili to težavo" v komentarjih ali na Telegramu bashkirova.

Vir: www.habr.com

Dodaj komentar