Mobil CICD-upplevelse: en fastlane-standard för många mobila applikationer
Jag skulle vilja prata om kontinuerlig integration och leverans för mobilappar som använder fastlane. Hur vi implementerar CI/CD på alla mobila applikationer, hur vi kom dit och vad som hände till slut.
Det finns redan tillräckligt med material på nätverket på verktyget, som vi så saknade i början, så jag kommer medvetet inte att beskriva verktyget i detalj, utan kommer bara att referera till det vi hade då:
Bakgrund till framväxten av mobil CI/CD i företaget
Teknisk lösning för utrullning av CI/CD för N-applikationer
Den första delen är mer nostalgi för gamla dagar, och den andra är en upplevelse som du kan applicera på dig själv.
Det var så det hände historiskt
År 2015
Vi har precis börjat utveckla mobila applikationer, sedan visste vi ingenting om kontinuerlig integration, om DevOps och andra moderiktiga saker. Varje programuppdatering rullades ut av utvecklaren själv från sin maskin. Och om det är ganska enkelt för Android - monterat, signerat .apk och laddade upp det till Google Developer Console, sedan för iOS gav det dåvarande distributionsverktyget via Xcode oss fantastiska kvällar - försök att ladda ner arkivet slutade ofta i fel och vi var tvungna att försöka igen. Det visade sig att den mest avancerade utvecklaren inte skriver kod flera gånger i månaden, utan snarare släpper applikationen.
År 2016
Vi växte upp, vi hade redan tankar om hur vi skulle frigöra utvecklare från en hel dag för en release, och en andra applikation dök också upp, som bara drev oss mer mot automatisering. Samma år installerade vi Jenkins för första gången och skrev ett gäng läskiga skript, väldigt lika de som fastlane visar i sin dokumentation.
Tyvärr har bara våra utvecklare hittills vetat hur dessa skript fungerar och varför denna oändliga hög med nycklar behövs, och när något gick sönder igen fick de "underbara kvällar" för att analysera loggar.
År 2017
I år lärde vi oss att det finns något sådant som fastlane. Det fanns inte så mycket information som det finns nu - hur man startar en, hur man använder den. Och själva verktyget var fortfarande grovt på den tiden: ständiga fel gjorde oss bara besvikna och det var svårt att tro på den magiska automatisering som de lovade.
De viktigaste verktygen som ingår i fastlane-kärnan är dock gym и pilot, vi lyckades starta den.
De har förbättrats, om så bara för att inte alla parametrar som behövs för xcodebuildmåste du ange - gym kommer självständigt att förstå var och vad som ligger. Och för mer finjustering kan du ange samma nycklar som i xcodebuild, bara namnet på nycklarna är tydligare.
Den här gången, tack vare gym och den inbyggda xcpretty-formateraren, har byggloggarna blivit mycket mer läsbara. Detta började spara tid på att fixa trasiga sammansättningar, och ibland kunde releaseteamet ta reda på det på egen hand.
Tyvärr, monteringshastighetsmätningar xcodebuild и gym Vi gjorde det inte, men vi litar på dokumentationen - upp till 30 % snabbare.
En enda process för alla applikationer
År 2018 och nu
År 2018 flyttade processen med att bygga och rulla ut applikationer helt till Jenkins, utvecklare slutade släppa från sina maskiner och bara releaseteamet hade rätt att släppa.
Vi ville redan förbättra lanseringen av tester och statisk analys, och våra skript växte och växte. Växte och förändrades tillsammans med våra applikationer. Vid den tiden fanns det cirka 10 applikationer. Med tanke på att vi har två plattformar, är det cirka 20 "levande" skript.
Varje gång vi ville lägga till ett nytt steg i skriptet var vi tvungna att kopiera och klistra in bitarna i alla skalskript. Vi kanske kunde ha arbetat mer noggrant, men ofta slutade sådana ändringar i stavfel, som blev kvällar för releaseteamet för att fixa skript och ta reda på vilken smart kille som lagt till det här kommandot och vad det faktiskt gör. Generellt kan det inte sägas att skripten för montering för en plattform åtminstone var något liknande. Även om de säkert gjorde samma sak.
För att starta en process för en ny applikation var det nödvändigt att spendera en dag för att välja en "färsk" version av dessa skript, felsöka den och säga att "ja, det fungerar."
Sommaren 2018 tittade vi återigen mot den fortfarande utvecklade fastlanen.
Uppgift #1: sammanfatta alla skriptsteg och skriv om dem i Fastfile
När vi började såg våra manus ut som en fotduk som bestod av alla steg och kryckor i ett skalmanus i Jenkins. Vi har ännu inte gått över till pipeline och division för steg.
Vi tittade på vad vi har och identifierade 4 steg som passar beskrivningen av vår CI/CD:
bygga - installera beroenden, sätta ihop arkivet,
test — köra tester för utvecklarenhet, beräkna täckning,
ekolod - startar alla linters och skickar rapporter till SonarQube,
deploy — skickar en artefakt till alpha (TestFlight).
Och om du inte går in på detaljer och utelämnar nycklarna som används i åtgärder, får du denna snabbfil:
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
Faktum är att vår första Fastfile visade sig vara monstruös, med tanke på några av de kryckor som vi fortfarande behövde och antalet parametrar som vi bytte ut:
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 exemplet ovan är det bara en del av parametrarna som vi behöver specificera: dessa är byggparametrarna - schema, konfiguration, tilldelningsprofilnamn, såväl som distributionsparametrar - Apple-ID för utvecklarkontot, lösenord, applikations-ID och så på. Som en första uppskattning lägger vi alla dessa nycklar i specialfiler - Gymfile, Matchfile и Appfile.
Nu i Jenkins kan du anropa korta kommandon som inte suddar vyn och som är lätta att läsa för ögat:
Vad fick du? Tydliga kommandon för varje steg. Rensade skript, snyggt ordnade i fastlane-filer. Glada sprang vi till utvecklarna och bad dem lägga till allt de behövde till sina förråd.
Men vi insåg med tiden att vi skulle stöta på samma svårigheter - vi skulle fortfarande ha 20 monteringsskript som på ett eller annat sätt skulle börja leva sina egna liv, det skulle bli svårare att redigera dem, eftersom skripten skulle flytta till arkiv, och vi hade inte tillgång dit. Och i allmänhet kommer det inte att vara möjligt att lösa vår smärta på detta sätt.
Uppgift #2: skaffa en enda Fastfile för N applikationer
Nu verkar det som att det inte är så svårt att lösa problemet - ställ in variablerna och låt oss gå. Ja, faktiskt, det var så problemet löstes. Men för tillfället när vi skruvade ihop det hade vi varken expertis i själva fastlane, eller i Ruby, som fastlane står i, eller användbara exempel på nätverket - alla som skrev om fastlane då var begränsade till ett exempel för en applikation för en utvecklare.
Fastlane kan hantera miljövariabler, och vi har redan provat detta genom att ställa in lösenordet för nyckelring:
ENV['KEYCHAIN_PASSWORD']
Efter att ha tittat på våra skript identifierade vi de vanliga delarna:
#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, för att börja använda dessa nycklar i fastlane-filer, var vi tvungna att ta reda på hur vi skulle leverera dem där. Fastlane har en lösning för detta: ladda variabler via dotenv. Dokumentationen säger att om det är viktigt för dig att ladda nycklar för olika ändamål, skapa flera konfigurationsfiler i fastlane-katalogen .env, .env.default, .env.development.
Och sedan bestämde vi oss för att använda det här biblioteket lite annorlunda. Låt oss inte placera fastlane-skripten och dess metainformation i utvecklarens repository, utan de unika nycklarna för denna applikation i filen .env.appName.
själva Fastfile, Appfile, Matchfile и Gymfile, gömde vi det i ett separat arkiv. En ytterligare fil med lösenordsnycklar från andra tjänster gömdes där - .env.
Du kan se ett exempel här.
På CI har samtalet inte förändrats mycket; en konfigurationsnyckel för en specifik applikation har lagts till:
Lämnade denna lösning för nu, även om Fastlane har en lösning för att ladda ner Fastfile via handlingimport_from_git, men det fungerar bara för Fastfile, men inte för andra filer. Om du vill ha "riktigt vacker", kan du skriva din egen action.
En liknande uppsättning gjordes för Android-applikationer och ReactNative, filerna finns i samma arkiv, men i olika grenar iOS, android и react_native.
När releaseteamet vill lägga till något nytt steg, registreras ändringar i skriptet via MR i git, det finns inte längre något behov av att leta efter de skyldiga till trasiga skript, och generellt sett måste du nu försöka bryta det.
Nu är det det säkert
Tidigare ägnade vi tid åt att underhålla alla skript, uppdatera dem och fixa alla konsekvenser av uppdateringar. Det var en stor besvikelse när orsakerna till fel och stillestånd i releaser var enkla stavfel som var så svåra att hålla reda på i virrvarret av skalskript. Nu är sådana fel reducerade till ett minimum. Ändringar rullas ut till alla applikationer på en gång. Och det tar 15 minuter att lägga in en ny applikation i processen - skapa en mallpipeline på CI och lägg till nycklarna till utvecklarens arkiv.
Det verkar som att poängen med Fastfile för Android och applikationssignatur förblir oförklarad; om artikeln är intressant kommer jag att skriva en fortsättning. Jag kommer gärna se dina frågor eller förslag "hur skulle du lösa det här problemet" i kommentarerna eller på Telegram bashkirova.