Funktionen für die Zusammenstellung und Bereitstellung von iOS-Anwendungen

In diesem Artikel berichtet Maxim Shestakov, DevOps-Ingenieur im Plarium Krasnodar-Studio, über seine Erfahrungen beim Erstellen und Bereitstellen von iOS-Anwendungen für Benutzer, die sich während des CI / CD-Debuggens angesammelt haben.



Ausbildung


Jeder, der mit der Entwicklung von Anwendungen für Apple-Geräte verbunden ist, hat es bereits geschafft, die umstrittene Benutzerfreundlichkeit der Infrastruktur zu würdigen. Es gibt überall Schwierigkeiten: vom Entwicklerprofilmenü bis zu den Debugging- und Assembly-Tools.

Es gibt viele Artikel zu den Grundlagen im Internet, daher werden wir versuchen, die Hauptsache hervorzuheben. Folgendes benötigen Sie, um die Anwendung erfolgreich zu erstellen:

  • Entwicklerkonto ;
  • MacOS-basiertes Gerät, das als Build-Server fungiert;
  • das generierte Entwicklerzertifikat , das dann zum Signieren der Anwendung verwendet wird;
  • erstellte Anwendung mit einer eindeutigen ID (die Bedeutung der Bundle- ID sollte beachtet werden, da die Verwendung der Platzhalter-ID die Verwendung vieler Funktionen der Anwendung unmöglich macht, z. B. zugeordnete Domänen, Push-Benachrichtigungen, Apple-Anmeldung und andere);
  • Anwendungssignatur Profil .

Das Entwicklerzertifikat sollte über den Schlüsselbund auf jedem MacOS-Gerät generiert werden. Die Art des Zertifikats ist sehr wichtig. Abhängig von der Anwendungsumgebung (Entwicklung, Qualitätssicherung, Bereitstellung, Produktion) unterscheiden sich diese (Entwicklung oder Verteilung) sowie die Art des Anwendungssignaturprofils.

Die Haupttypen von Profilen:

  • Entwicklung - Entwickelt, um die Anwendung des Entwicklungsteams mithilfe des Entwicklungszertifikats zu signieren (Name des Formulars iPhone Entwickler: XXXXX)
  • Ad-hoc - zum Signieren einer Testanwendung und zur internen Überprüfung durch die QS-Abteilung unter Verwendung des Distributionszertifikats des Entwicklers (Name des iPhone-Distributionstyps: XXXXX);
  • App Store - Release-Build für externe Tests über TestFlight und Hochladen in den App Store unter Verwendung des Distributionszertifikats des Entwicklers.

Beim Generieren von Entwicklungs- und Ad-hoc-Profilen wird auch eine Liste der Geräte angezeigt , auf denen Sie den Build installieren können, sodass Sie den Zugriff für Benutzer weiter einschränken können. Das App Store-Profil enthält keine Liste der Geräte, da TestFlight für die Zugriffskontrolle während der Closed Beta-Tests verantwortlich ist, die später erläutert werden.

Aus Gründen der Übersichtlichkeit können Sie das Entwicklerprofil unten in Form eines Tablets darstellen. Es ist einfacher zu verstehen, welche Parameter für die Baugruppe wir benötigen und wo sie erhältlich sind.



Versammlung


Um die Trennung von Assemblys nach Projekt und Umgebung zu vereinfachen, verwenden wir die Namen der Profile der Ansicht ${ProjectName}_${Instance}, dh den Namen des Projekts + der Instanz (abhängig von der Anwendungsumgebung: Dev, QA, GD, Staging, Live usw.).

Beim Importieren auf einen Build-Server ändert das Profil seinen Namen in eine eindeutige ID und wird in den Ordner verschoben /Users/$Username/Library/MobileDevice/Provisioning Profiles(in $Usernamedem er dem Namen des Build-Server-Benutzerkontos entspricht).

Es gibt zwei Möglichkeiten, die * .ipa-Datei zu erstellen - veraltet (PackageApplication) und modern (durch Erstellen von XcAchive und Exportieren). Die erste Methode gilt als veraltet, da ab Version 8.3 das App-Dateiverpackungsmodul aus der Xcode-Distribution entfernt wurde. Um es zu verwenden, müssen Sie das Modul vom alten Xcode (Version 8.2 und früher) in den Ordner kopieren:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/

Führen Sie dann den folgenden Befehl aus:

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

Als nächstes müssen Sie die * .app-Datei der Anwendung sammeln:

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

Wobei:

-workspace- Pfad zur Projektdatei.

-scheme- verwendete Schaltung im Projekt angegeben.

-derivedDataPath- Der Pfad zum Entladen der zusammengestellten Anwendung (* .app).

CODE_SIGN_IDENTITY- Der Name des Entwicklerkontos, das in Keychain überprüft werden kann (iPhone-Entwickler: XXXX XXXXXXX, ohne TeamID in Klammern).



PROVISIONING_PROFILE- Die Profil-ID zum Signieren der Anwendung, die mit dem folgenden Befehl abgerufen werden kann:

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

Wenn die Anwendung ein zusätzliches Profil verwendet (z. B. für Push-Benachrichtigungen), geben Sie stattdessen PROVISIONING_PROFILEFolgendes an:

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

Als nächstes sollte die resultierende * .app-Datei in * .ipa gepackt werden. Dazu können Sie einen Befehl des Formulars verwenden:

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

Diese Methode wird jedoch aus Sicht von Apple als veraltet angesehen. Es ist wichtig, * .ipa durch Exportieren aus dem Anwendungsarchiv zu erhalten.

Zuerst müssen Sie das Archiv mit dem folgenden Befehl sammeln:

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

Die Unterschiede liegen in der Assemblierungsmethode und der Option SYNCHRONOUS_SYMBOL_PROCESSING, die das Entladen von Zeichen während der Assemblierung deaktiviert.

Als nächstes müssen wir eine Datei mit Exporteinstellungen generieren:

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

Wobei:

$Method- die Übermittlungsmethode dem Typ des Anwendungssignaturprofils entspricht, dh für die Entwicklung ist der Wert die Entwicklung, für Ad-hoc - Ad-hoc und für den App Store - App-Store.

$BundleID- Die Anwendungs-ID, die in den Anwendungseinstellungen angegeben ist. Sie können mit dem Befehl überprüfen:

defaults read $ProjectDir/Info CFBundleIdentifier

$DevAccName $ProfileId- Einstellungen für den Entwicklernamen und die Signaturprofil-ID, die zuvor verwendet wurden und mit den Werten in den Exporteinstellungen übereinstimmen müssen.

$TeamID- zehnstellige ID in Klammern nach dem Namen des Entwicklers, Beispiel: iPhone-Entwickler: ....... (XXXXXXXXXX); kann in Schlüsselbund einchecken.

Als nächstes erhalten wir mit dem Exportbefehl die erforderliche * .ipa-Datei:

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

Lieferung


Jetzt muss die zusammengestellte Datei an den Endbenutzer geliefert werden, dh auf dem Gerät installiert.

Für die Verteilung von Entwicklungs- und Ad-hoc-Builds gibt es viele Dienste wie HockeyApp, AppBlade und andere. In diesem Artikel wird jedoch auf einen eigenständigen Server für die Verteilung von Anwendungen eingegangen.

Die Installation der Anwendung für iOS erfolgt in zwei Schritten:

  1. Abrufen des Anwendungsinstallationsmanifests über den Elementdienst.
  2. Installieren der * .ipa-Datei gemäß den im Manifest angegebenen Informationen über HTTPS.

Daher müssen wir zunächst das Installationsmanifest (Dateityp * .plist) mit dem folgenden Befehl generieren:

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

Wie Sie sehen können, enthält das Manifest fast alle Parameter, die an der Zusammenstellung der Anwendung beteiligt sind.

Die Anwendungsversion ( $AppVersion) kann mit dem folgenden Befehl überprüft werden:

defaults read $ProjectDir/Info CFBundleVersion

Der Parameter $ipaUrlenthält einen direkten Link zum Herunterladen der * .ipa-Datei. Ab der siebten Version von iOS muss die Anwendung über HTTPS installiert werden. In der achten Version hat sich das Manifestformat geringfügig geändert: Blöcke mit Einstellungen für Anwendungssymbole des Formulars wurden entfernt

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

Um die Anwendung zu installieren, reicht eine einfache HTML-Seite mit einem Link des Formulars aus:

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

Für die Anforderungen der Entwicklungs- und Testabteilungen hat Plarium eine Build-Installationsanwendung erstellt, die uns Folgendes bietet:

  • Autonomie und Unabhängigkeit,
  • Zentralisierte Zugriffskontrolle und sichere Installation von Anwendungen über "temporäre", dynamisch erstellte Links,
  • erweiterbare Funktionalität (dh das Entwicklungsteam kann bei Bedarf die fehlenden Funktionen in eine vorhandene Anwendung integrieren).

Testen


Jetzt werden wir über das Testen von Anwendungen vor der Veröffentlichung mit TestFlight sprechen .

Voraussetzungen für das Herunterladen sind der Signaturprofiltyp des App Store und das Vorhandensein generierter API-Schlüssel.

Es gibt verschiedene Möglichkeiten, die Anwendung herunterzuladen:

  • über Xcode (Organizer),
  • durch altool,
  • über Application Loader für ältere Versionen von Xcode (jetzt Transporter).

Zum automatischen Laden wird altool verwendet, das auch zwei Autorisierungsmethoden hat:

  • App-spezifisches Passwort,
  • API-Schlüssel

Es ist vorzuziehen, die Anwendung mit dem API-Schlüssel herunterzuladen.

Um den API-Schlüssel zu erhalten, folgen Sie dem Link und generieren Sie den Schlüssel. Zusätzlich zum Schlüssel selbst im * .p8-Format benötigen wir zwei Parameter: IssuerID und KeyID.



Als nächstes importieren wir den heruntergeladenen Schlüssel auf den Build-Server:

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

Bevor Sie die Anwendung in TestFlight laden, müssen Sie die Anwendung validieren. Führen Sie dazu den folgenden Befehl aus:

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

Wo apiKeyund apiIssuerhaben Feldwerte von der Seite zur API-Schlüsselgenerierung.

Nach erfolgreicher Validierung laden wir die Anwendung mit einem Befehl --upload-appmit denselben Parametern.

Die Anwendung wird innerhalb von ein bis zwei Tagen von Apple getestet und steht danach externen Testern zur Verfügung: Sie erhalten E-Mail-Links zur Installation.

Eine andere Möglichkeit, die Anwendung über altool herunterzuladen, besteht darin, das app-spezifische Kennwort zu verwenden.

Um das App-spezifische Passwort zu erhalten, müssen Sie dem Link folgen und es im Abschnitt Sicherheit generieren.



Erstellen Sie als Nächstes einen Build-Server-Datensatz in Keychain mit diesem Kennwort. Ab Version 11 von Xcode kann dies mit dem folgenden Befehl erfolgen:

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

Wobei:

$DeveloperNameder Name des iOS-Entwicklerkontos ist, mit dem Sie sich bei Apple-Diensten anmelden.

$AppPswd- generiertes app-spezifisches Passwort.

Als Nächstes erhalten wir den Wert des Parameters asc-provider und überprüfen den Erfolg des Imports des Kennworts mit dem folgenden Befehl:

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

Wir kommen zu dem Schluss:

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

Wie Sie sehen können, stimmt der gewünschte Wert für Short Name (ASC-Provider) mit dem Parameter $ TeamID überein, den wir beim Erstellen der Anwendung verwendet haben.

Verwenden Sie den folgenden Befehl, um die Anwendung in TestFlight zu validieren und zu laden:

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

Als Parameterwert -pkönnen Sie den Wert $AppPswdin unverschlüsselter (expliziter) Form annehmen .

Wie bereits erwähnt, ist es aus Sicht der Bedienbarkeit besser, den API-Schlüssel für das Autorisierungs-Altool auszuwählen, da in verschiedenen Xcode-Versionen verschiedene Probleme auftreten (Schlüsselbund, Autorisierungsfehler beim Entladen usw. werden nicht angezeigt).

Das ist in der Tat alles. Ich wünsche allen Beteiligten erfolgreiche Builds und problemlose Releases im App Store.

All Articles