ProHoster > блог > адміністраванне > Вопыт мабільнага CICD: адзін стандарт fastlane на шмат мабільных прыкладанняў
Вопыт мабільнага CICD: адзін стандарт fastlane на шмат мабільных прыкладанняў
Я б хацела пагаварыць аб бесперапыннай інтэграцыі і дастаўцы для мабільных прыкладанняў з дапамогай fastlane. Як мы ўкараняем CI/CD на ўсе мабільныя прыкладанні, як мы да гэтага ішлі і што атрымалася ў выніку.
У сетцы ўжо дастаткова матэрыялу па інструменце, якога так не хапала нам на старце, таму я наўмысна не буду падрабязна апісваць інструмент, а толькі спашлюся на тое, што было ў нас тады:
Перадгісторыя з'яўлення мабільнага CI/CD у кампаніі
Тэхнічнае рашэнне раскочвання CI/CD на N-прыкладанняў
Першая частка - больш настальгія па былых часах, а другая ж - вопыт, які можна прымяніць у сябе.
Так гістарычна склалася
Год 2015
Мы толькі пачалі займацца распрацоўкай мабільных дадаткаў, тады яшчэ мы нічога не ведалі пра бесперапынную інтэграцыю, пра DevOps і іншыя модныя штукі. Кожнае абнаўленне прыкладання выкочваў сам распрацоўшчык са сваёй машыны. І калі для Android гэта дастаткова проста — сабраў, падпісаў .apk і закінуў у Google Developer Console, то для iOS тагачасны інструмент дыстрыбуцыі праз Xcode пакідаў нам шыкоўныя вечары – спробы загрузіць архіў часта заканчваліся памылкамі і даводзілася спрабаваць яшчэ раз. Атрымлівалася, што самы прапампаваны распрацоўшчык некалькі разоў у месяц не піша код, а займаецца рэлізам прыкладання.
Год 2016
Мы падраслі, за плячыма ўжо былі думкі аб тым, як вызваліць распрацоўшчыкаў ад цэлага дня для рэлізу, а гэтак жа з'явілася другое прыкладанне, што толькі мацней нас падштурхоўвала да аўтаматызацыі. У той жа год мы ўпершыню паставілі Jenkins і напісалі кучку страшненькіх скрыптоў, вельмі падобных да тых, што паказвае fastlane у сваёй дакументацыі.
Нажаль, аб тым як гэтыя скрыпты працуюць і для чаго патрэбны гэты бясконцы пачак ключоў дагэтуль ведалі толькі нашы распрацоўнікі, а калі нешта ў чарговы раз ламалася, "шыкоўныя вечары" для разбораў логаў ім жа і даставаліся.
Год 2017
У гэтым годзе мы даведаліся, што ёсць такая штука як fastlane. Было не так шмат інфармацыі, як цяпер - як завесці, як выкарыстоўваць. Ды і сам інструмент быў тады яшчэ сыраваты: пастаянныя памылкі, толькі расчароўвалі нас і ў чароўную аўтаматызацыю, якую яны абяцалі, верылася з цяжкасцю.
Аднак асноўныя ўтыліты, якія ўваходзяць у ядро fastlane, - gym и pilot, у нас атрымалася завесці.
Акультурыліся хаця б таму, што не ўсе параметры, неабходныя для xcodebuild, трэба паказваць gym самастойна зразумее дзе і што ляжыць. А для больш тонкай наладкі можна паказаць тыя ж самыя ключы, што і ў xcodebuild, толькі нэймінг ключоў больш зразумела.
На гэты раз, дзякуючы gym і ўбудаванаму фарматар xcpretty, логі зборкі сталі нашмат пераборлівей. Гэта стала эканоміць час на папраўку зламанай зборкі, а часам у гэтым магла самастойна разабрацца рэліз-каманда.
Нажаль, замераў па хуткасці зборкі xcodebuild и gym мы не зрабілі, але будзем верыць дакументацыі - да 30% паскарэння.
Адзіны працэс на ўсе прыкладанні
Год 2018 і цяперашні час
Да 2018 году сам працэс зборкі і выкаткі прыкладанняў цалкам пераехаў на Jenkins, распрацоўнікі перасталі рэлізаваць са сваіх машын, права на рэліз мела толькі рэліз-каманда.
Нам ужо захацелася дакруціць запуск тэстаў і статычны аналіз, а нашыя скрыпты раслі і раслі. Раслі і мяняліся разам з нашымі праграмамі. На той момант прыкладанняў было каля 10. Улічваючы, што платформы ў нас дзве – гэта каля 20 "якія жывуць" скрыптоў.
Кожны раз, калі мы жадалі дадаць новы крок у скрыпт, прыходзілася капіпасціць кавалачкі ва ўсе shell-скрыпты. Магчыма, можна было працаваць і акуратней, але часта такія змены заканчваліся памылкамі друку, якія ўжо ператвараліся ў вечары рэліз-каманды на папраўку скрыптоў і высвятленні, хто з разумнікаў дадаў гэтую каманду і што яна наогул робіць. У цэлым нельга сказаць што скрыпты для зборкі пад адну платформу былі хоць колькі-небудзь падобнымі. Хаця безумоўна рабілі адно і тое ж.
Для таго каб завесці працэс для новага прыкладання - трэба было выдаткаваць дзень, каб падабраць "свежую" версію з гэтых скрыптоў, адладзіць і сказаць што "так, працуе".
Улетку 2018 мы яшчэ раз паглядзелі ў бок усё яшчэ развіваецца fastlane.
Задача №1: абагульніць усе крокі скрыптоў і перапісаць іх у Fastfile
Калі мы пачыналі, нашы скрыпты выглядалі анучай з усіх крокаў і мыліц у адным shell-скрыпце ў Jenkins. Мы яшчэ не перайшлі на pipeline і дзяленне па stage.
Паглядзелі на тое, што ёсць і вылучылі 4 кроку, падыходных пад апісанне нашага CI/CD:
build - усталёўка залежнасцяў, зборка архіва,
test - запуск unit-тэстаў распрацоўніка, падлік пакрыцця,
sonar - запуск усіх лінтэраў і адпраўка справаздач у SonarQube,
deploy - адпраўка артэфакта ў альфу (TestFlight).
І калі не ўдавацца ў падрабязнасці, апусціць выкарыстоўваныя ключы ў actions, атрымаецца вось такі 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
Насамрэч, першы Fastfile у нас атрымаўся монструозным, улічваючы некаторыя мыліцы, якія нам усё яшчэ былі патрэбныя, і колькасць параметраў, якія мы падстаўлялі:
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
На прыкладзе вышэй, толькі частка параметраў, якія нам трэба паказаць: гэта параметры зборкі - схема, канфігурацыя, назвы Provision Profile, а таксама параметры дыстрыбуцыі - Apple ID акаўнта распрацоўніка, пароль, ідэнтыфікатар прыкладання і гэтак далей. У першым набліжэнні мы паклалі ўсе гэтыя ключы ў спецыяльныя файлы. Gymfile, Matchfile и Appfile.
Зараз у Jenkins можна выклікаць кароткія каманды, якія не "замыльваюць" погляд і добра счытваюцца вокам:
Што атрымалі? Зразумелыя каманды для кожнага кроку. Прычасаныя скрыпты, акуратна раскладзеныя ў файлы fastlane. Узрадаваўшыся, мы было пабеглі да распрацоўшчыкаў з просьбай дадаць усё што трэба ў свае рэпазітары.
Але своечасова ўсвядомілі, што сутыкнемся з тымі ж складанасцямі - у нас усё яшчэ будзе 20 скрыптоў зборкі, якія так ці інакш пачнуць жыць сваім жыццём, правіць іх будзе складаней, бо скрыпты пераедуць у рэпазітары, а ў нас доступу туды няма. І, увогуле, вырашыць наш боль такім чынам не атрымаецца.
Задача №2: атрымаць адзіны Fastfile для N-прыкладанняў
Цяпер ужо здаецца, што вырашыць задачу не так ужо і складана - задайце зменныя, і паехалі. Так, уласна, так задачу і вырашылі. Але ў той момант, калі мы гэта ўкручвалі, у нас не было ні экспертызы ў самім fastlane, ні ў Ruby, на якім напісаны fastlane, ні карысных прыкладаў у сетцы — кожны, хто пісаў пра fastlane тады, абмяжоўваўся прыкладам для аднаго дадатку для аднаго распрацоўшчыка.
Fastlane умее ў зменныя асяроддзі, і гэта мы ўжо паспрабавалі, задаўшы пароль ад Keychain:
ENV['KEYCHAIN_PASSWORD']
Паглядзеўшы на нашыя скрыпты, мы вылучылі агульныя часткі:
#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
Цяпер для таго, каб пачаць выкарыстоўваць гэтыя ключы ў файлах fastlane'а, трэба было прыдумаць як іх туды дастаўляць. У Fastlane ёсць для гэтага рашэнне: загрузка зменных праз dotenv. У дакументацыі сказана, калі вам важна падгружаць ключы для розных мэт, напладзіце ў дырэкторыі fastlane некалькі канфігурацыйных файлаў .env, .env.default, .env.development.
І тады мы вырашылі выкарыстоўваць гэтую бібліятэку крыху па-іншаму. Змесцім у рэпазітары распрацоўнікаў не скрыпты fastlane і яго мэта інфармацыю, а ўнікальныя ключы гэтага прыкладання ў файле .env.appName.
Самі Fastfile, Appfile, Matchfile и Gymfile, мы схавалі ў асобны рэпазітар. Туды ж схавалі дадатковы файл з ключамі-паролямі ад іншых сэрвісаў. .env.
Прыклад, можна паглядзець тут.
На CI выклік не моцна памяняўся, дадаўся ключ канфігурацыі канкрэтнага дадатку:
Пакуль пакінулі гэтае рашэнне, хоць у Fastlane ёсць рашэнне для загрузкі Fastfile праз дзеяннеimport_from_git, але ён працуе толькі для Fastfile, для астатніх жа файлаў - не. Калі хочацца "прам зусім прыгожа", можна напісаць свой action.
Аналагічны набор зрабілі для Android прыкладанняў і ReactNative, файлы ляжаць у адным рэпазітары, але ў розных галінках iOS, android и react_native.
Калі рэліз каманда жадае дадаць які-небудзь новы крок, змены ў скрыпце фіксуюцца праз MR у git, больш не трэба шукаць вінаватых паламаных скрыптоў, ды і ў цэлым - зламаць зараз, гэта трэба паспрабаваць.
Цяпер сапраўды ўсё
Раней мы марнавалі час на падтрымку ўсіх скрыптоў, іх абнаўленне і папраўку ўсіх наступстваў абнаўленняў. Было вельмі крыўдна, калі чыннікі памылак і прастояў рэлізаў былі простымі памылкамі друку, за якімі так складана ўсачыць у мяшаніне shell-скрыпту. Цяпер жа такія памылкі зведзены да мінімуму. Змены накатваюцца адразу на ўсе прыкладанні. А новае прыкладанне завесці ў працэс каштуе 15 хвілін - наладзіць шаблонны pipeline на CI і дадаць ключы ў рэпазітар распрацоўніка.
Здаецца, застаўся неасветленым пункт з Fastfile для Android і подпіс прыкладанняў, калі артыкул будзе цікавая, напішу працяг. Буду рада вашым пытанням або прапановам "як бы вы вырашылі гэтую задачу" у каментарах або ў Telegram bashkirova.