Funkcje tworzenia i dostarczania aplikacji na iOS

W tym artykule dzielimy się doświadczeniami w zakresie asemblowania i dostarczania użytkownikom aplikacji iOS, które studio Plarium Krasnodar zgromadziło w procesie debugowania CI/CD.

Funkcje tworzenia i dostarczania aplikacji na iOS

Szkolenie

Każda osoba, która w taki czy inny sposób jest zaangażowana w rozwój aplikacji na urządzenia Apple, doceniła już kontrowersyjną wygodę infrastruktury. Trudności można znaleźć wszędzie: od menu profilu programisty po narzędzia do debugowania i budowania.

W Internecie jest mnóstwo artykułów na temat „podstaw”, dlatego postaramy się podkreślić najważniejsze. Oto, czego potrzebujesz, aby pomyślnie zbudować aplikację:

  • konto dewelopera;
  • urządzenie z systemem macOS pełniące funkcję serwera kompilacji;
  • wygenerowane certyfikat dewelopera, który będzie dalej wykorzystany do podpisania wniosku;
  • utworzona aplikacja z unikalnym ID (należy zwrócić uwagę na znaczenie Identyfikatora Pakietu, ponieważ użycie identyfikatora wieloznacznego uniemożliwia korzystanie z wielu funkcji aplikacji, np.: Powiązane Domeny, Powiadomienia Push, Apple Logowanie i inne);
  • profil podpisy aplikacji.

Certyfikat programisty musi zostać wygenerowany za pomocą pęku kluczy na dowolnym urządzeniu z systemem macOS. Rodzaj certyfikatu jest bardzo ważny. W zależności od środowiska aplikacji (Dev, QA, Staging, Production) będzie się ono różnić (Programowanie lub Dystrybucja), podobnie jak typ profilu sygnatur aplikacji.

Główne typy profili:

  • Development - przeznaczony do podpisywania aplikacji zespołu programistów, używany jest certyfikat deweloperski (nazwa typu iPhone Developer: XXXXX);
  • Ad Hoc – przeznaczony do podpisania aplikacji testowej i wewnętrznej weryfikacji przez dział QA, wykorzystywany jest certyfikat dystrybucji dewelopera (nazwa typu iPhone Distribution: XXXXX);
  • App Store - wersja kompilacji do testów zewnętrznych za pośrednictwem TestFlight i przesyłania do App Store, używany jest certyfikat dystrybucyjny dewelopera.

Jest to również wskazane przy generowaniu profili Development i Ad Hoc Lista urządzeń, na którym można zainstalować kompilację pozwalającą na dalsze ograniczenie dostępu użytkownikom. W profilu App Store nie ma listy urządzeń, gdyż kontrolą dostępu podczas zamkniętych testów beta zajmuje się TestFlight, o czym powiemy później.

Dla przejrzystości możesz przedstawić profil dewelopera w formie poniższej tabeli. Dzięki temu łatwiej zrozumieć jakie parametry potrzebujemy do montażu i skąd je wziąć.

Funkcje tworzenia i dostarczania aplikacji na iOS

montaż

Aby ułatwić oddzielanie zespołów według projektu i środowiska, używamy nazw profili, takich jak ${ProjectName}_${Instance}, czyli nazwa projektu + instancja (w zależności od środowiska aplikacji: Dev, QA, GD, Staging, Live itd.).

Po zaimportowaniu na serwer kompilacji profil zmienia nazwę na unikalny identyfikator i jest przenoszony do folderu /Users/$Username/Library/MobileDevice/Provisioning Profiles (Gdzie $Username odpowiada nazwie konta użytkownika serwera kompilacji).

Istnieją dwa sposoby budowania pliku *.ipa – starszy (PackageApplication) i nowoczesny (poprzez tworzenie i eksportowanie XcAchive). Pierwszą metodę uważa się za przestarzałą, ponieważ od wersji 8.3 moduł pakowania plików aplikacji został usunięty z dystrybucji Xcode. Aby z niego skorzystać należy skopiować moduł ze starego Xcode (wersja 8.2 i wcześniejsze) do folderu:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/

A następnie uruchom polecenie:

chmod +x /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/*

Następnie musisz zebrać plik *.app aplikacji:

xcodebuild 
-workspace $ProjectDir/$ProjectName.xcworkspace 
-scheme $SchemeName 
-sdk iphoneos 
build 
-configuration Release 
-derivedDataPath build 
CODE_SIGN_IDENTITY=”$DevAccName”
PROVISIONING_PROFILE=”$ProfileId”
DEPLOYMENT_POSTPROCESSING=YES 
SKIP_INSTALL=YES 
ENABLE_BITCODE=NO

Gdzie:

-workspace — ścieżka do pliku projektu.

-scheme — zastosowany schemat określony w projekcie.

-derivedDataPath — ścieżka do pobrania zmontowanej aplikacji (*.app).

CODE_SIGN_IDENTITY — nazwa konta programisty, które można zweryfikować w Keychain (iPhone Developer: XXXX XXXXXXX, bez TeamID w nawiasach).

Funkcje tworzenia i dostarczania aplikacji na iOS

PROVISIONING_PROFILE — Identyfikator profilu do podpisania wniosku, który można uzyskać komendą:

cd "/Users/$Username/Library/MobileDevice/Provisioning Profiles/" && find *.mobileprovision -type f | xargs grep -li ">${ProjectName}_${Instance}<" | sed -e 's/.mobileprovision//'

Jeśli aplikacja korzysta z dodatkowego profilu (na przykład dla powiadomień push), to zamiast PROVISIONING_PROFILE wskazać:

APP_PROFILE=”$AppProfile” 
EXTENSION_PROFILE=”$ExtProfile” 

Następnie powstały plik *.app należy spakować do *.ipa. Aby to zrobić, możesz użyć polecenia takiego jak:

/usr/bin/xcrun --sdk iphoneos PackageApplication 
-v $(find "$ProjectDir/build/Build/Products/Release-iphoneos" -name "*.app") 
-o "$ProjectDir/$ProjectName_$Instance.ipa"

Jednak z punktu widzenia Apple metoda ta jest uważana za przestarzałą. Istotne jest uzyskanie pliku *.ipa poprzez eksport z archiwum aplikacji.

Najpierw musisz zebrać archiwum za pomocą polecenia:

xcodebuild 
-workspace $ProjectDir/$ProjectName.xcworkspace 
-scheme $SchemeName 
-sdk iphoneos 
-configuration Release 
archive 
-archivePath $ProjectDir/build/$ProjectName.xcarchive 
CODE_SIGN_IDENTITY=”$DevAccName” 
PROVISIONING_PROFILE=”$ProfileId”
ENABLE_BITCODE=NO 
SYNCHRONOUS_SYMBOL_PROCESSING=FALSE

Różnice polegają na sposobie montażu i opcjach SYNCHRONOUS_SYMBOL_PROCESSING, co wyłącza rozładowywanie symboli w czasie kompilacji.

Następnie musimy wygenerować plik z ustawieniami eksportu:

ExportSettings="$ProjectDir/exportOptions.plist"

cat << EOF > $ExportSettings
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>compileBitcode</key>
<false/>
<key>uploadBitcode</key>
<false/>
<key>uploadSymbols</key>
<false/>
<key>method</key>
<string>$Method</string>
<key>provisioningProfiles</key>
<dict>
<key>$BundleID</key>
<string>$ProfileId</string>
</dict>
<key>signingCertificate</key>
<string>$DevAccName</string>
<key>signingStyle</key>
<string>manual</string>
<key>stripSwiftSymbols</key>
<true/>
<key>teamID</key>
<string>$TeamID</string>
<key>thinning</key>
<string><none></string>
</dict>
</plist>
EOF

Gdzie:

$Method — metoda dostawy, odpowiada typowi profilu sygnatury aplikacji, czyli dla Development wartością będzie development, dla Ad Hoc - ad-hoc, a dla App Store - app-store.

$BundleID — Identyfikator aplikacji określony w ustawieniach aplikacji. Możesz sprawdzić za pomocą polecenia:

defaults read $ProjectDir/Info CFBundleIdentifier

$DevAccName и $ProfileId — ustawienia nazwy programisty i identyfikatora profilu podpisu, które były używane wcześniej i muszą odpowiadać wartościom w ustawieniach eksportu.

$TeamID — dziesięciocyfrowy identyfikator w nawiasie po nazwie dewelopera, przykład: iPhone Developer: …… (XXXXXXXXXXXX); można sprawdzić w pęku kluczy.

Następnie za pomocą polecenia eksportu uzyskujemy niezbędny plik *.ipa:

xcodebuild 
-exportArchive 
-archivePath $ProjectDir/build/$ProjectName.xcarchive 
-exportPath $ProjectDir 
-exportOptionsPlist $ExportSettings

Dostawa

Teraz zebrany plik należy dostarczyć do użytkownika końcowego, czyli zainstalować na urządzeniu.

Istnieje wiele usług dystrybucji kompilacji programistycznych i ad hoc, takich jak HockeyApp, AppBlade i inne, ale w tym artykule porozmawiamy o samodzielnym serwerze do dystrybucji aplikacji.

Instalacja aplikacji na iOS odbywa się w 2 etapach:

  1. Otrzymanie manifestu instalacji aplikacji za pośrednictwem usługi Items.
  2. Instalacja pliku *.ipa zgodnie z informacjami zawartymi w manifeście za pośrednictwem protokołu HTTPS.

Dlatego najpierw musimy wygenerować manifest instalacji (typ pliku *.plist) za pomocą polecenia:

cat << EOF > $manifest
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>$ipaUrl</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>$BundleID</string>
<key>bundle-version</key>
<string>$AppVersion</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>$ProjectName_$Instance</string>
<key>subtitle</key>
<string>$Instance</string>
</dict>
</dict>
</array>
</dict>
</plist>
EOF

Jak widać, manifest zawiera prawie wszystkie parametry potrzebne do zbudowania aplikacji.

Wersja aplikacji ($AppVersion) można sprawdzić za pomocą polecenia:

defaults read $ProjectDir/Info CFBundleVersion

Parametr $ipaUrl zawiera bezpośredni link do pobrania pliku *.ipa. Od siódmej wersji iOS aplikacja musi być instalowana poprzez HTTPS. W ósmej wersji zmienił się nieco format manifestu: bloki z ustawieniami ikon aplikacji, np

<images>
   <image>...</image>
</images>

Zatem do zainstalowania aplikacji wystarczy prosta strona HTML z linkiem takim jak ten:

itms-services://?action=download-manifest&url=https://$ServerUrl/$ProjectName/$Instance/iOS/$AppVersion/manifest.plist

Na potrzeby działu rozwoju i testów Plarium stworzyło własną aplikację instalacyjną build, która daje nam:

  • autonomia i niezależność,
  • centralizacja kontroli dostępu i bezpieczna instalacja aplikacji poprzez „tymczasowe” dynamicznie tworzone łącza,
  • rozszerzalna funkcjonalność (tzn. zespół programistów, jeśli zajdzie taka potrzeba, może zintegrować brakujące funkcje z istniejącą aplikacją).

Testowanie

Teraz porozmawiamy o testowaniu przedpremierowym aplikacji za pomocą Lot testowy.

Wymagane warunki pobrania to rodzaj profilu podpisu App Store oraz obecność wygenerowanych kluczy API.

Istnieje kilka sposobów pobrania aplikacji:

  • poprzez Xcode (Organizator),
  • poprzez altool,
  • poprzez moduł ładujący aplikacje dla starszych wersji Xcode (obecnie Transporter).

Do automatycznego pobierania wykorzystywany jest altool, który również posiada dwie metody autoryzacji:

  • Hasło specyficzne dla aplikacji,
  • Klucz API.

Zaleca się pobieranie aplikacji przy użyciu klucza API.

Aby otrzymać klucz API przejdź do powiązanie i wygeneruj klucz. Oprócz samego klucza w formacie *.p8 będziemy potrzebować dwóch parametrów: IssuerID i KeyID.

Funkcje tworzenia i dostarczania aplikacji na iOS

Następnie zaimportuj pobrany klucz na serwer kompilacji:

mkdir -p ~/.appstoreconnect/private_keys
mv ~/Downloads/AuthKey_${KeyID}.p8 ~/.appstoreconnect/private_keys/

Przed wgraniem aplikacji do TestFlight należy dokonać walidacji aplikacji, robimy to za pomocą polecenia:

xcrun altool 
--validate-app 
-t ios 
-f $(find "$ProjectDir" -name "*.ipa") 
--apiKey “$KeyID” 
--apiIssuer “$IssuerID” 

Где apiKey и apiIssuer mają wartości pól ze strony generowania klucza API.

Następnie po pomyślnej walidacji ładujemy aplikację komendą --upload-app z tymi samymi parametrami.

Aplikacja zostanie przetestowana przez firmę Apple w ciągu jednego lub dwóch dni, a następnie zostanie udostępniona zewnętrznym testerom: otrzymają oni e-mailem linki do instalacji.

Innym sposobem pobrania aplikacji poprzez altool jest użycie hasła specyficznego dla aplikacji.

Aby uzyskać hasło specyficzne dla aplikacji, musisz przejść do powiązanie i wygeneruj go w sekcji Bezpieczeństwo.

Funkcje tworzenia i dostarczania aplikacji na iOS

Następnie powinieneś utworzyć rekord serwera kompilacji w Keychain z tym hasłem. Od wersji 11 Xcode można to zrobić za pomocą polecenia:

xcrun altool --store-password-in-keychain-item "Altool" -u "$DeveloperName" -p $AppPswd

Gdzie:

$DeveloperName — nazwa konta programisty iOS używanego do logowania się do usług Apple.

$AppPswd — wygenerowano hasło specyficzne dla aplikacji.

Następnie pobieramy wartość parametru asc-provider i sprawdzamy powodzenie importu hasła za pomocą polecenia:

xcrun altool --list-providers -u "$DeveloperName" -p "@keychain:Altool"

Otrzymujemy dane wyjściowe:

Provider listing:
- Long Name - - Short Name -
XXXXXXX        XXXXXXXXX

Jak widać wymagana wartość krótkiej nazwy (asc-provider) pokrywa się z parametrem $TeamID, którego użyliśmy podczas budowania aplikacji.

Aby sprawdzić poprawność i załadować aplikację do TestFlight, użyj polecenia:

xcrun altool 
--(validate|upload)-app   
-f $(find "$ProjectDir" -name "*.ipa") 
-u "$DeveloperName" 
-p "@keychain:Altool" 

Jako wartość parametru -p możesz przyjąć wartość $AppPswd w formie niezaszyfrowanej (jawnej).

Jednakże, jak już wspomniano, z punktu widzenia wydajności lepiej jest wybrać klucz API do autoryzacji altool, ponieważ różne wersje Xcode mają pewne problemy („nie widzi” pęku kluczy, błędy autoryzacji podczas przesyłania itp.).

Właściwie to wszystko. Życzę wszystkim zaangażowanym udanych kompilacji i bezproblemowych wydań w App Store.

Źródło: www.habr.com

Dodaj komentarz