Mobil CICD-oplevelse: én fastlane-standard for mange mobile applikationer

Mobil CICD-oplevelse: én fastlane-standard for mange mobile applikationer
Jeg vil gerne tale om kontinuerlig integration og levering til mobilapps ved hjælp af fastlane. Hvordan vi implementerer CI/CD på alle mobile applikationer, hvordan vi kom dertil, og hvad der skete i sidste ende.

Der er allerede nok materiale på netværket på værktøjet, som vi så manglede i starten, så jeg vil bevidst ikke beskrive værktøjet i detaljer, men vil kun referere til det, vi havde dengang:

Artiklen består af to dele:

  • Baggrund for fremkomsten af ​​mobil CI/CD i virksomheden
  • Teknisk løsning til udrulning af CI/CD til N-applikationer

Den første del er mere nostalgi til gamle dage, og den anden er en oplevelse, som du kan anvende på dig selv.

Sådan skete det historisk

år 2015

Vi er lige begyndt at udvikle mobile applikationer, så vidste vi ikke noget om kontinuerlig integration, om DevOps og andre moderigtige ting. Hver applikationsopdatering blev rullet ud af udvikleren selv fra sin maskine. Og hvis det til Android er ret simpelt - samlet, signeret .apk og uploadede det til Google Developer Console, så til iOS efterlod det daværende distributionsværktøj via Xcode os med gode aftener - forsøg på at downloade arkivet endte ofte med fejl, og vi måtte prøve igen. Det viste sig, at den mest avancerede udvikler ikke skriver kode flere gange om måneden, men snarere frigiver applikationen.

år 2016

Vi voksede op, vi havde allerede tanker om, hvordan vi kunne frigøre udviklere fra en hel dag til en udgivelse, og en anden applikation dukkede også op, som kun skubbede os mere i retning af automatisering. Samme år installerede vi Jenkins for første gang og skrev en masse skræmmende scripts, meget lig dem, som fastlane viser i sin dokumentation.

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

Desværre har indtil nu kun vores udviklere vidst, hvordan disse scripts fungerer, og hvorfor denne endeløse stak af nøgler er nødvendig, og da noget gik i stykker igen, fik de de "smukke aftener" til at analysere logfiler.

år 2017

I år lærte vi, at der er sådan noget som fastlane. Der var ikke så meget information, som der er nu - hvordan man starter en, hvordan man bruger den. Og selve værktøjet var stadig råt på det tidspunkt: konstante fejl skuffede os kun, og det var svært at tro på den magiske automatisering, de lovede.

De vigtigste hjælpeprogrammer inkluderet i fastlane-kernen er dog gym и pilot, lykkedes det os at starte den.

Vores scripts er blevet forbedret en smule.

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

De er blevet forbedret, om ikke andet fordi ikke alle de nødvendige parametre til xcodebuild, skal du angive - gym vil selvstændigt forstå hvor og hvad der ligger. Og for mere finjustering kan du angive de samme taster som i xcodebuild, kun navngivningen af ​​tasterne er tydeligere.

Denne gang, takket være træningscenteret og den indbyggede xcpretty-formater, er byggelogfilerne blevet meget mere læselige. Dette begyndte at spare tid på at reparere ødelagte samlinger, og nogle gange kunne udgivelsesteamet finde ud af det på egen hånd.

Desværre monteringshastighedsmålinger xcodebuild и gym Vi gjorde det ikke, men vi stoler på dokumentationen - op til 30 % fremskyndelse.

En enkelt proces for alle ansøgninger

Årgang 2018 og nu

I 2018 flyttede processen med at bygge og udrulle applikationer fuldstændigt til Jenkins, udviklere holdt op med at frigive fra deres maskiner, og kun udgivelsesteamet havde ret til at frigive.

Vi ønskede allerede at forbedre lanceringen af ​​test og statisk analyse, og vores scripts voksede og voksede. Voksede og ændrede sig sammen med vores applikationer. På det tidspunkt var der omkring 10 applikationer. I betragtning af, at vi har to platforme, er det omkring 20 "levende" scripts.

Hver gang vi ønskede at tilføje et nyt trin til scriptet, var vi nødt til at kopiere og indsætte stykkerne i alle shell-scripts. Måske kunne vi have arbejdet mere omhyggeligt, men ofte endte sådanne ændringer med tastefejl, som blev til aftener for udgivelsesteamet for at rette scripts og finde ud af, hvilken smart fyr der tilføjede denne kommando, og hvad den rent faktisk gør. Generelt kan det ikke siges, at scripts til montering for én platform i det mindste var lidt ens. Selvom de bestemt gjorde det samme.

For at starte en proces for en ny applikation var det nødvendigt at bruge en dag på at vælge en "frisk" version af disse scripts, fejlfinde den og sige, at "ja, det virker."

I sommeren 2018 kiggede vi igen mod den stadigt udviklende fastlane.

Opgave #1: opsummer alle script-trin og omskriv dem i Fastfile

Da vi startede, lignede vores manuskripter en foddug, der bestod af alle trin og krykker i én skalmanuskript i Jenkins. Vi er endnu ikke gået over til pipeline og division for etape.

Vi så på, hvad vi har og identificerede 4 trin, der passer til beskrivelsen af ​​vores CI/CD:

  • build - installation af afhængigheder, samling af arkivet,
  • test — kørsel af udviklerenhedstests, beregning af dækning,
  • sonar - starter alle linters og sender rapporter til SonarQube,
  • deploy — sender en artefakt til alpha (TestFlight).

Og hvis du ikke går i detaljer og udelader nøglerne, der bruges i handlinger, får du denne 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

Faktisk viste vores første Fastfile sig at være monstrøs, i betragtning af nogle af de krykker, vi stadig havde brug for, og antallet af parametre, som vi erstattede:

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

I eksemplet ovenfor er det kun en del af parametrene, som vi skal specificere: disse er byggeparametrene - skema, konfiguration, Provisionsprofilnavne samt distributionsparametre - Apple-id for udviklerkontoen, adgangskode, applikations-id og så på. Som en første tilnærmelse lægger vi alle disse nøgler i specielle filer - Gymfile, Matchfile и Appfile.

Nu i Jenkins kan du kalde korte kommandoer, der ikke slører visningen og er let læselige for øjet:

# fastlane ios <lane_name>

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

Hurra, vi er gode

Hvad fik du? Klare kommandoer for hvert trin. Ryddede op i scripts, pænt arrangeret i fastlane-filer. Vi løb med glæde hen til udviklerne og bad dem om at tilføje alt, hvad de havde brug for til deres arkiver.

Men vi indså med tiden, at vi ville støde på de samme vanskeligheder - vi ville stadig have 20 assembly-scripts, der på en eller anden måde ville begynde at leve deres eget liv, det ville være sværere at redigere dem, da scripts ville flytte til repositories, og der havde vi ikke adgang. Og generelt vil det ikke være muligt at løse vores smerte på denne måde.

Mobil CICD-oplevelse: én fastlane-standard for mange mobile applikationer

Opgave #2: Få en enkelt Fastfile til N applikationer

Nu ser det ud til, at det ikke er så svært at løse problemet - indstil variablerne, og lad os gå. Ja, faktisk var det sådan, problemet blev løst. Men i det øjeblik, hvor vi skruede op, havde vi hverken ekspertise i selve fastlane eller i Ruby, som fastlane er skrevet i, eller brugbare eksempler på netværket - alle, der skrev om fastlane dengang, var begrænset til et eksempel for én applikation for én udvikler.

Fastlane kan håndtere miljøvariabler, og vi har allerede prøvet dette ved at indstille nøgleringsadgangskoden:

ENV['KEYCHAIN_PASSWORD']

Efter at have set på vores scripts, identificerede vi de fælles 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

Nu, for at begynde at bruge disse nøgler i fastlane-filer, var vi nødt til at finde ud af, hvordan vi kunne levere dem der. Fastlane har en løsning til dette: indlæsning af variabler via dotenv. Dokumentationen siger, at hvis det er vigtigt for dig at indlæse nøgler til forskellige formål, skal du oprette flere konfigurationsfiler i fastlane-mappen .env, .env.default, .env.development.

Og så besluttede vi at bruge dette bibliotek lidt anderledes. Lad os ikke placere fastlane-scripts og dets metainformation i udviklernes lager, men de unikke nøgler til denne applikation i filen .env.appName.

selv Fastfile, Appfile, Matchfile и Gymfile, gemte vi det i et separat lager. En ekstra fil med adgangskodenøgler fra andre tjenester var skjult der - .env.
Du kan se et eksempel her.

Mobil CICD-oplevelse: én fastlane-standard for mange mobile applikationer

På CI har opkaldet ikke ændret sig meget; en konfigurationsnøgle til en specifik applikation er blevet tilføjet:

# 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

Før vi kører kommandoerne, indlæser vi vores lager med scripts. Det ser ikke så pænt ud:

git clone [email protected]/FastlaneCICD.git fastlane_temp

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

Forlod denne løsning for nu, selvom Fastlane har en løsning til at downloade Fastfile via Action import_from_git, men det virker kun for Fastfile, men ikke for andre filer. Hvis du vil have "rigtig smuk", kan du skrive din egen action.

Et lignende sæt blev lavet til Android-applikationer og ReactNative, filerne er i det samme lager, men i forskellige grene iOS, android и react_native.

Når udgivelsesteamet ønsker at tilføje et nyt trin, optages ændringer i scriptet via MR i git, der er ikke længere behov for at lede efter synderne af ødelagte scripts, og generelt skal du nu prøve at bryde det.

Nu er det helt sikkert det

Tidligere brugte vi tid på at vedligeholde alle scripts, opdatere dem og rette op på alle konsekvenser af opdateringer. Det var meget skuffende, da årsagerne til fejl og nedetid i udgivelser var simple tastefejl, som var så svære at holde styr på i virvar af shell-scripts. Nu er sådanne fejl reduceret til et minimum. Ændringer udrulles til alle applikationer på én gang. Og det tager 15 minutter at sætte en ny applikation ind i processen - opsæt en skabelonpipeline på CI og tilføj nøglerne til udviklerens lager.

Det ser ud til, at pointen med Fastfile til Android og applikationssignatur forbliver uforklarlig; hvis artiklen er interessant, vil jeg skrive en fortsættelse. Jeg vil være glad for at se dine spørgsmål eller forslag "hvordan ville du løse dette problem" i kommentarerne eller på Telegram bashkirova.

Kilde: www.habr.com

Tilføj en kommentar