ProHoster > Blog > administracja > Mobilne środowisko CICD: jeden standard Fastlane dla wielu aplikacji mobilnych
Mobilne środowisko CICD: jeden standard Fastlane dla wielu aplikacji mobilnych
Chciałbym porozmawiać o ciągłej integracji i dostarczaniu aplikacji mobilnych za pomocą Fastlane. Jak wdrażamy CI/CD we wszystkich aplikacjach mobilnych, jak do tego dotarliśmy i co ostatecznie się wydarzyło.
W sieci jest już wystarczająco dużo materiału na temat narzędzia, którego tak bardzo nam brakowało na początku, dlatego celowo nie będę szczegółowo opisywał narzędzia, a jedynie odniosę się do tego, co wtedy mieliśmy:
Rozwiązanie techniczne umożliwiające wdrażanie CI/CD dla aplikacji typu N
Pierwsza część to bardziej nostalgia za dawnymi czasami, a druga to doświadczenie, które możesz zastosować do siebie.
Tak to się działo historycznie
2015 rok
Dopiero zaczęliśmy tworzyć aplikacje mobilne, wtedy nie wiedzieliśmy nic o ciągłej integracji, DevOps i innych modnych rzeczach. Każda aktualizacja aplikacji była wdrażana przez samego programistę ze jego komputera. A jeśli dla Androida jest to dość proste - zmontowane, podpisane .apk i przesłałem go do Google Developer Console, następnie w przypadku iOS ówczesne narzędzie do dystrybucji za pośrednictwem Xcode pozostawiło nam wspaniałe wieczory - próby pobrania archiwum często kończyły się błędami i musieliśmy spróbować ponownie. Okazało się, że najbardziej zaawansowany programista nie pisze kodu kilka razy w miesiącu, tylko wydaje aplikację.
2016 rok
Dorastaliśmy, myśleliśmy już o tym, jak zwolnić programistów z całego dnia na wydanie, pojawiła się też druga aplikacja, co tylko popchnęło nas bardziej w stronę automatyzacji. W tym samym roku po raz pierwszy zainstalowaliśmy Jenkinsa i napisaliśmy kilka przerażających skryptów, bardzo podobnych do tych, które Fastlane pokazuje w swojej dokumentacji.
Niestety, do tej pory tylko nasi programiści wiedzieli, jak działają te skrypty i do czego potrzebny jest ten niekończący się stos kluczy, a gdy znów coś się zepsuło, mieli „cudowne wieczory” na analizowanie logów.
2017 rok
W tym roku dowiedzieliśmy się, że istnieje coś takiego jak fastlane. Nie było tak wielu informacji jak teraz – jak zacząć, jak to wykorzystać. A samo narzędzie było wówczas jeszcze prymitywne: ciągłe błędy tylko nas rozczarowały i trudno było uwierzyć w magiczną automatyzację, którą obiecywały.
Jednakże głównymi narzędziami zawartymi w rdzeniu Fastlane są gym и pilot, udało nam się to rozpocząć.
Zostały ulepszone choćby dlatego, że nie wszystkie parametry potrzebne xcodebuild, musisz wskazać - gym samodzielnie zrozumie, gdzie i co leży. Aby uzyskać dokładniejsze dostrojenie, możesz określić te same klawisze, co w xcodebuild, tylko nazewnictwo klawiszy jest jaśniejsze.
Tym razem, dzięki Gym i wbudowanemu formaterowi xcpretty, logi kompilacji stały się znacznie bardziej czytelne. Zaczęło to oszczędzać czas na naprawie uszkodzonych zespołów i czasami zespół wydający mógł rozwiązać ten problem samodzielnie.
Niestety pomiary szybkości montażu xcodebuild и gym Nie zrobiliśmy tego, ale zaufamy dokumentacji - przyspieszenie do 30%.
Jeden proces dla wszystkich zastosowań
Rok 2018 i obecnie
Do 2018 roku proces tworzenia i wdrażania aplikacji został całkowicie przeniesiony na Jenkins, programiści przestali wypuszczać aplikacje ze swoich maszyn i tylko zespół wydający miał prawo do wydawania aplikacji.
Chcieliśmy już usprawnić uruchamianie testów i analiz statycznych, a nasze skrypty rosły i rosły. Rośnie i zmienia się wraz z naszymi aplikacjami. Aplikacji było wówczas około 10. Biorąc pod uwagę, że mamy dwie platformy, to około 20 „żywych” skryptów.
Za każdym razem, gdy chcieliśmy dodać nowy krok do skryptu, musieliśmy skopiować i wkleić fragmenty do wszystkich skryptów powłoki. Być może moglibyśmy pracować ostrożniej, ale często takie zmiany kończyły się literówkami, co zamieniało się w wieczory, w których zespół ds. wydania zajmował się poprawianiem skryptów i dowiadywaniem się, który mądry facet dodał to polecenie i co faktycznie robi. Generalnie nie można powiedzieć, że skrypty do asemblera dla jednej platformy były choć trochę podobne. Chociaż z pewnością zrobili to samo.
Aby rozpocząć proces tworzenia nowej aplikacji, trzeba było poświęcić jeden dzień na wybranie „świeżej” wersji tych skryptów, zdebugowanie jej i stwierdzenie „tak, to działa”.
Latem 2018 roku ponownie spojrzeliśmy w stronę wciąż rozwijającego się fastlane’u.
Zadanie nr 1: podsumuj wszystkie kroki skryptu i przepisz je w Fastfile
Kiedy zaczynaliśmy, nasze skrypty wyglądały jak obrus składający się ze wszystkich stopni i kul w jednym skrypcie skorupowym w Jenkins. Nie przeszliśmy jeszcze na rurociąg i podział etapowy.
Przyjrzeliśmy się temu, co mamy i zidentyfikowaliśmy 4 kroki, które pasują do opisu naszego CI/CD:
test — uruchamianie testów jednostkowych dewelopera, obliczanie pokrycia,
sonar - uruchamia wszystkie lintery i wysyła raporty do SonarQube,
wdrożyć — wysłanie artefaktu do wersji alfa (TestFlight).
A jeśli nie wdasz się w szczegóły, pomijając klawisze używane w akcjach, otrzymasz ten 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
W rzeczywistości nasz pierwszy Fastfile okazał się potworny, biorąc pod uwagę niektóre podpory, których wciąż potrzebowaliśmy i liczbę parametrów, które zastąpiliśmy:
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
W powyższym przykładzie tylko część parametrów, które musimy określić: są to parametry kompilacji - schemat, konfiguracja, nazwy profili prowizyjnych, a także parametry dystrybucji - Apple ID konta programisty, hasło, identyfikator aplikacji i tak dalej NA. W pierwszym przybliżeniu umieścimy wszystkie te klucze w specjalnych plikach - Gymfile, Matchfile и Appfile.
Teraz w Jenkinsie możesz wywoływać krótkie polecenia, które nie zamazują widoku i są czytelne dla oka:
Co dostałeś? Jasne polecenia dla każdego kroku. Oczyszczone skrypty, starannie ułożone w plikach Fastlane. Radując się, pobiegliśmy do programistów, prosząc ich, aby dodali wszystko, czego potrzebują do swoich repozytoriów.
Ale z czasem zdaliśmy sobie sprawę, że napotkamy te same trudności - nadal mielibyśmy 20 skryptów asemblerowych, które tak czy inaczej zaczęłyby żyć własnym życiem, trudniej byłoby je edytować, ponieważ skrypty przeniosłyby się do repozytoriów, i nie mieliśmy tam dostępu. I ogólnie rzecz biorąc, nie będzie możliwe rozwiązanie naszego bólu w ten sposób.
Zadanie nr 2: zdobądź pojedynczy plik Fastfile dla N aplikacji
Teraz wydaje się, że rozwiązanie problemu nie jest takie trudne - ustaw zmienne i jedziemy. Tak, faktycznie, w ten sposób problem został rozwiązany. Ale w momencie, gdy to schrzaniliśmy, nie mieliśmy ani wiedzy o samym fastlane, ani o Ruby, w którym napisany jest fastlane, ani przydatnych przykładów w sieci - każdy, kto pisał wtedy o fastlane, ograniczał się wówczas do przykładu dla jednej aplikacji dla jednego dewelopera.
Fastlane może obsługiwać zmienne środowiskowe i już tego próbowaliśmy, ustawiając hasło pęku kluczy:
ENV['KEYCHAIN_PASSWORD']
Po przejrzeniu naszych skryptów zidentyfikowaliśmy wspólne części:
#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
Teraz, aby zacząć używać tych kluczy w plikach Fastlane, musieliśmy wymyślić, jak je tam dostarczyć. Fastlane ma na to rozwiązanie: ładowanie zmiennych poprzez dotenv. Dokumentacja mówi, że jeśli ważne jest, aby załadować klucze do różnych celów, utwórz kilka plików konfiguracyjnych w katalogu Fastlane .env, .env.default, .env.development.
A potem postanowiliśmy wykorzystać tę bibliotekę nieco inaczej. Umieśćmy w repozytorium programistów nie skrypty Fastlane i ich metainformacje, ale unikalne klucze tej aplikacji w pliku .env.appName.
Sami Fastfile, Appfile, Matchfile и Gymfile, ukryliśmy go w osobnym repozytorium. Ukryto tam dodatkowy plik z kluczami haseł z innych serwisów - .env.
Możesz zobaczyć przykład tutaj.
Na CI wywołanie nie uległo większym zmianom, dodano klucz konfiguracyjny dla konkretnej aplikacji:
Na razie porzuciłem to rozwiązanie, chociaż Fastlane ma rozwiązanie do pobierania Fastfile przez akcjaimport_from_git, ale działa tylko w przypadku Fastfile, ale nie w przypadku innych plików. Jeśli chcesz „naprawdę piękne”, możesz napisać własne action.
Podobny zestaw został wykonany dla aplikacji Android i ReactNative, pliki znajdują się w tym samym repozytorium, ale w różnych gałęziach iOS, android и react_native.
Kiedy zespół wydawniczy chce dodać jakiś nowy krok, zmiany w skrypcie są rejestrowane poprzez MR w git, nie ma już potrzeby szukania winowajców zepsutych skryptów i w ogóle teraz trzeba próbować to złamać.
Teraz to już na pewno
Wcześniej spędzaliśmy czas na utrzymywaniu wszystkich skryptów, aktualizowaniu ich i naprawianiu wszystkich konsekwencji aktualizacji. Było to bardzo rozczarowujące, gdy przyczyną błędów i przestojów w wydaniach były zwykłe literówki, które tak trudno było wyśledzić w gąszczu skryptów powłoki. Teraz tego typu błędy zostały zredukowane do minimum. Zmiany są wdrażane we wszystkich aplikacjach jednocześnie. A włączenie nowej aplikacji do procesu zajmuje 15 minut — skonfiguruj potok szablonów w CI i dodaj klucze do repozytorium programisty.
Wygląda na to, że kwestia Fastfile dla Androida i sygnatury aplikacji pozostaje niewyjaśniona, jeśli artykuł będzie ciekawy, napiszę kontynuację. Z przyjemnością zobaczę Twoje pytania lub sugestie „Jak rozwiązać ten problem” w komentarzach lub na Telegramie baszkirowa.