Experiència CICD mòbil: un estàndard de línia ràpida per a moltes aplicacions mòbils

Experiència CICD mòbil: un estàndard de línia ràpida per a moltes aplicacions mòbils
M'agradaria parlar de la integració i el lliurament contínues d'aplicacions mòbils que utilitzen Fastlane. Com implementem CI/CD a totes les aplicacions mòbils, com vam arribar-hi i què va passar al final.

Ja hi ha prou material a la xarxa sobre l'eina, que tant ens faltava al principi, així que deliberadament no descriuré l'eina en detall, sinó que només em referiré al que teníem aleshores:

L'article consta de dues parts:

  • Antecedents de l'aparició del CI/CD mòbil a l'empresa
  • Solució tècnica per desplegar CI/CD per a aplicacions N

La primera part és més nostàlgia dels vells temps, i la segona és una experiència que pots aplicar a tu mateix.

Així va passar històricament

Any 2015

Acabem de començar a desenvolupar aplicacions mòbils, després no sabíem res sobre la integració contínua, sobre DevOps i altres coses de moda. Cada actualització de l'aplicació va ser llançada pel mateix desenvolupador des de la seva màquina. I si per a Android és bastant senzill: muntat, signat .apk i el va penjar a la Consola per a desenvolupadors de Google, després per a iOS, l'eina de distribució a través de Xcode ens va deixar grans vetllades: els intents de descarregar l'arxiu sovint van acabar en errors i vam haver de tornar-ho a provar. Va resultar que el desenvolupador més avançat no escriu codi diverses vegades al mes, sinó que llança l'aplicació.

Any 2016

Vam créixer, ja teníem pensaments sobre com alliberar desenvolupadors d'un dia sencer per a un llançament, i també va aparèixer una segona aplicació, que només ens va empènyer més cap a l'automatització. Aquell mateix any, vam instal·lar Jenkins per primera vegada i vam escriure un munt de guions de por, molt semblants als que mostra Fastlane a la seva documentació.

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

Malauradament, fins ara només els nostres desenvolupadors sabien com funcionaven aquests scripts i per què calia aquesta pila interminable de claus, i quan alguna cosa es trencava de nou, tenien les "vetllades magnífiques" per analitzar els registres.

Any 2017

Aquest any hem après que hi ha una cosa com el fastlane. No hi havia tanta informació com ara: com començar-ne una, com utilitzar-la. I l'eina en si era encara crua en aquell moment: els errors constants només ens decebrien i era difícil de creure en l'automatització màgica que prometien.

No obstant això, les principals utilitats incloses al nucli Fastlane són gym и pilot, vam aconseguir posar-lo en marxa.

Els nostres guions s'han millorat una mica.

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

S'han millorat, encara que només perquè no tots els paràmetres necessaris per xcodebuild, cal indicar - gym entendre de manera independent on i què hi ha. I per a una millora més precisa, podeu especificar les mateixes tecles que a xcodebuild, només la denominació de les claus és més clara.

Aquesta vegada, gràcies al gimnàs i al formatador xcpretty integrat, els registres de compilació s'han tornat molt més llegibles. Això va començar a estalviar temps a arreglar conjunts trencats i, de vegades, l'equip de llançament ho podia resoldre per si mateix.

Malauradament, les mesures de velocitat de muntatge xcodebuild и gym No ho vam fer, però confiarem en la documentació: fins a un 30% d'acceleració.

Procés únic per a totes les sol·licituds

Any 2018 i present

L'any 2018, el procés de creació i desplegament d'aplicacions es va traslladar completament a Jenkins, els desenvolupadors van deixar de llançar-se de les seves màquines i només l'equip de llançament tenia dret a llançar-les.

Ja volíem millorar el llançament de proves i anàlisi estàtica, i els nostres scripts van créixer i créixer. Va créixer i canviar juntament amb les nostres aplicacions. En aquell moment hi havia unes 10 aplicacions, tenint en compte que tenim dues plataformes, són uns 20 scripts "vius".

Cada vegada que volíem afegir un nou pas a l'script, havíem de copiar i enganxar les peces a tots els scripts de l'intèrpret d'ordres. Potser podríem haver treballat amb més cura, però sovint aquests canvis van acabar amb errors d'ortografia, que es van convertir en vetllades perquè l'equip de llançament arregís scripts i esbrinés quin tipus intel·ligent va afegir aquesta ordre i què fa realment. En general, no es pot dir que els scripts per al muntatge d'una plataforma fossin almenys una mica similars. Encara que sens dubte van fer el mateix.

Per iniciar un procés per a una nova aplicació, va ser necessari passar un dia per seleccionar una versió "fresca" d'aquests scripts, depurar-la i dir que "sí, funciona".

A l'estiu del 2018, vam tornar a mirar cap a la línia ràpida encara en desenvolupament.

Tasca núm. 1: resumeix tots els passos de l'script i reescriu-los a Fastfile

Quan vam començar, els nostres guions semblaven un drap de peus format per tots els passos i crosses en un guió de shell a Jenkins. Encara no hem passat al pipeline i la divisió per etapes.

Hem analitzat el que tenim i hem identificat 4 passos que s'ajusten a la descripció del nostre CI/CD:

  • construir - instal·lar dependències, muntar l'arxiu,
  • prova: executar proves d'unitats de desenvolupadors, calcular la cobertura,
  • sonar: llança tots els linters i envia informes a SonarQube,
  • desplegar: enviant un artefacte a alpha (TestFlight).

I si no entres en detalls, ometent les claus utilitzades en les accions, obtindràs aquest fitxer ràpid:

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

De fet, el nostre primer Fastfile va resultar monstruós, tenint en compte algunes de les crosses que encara necessitàvem i el nombre de paràmetres que vam substituir:

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

A l'exemple anterior, només una part dels paràmetres que hem d'especificar: aquests són els paràmetres de compilació: esquema, configuració, noms de perfils de subministrament, així com paràmetres de distribució: ID d'Apple del compte de desenvolupador, contrasenya, identificador de l'aplicació, etc. activat. Com a primera aproximació, posem totes aquestes claus en fitxers especials: Gymfile, Matchfile и Appfile.

Ara, a Jenkins, podeu cridar ordres breus que no difuminen la vista i que siguin fàcilment llegibles a simple vista:

# fastlane ios <lane_name>

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

Hura, estem genials

Què has aconseguit? Comandes clares per a cada pas. Scripts netejats, ordenats perfectament en fitxers Fastlane. Alegres, vam córrer cap als desenvolupadors per demanar-los que afegissin tot el que necessitaven als seus repositoris.

Però amb el temps ens vam adonar que ens trobaríem amb les mateixes dificultats: encara tindríem 20 scripts de muntatge que d'una manera o altra començarien a viure la seva pròpia vida, seria més difícil editar-los, ja que els scripts es traslladarien als repositoris, i no hi teníem accés. I, en general, no serà possible resoldre el nostre dolor d'aquesta manera.

Experiència CICD mòbil: un estàndard de línia ràpida per a moltes aplicacions mòbils

Tasca núm. 2: obtenir un únic Fastfile per a N aplicacions

Ara sembla que resoldre el problema no és tan difícil: establiu les variables i anem-hi. Sí, de fet, així es va resoldre el problema. Però en el moment en què ho vam fer malbé, no teníem experiència en Fastlane en si, ni en Ruby, en el qual està escrit Fastlane, ni exemples útils a la xarxa: tots els que van escriure sobre Fastlane llavors es limitaven a un exemple per a una aplicació per a un desenvolupador.

Fastlane pot gestionar variables d'entorn, i ja ho hem provat establint la contrasenya del clauer:

ENV['KEYCHAIN_PASSWORD']

Després de mirar els nostres guions, vam identificar les parts comunes:

#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

Ara, per començar a utilitzar aquestes claus als fitxers Fastlane, havíem d'esbrinar com lliurar-les allà. Fastlane té una solució per a això: càrrega de variables mitjançant dotenv. La documentació diu que si és important que carregueu claus per a diferents propòsits, creeu diversos fitxers de configuració al directori Fastlane .env, .env.default, .env.development.

I aleshores vam decidir utilitzar aquesta biblioteca una mica diferent. Col·loquem al repositori dels desenvolupadors no els scripts de Fastlane i la seva metainformació, sinó les claus úniques d'aquesta aplicació al fitxer .env.appName.

Ells mateixos Fastfile, Appfile, Matchfile и Gymfile, el vam amagar en un repositori separat. S'hi va amagar un fitxer addicional amb claus de contrasenya d'altres serveis: .env.
Podeu veure un exemple aquí.

Experiència CICD mòbil: un estàndard de línia ràpida per a moltes aplicacions mòbils

A CI, la trucada no ha canviat gaire; s'ha afegit una clau de configuració per a una aplicació específica:

# 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

Abans d'executar les ordres, carreguem el nostre repositori amb scripts. No es veu tan bé:

git clone [email protected]/FastlaneCICD.git fastlane_temp

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

De moment, hem deixat aquesta solució, tot i que Fastlane té una solució per descarregar Fastfile mitjançant acció import_from_git, però només funciona per a Fastfile, però no per a altres fitxers. Si vols "realment bonic", pots escriure el teu action.

Es va fer un conjunt similar per a aplicacions d'Android i ReactNative, els fitxers es troben al mateix dipòsit, però en diferents branques iOS, android и react_native.

Quan l'equip de llançament vol afegir algun pas nou, els canvis en l'script es registren mitjançant MR a git, ja no cal buscar els culpables dels scripts trencats i, en general, ara cal intentar trencar-lo.

Ara això és tot segur

Anteriorment, hem dedicat temps a mantenir tots els scripts, actualitzar-los i corregir totes les conseqüències de les actualitzacions. Va ser molt decebedor quan els motius dels errors i el temps d'inactivitat a les versions eren simples errors d'ortografia que eren tan difícils de fer un seguiment en el revolt d'scripts d'intèrpret d'ordres. Ara aquests errors es redueixen al mínim. Els canvis s'apliquen a totes les aplicacions alhora. I es triguen 15 minuts a posar una aplicació nova al procés: configureu una canalització de plantilles a CI i afegiu les claus al repositori del desenvolupador.

Sembla que el punt amb Fastfile per a Android i la signatura de l'aplicació segueix sense explicar-se; si l'article és interessant, n'escriuré una continuació. Estaré encantat de veure les vostres preguntes o suggeriments "com resoldreu aquest problema" als comentaris o a Telegram bashkirova.

Font: www.habr.com

Afegeix comentari