Caractéristiques de l'assemblage et de la livraison d'applications iOS

Dans cet article, Maxim Shestakov, ingénieur DevOps au studio Plarium Krasnodar, partage son expérience dans la création et la livraison d'applications iOS aux utilisateurs qui se sont accumulées pendant le débogage CI / CD.



Entraînement


Tout le monde connecté au développement d'applications pour les appareils Apple a déjà réussi à apprécier la convivialité controversée de l'infrastructure. Les difficultés sont partout: du menu du profil développeur aux outils de débogage et d'assemblage.

Il y a beaucoup d'articles sur les bases sur le net, nous allons donc essayer de mettre en évidence l'essentiel. Voici ce dont vous avez besoin pour créer avec succès l'application:

  • Compte développeur ;
  • périphérique basé sur macOS agissant comme un serveur de génération;
  • le certificat de développeur généré , qui sera ensuite utilisé pour signer l'application;
  • application créée avec un ID unique (l'importance de l'identifiant de bundle doit être notée, car l'utilisation de l'ID générique rend impossible l'utilisation de nombreuses fonctions de l'application, par exemple: domaines associés, notifications push, connexion Apple et autres);
  • profil de signature d'application.

Le certificat de développeur doit être généré via le trousseau sur n'importe quel appareil macOS. Le type de certificat est très important. Selon l'environnement d'application (Dev, QA, Staging, Production), il sera différent (Développement ou Distribution), ainsi que le type de profil de signature d'application.

Les principaux types de profils:

  • Développement - conçu pour signer la demande de l'équipe de développement, en utilisant le certificat de développement (nom du formulaire iPhone Developer: XXXXX);
  • Ad Hoc - conçu pour la signature d'une application de test et la vérification interne par le service AQ, le certificat de distribution du développeur est utilisé (nom du type de distribution iPhone: XXXXX);
  • App Store - version de publication pour les tests externes via TestFlight et téléchargement sur l'App Store, en utilisant le certificat de distribution du développeur.

Lors de la génération de profils de développement et ad hoc, une liste des appareils sur lesquels vous pouvez installer la build est également indiquée , ce qui vous permet de restreindre davantage l'accès pour les utilisateurs. Le profil de l'App Store n'a pas de liste d'appareils, car TestFlight est responsable du contrôle d'accès pendant les tests bêta fermés, qui seront discutés plus tard.

Pour plus de clarté, vous pouvez présenter le profil de développeur sous la forme d'une tablette ci-dessous. Il est plus facile de comprendre les paramètres dont nous avons besoin pour l'assemblage et où les obtenir.



Assemblée


Pour faciliter la séparation des assemblys par projet et environnement, nous utilisons les noms des profils de vue ${ProjectName}_${Instance}, c'est-à-dire le nom du projet + l'instance (dépend de l'environnement d'application: Dev, QA, GD, Staging, Live, etc.).

Lors de l'importation sur un serveur de build, le profil change son nom en un ID unique et se déplace vers le dossier /Users/$Username/Library/MobileDevice/Provisioning Profiles(où il $Usernamecorrespond au nom du compte d'utilisateur du serveur de build).

Il existe deux façons de créer le fichier * .ipa - obsolète (PackageApplication) et moderne (en créant XcAchive et en exportant). La première méthode est considérée comme obsolète, car à partir de la version 8.3, le module d'empaquetage de fichiers d'application a été supprimé de la distribution Xcode. Pour l'utiliser, vous devez copier le module de l'ancien Xcode (version 8.2 et antérieure) dans le dossier:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/

Et puis exécutez la commande:

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

Ensuite, vous devez collecter le fichier * .app de l'application:

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

Où:

-workspace- chemin d'accès au fichier de projet.

-scheme- circuit utilisé spécifié dans le projet.

-derivedDataPath- le chemin pour décharger l'application assemblée (* .app).

CODE_SIGN_IDENTITY- le nom du compte développeur qui peut être vérifié dans le trousseau (développeur iPhone: XXXX XXXXXXX, sans TeamID entre parenthèses).



PROVISIONING_PROFILE- L'ID de profil pour signer l'application, qui peut être obtenu avec la commande:

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

Si l'application utilise un profil supplémentaire (par exemple, pour les notifications push), PROVISIONING_PROFILEindiquez à la place :

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

Ensuite, le fichier * .app résultant doit être empaqueté dans * .ipa. Pour ce faire, vous pouvez utiliser une commande du formulaire:

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

Cependant, cette méthode est considérée comme obsolète du point de vue d'Apple. Il est pertinent d'obtenir * .ipa en exportant à partir des archives de l'application.

Vous devez d'abord collecter l'archive avec la commande:

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

Les différences résident dans la méthode d'assemblage et l'option SYNCHRONOUS_SYMBOL_PROCESSINGqui désactive le déchargement des caractères pendant l'assemblage.

Ensuite, nous devons générer un fichier avec les paramètres d'exportation:

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

Où:

$Method- la méthode de livraison correspond au type de profil de signature d'application, c'est-à-dire que pour le développement, la valeur sera le développement, pour Ad Hoc - ad-hoc et pour l'App Store - app-store.

$BundleID- L'ID d'application spécifié dans les paramètres de l'application. Vous pouvez vérifier avec la commande:

defaults read $ProjectDir/Info CFBundleIdentifier

$DevAccName $ProfileId- les paramètres du nom du développeur et de l'ID du profil de signature qui ont été utilisés précédemment et doivent correspondre aux valeurs des paramètres d'exportation.

$TeamID- ID à dix chiffres entre parenthèses après le nom du développeur, exemple: iPhone Developer: ....... (XXXXXXXXXX); peut vérifier dans le trousseau.

Ensuite, en utilisant la commande d'exportation, nous obtenons le fichier * .ipa nécessaire:

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

Livraison


Le fichier assemblé doit maintenant être remis à l'utilisateur final, c'est-à-dire installé sur l'appareil.

Pour la distribution des versions de développement et ad hoc, il existe de nombreux services comme HockeyApp, AppBlade et d'autres, mais dans cet article, nous parlerons d'un serveur autonome pour la distribution d'applications.

L'installation de l'application pour iOS se déroule en 2 étapes:

  1. Obtention du manifeste d'installation de l'application via le service Items.
  2. Installation du fichier * .ipa selon les informations spécifiées dans le manifeste via HTTPS.

Ainsi, pour commencer, nous devons générer le manifeste d'installation (type de fichier * .plist) avec la commande:

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

Comme vous pouvez le voir, le manifeste contient presque tous les paramètres impliqués dans l'assemblage de l'application.

La version de l'application ( $AppVersion) peut être vérifiée avec la commande:

defaults read $ProjectDir/Info CFBundleVersion

Le paramètre $ipaUrlcontient un lien direct pour télécharger le fichier * .ipa. À partir de la septième version d'iOS, l'application doit être installée via HTTPS. Dans la huitième version, le format du manifeste a légèrement changé: les blocs avec les paramètres des icônes d'application du formulaire ont été supprimés

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

Ainsi, pour installer l'application, une simple page html avec un lien du formulaire suffit:

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

Pour les besoins des services de développement et de test, Plarium a créé son application d'installation de build, qui nous donne:

  • autonomie et indépendance,
  • contrôle d'accès centralisé et installation sécurisée des applications via des liens "temporaires", créés dynamiquement,
  • fonctionnalité extensible (c'est-à-dire que l'équipe de développement, si nécessaire, peut intégrer les fonctions manquantes dans une application existante).

Essai


Maintenant, nous allons parler des tests d'applications préliminaires à l' aide de TestFlight .

Les conditions préalables au téléchargement sont le type de profil de signature App Store et la présence de clés API générées.

Il existe plusieurs façons de télécharger l'application:

  • via Xcode (Organisateur),
  • à travers altool,
  • via Application Loader pour les anciennes versions de Xcode (maintenant Transporter).

Pour le chargement automatique, altool est utilisé, qui a également deux méthodes d'autorisation:

  • Mot de passe spécifique à l'application,
  • clé API

Il est préférable de télécharger l'application à l'aide de la clé API.

Pour obtenir la clé API, suivez le lien et générez la clé. En plus de la clé elle-même au format * .p8, nous aurons besoin de deux paramètres: IssuerID et KeyID.



Ensuite, nous importons la clé téléchargée sur le serveur de build:

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

Avant de charger l'application dans TestFlight, vous devez valider l'application, faites-le avec la commande:

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

apiKeyet apiIssueravoir des valeurs de champ à partir de la page de génération de clé API.

Ensuite, une fois la validation réussie, nous chargeons l'application avec une commande --upload-appavec les mêmes paramètres.

L'application sera testée par Apple dans un délai d'un à deux jours et sera ensuite mise à la disposition des testeurs externes: des liens e-mail leur seront envoyés pour l'installation.

Une autre façon de télécharger l'application via altool est d'utiliser le mot de passe spécifique à l'application.

Pour obtenir le mot de passe spécifique à l'application, vous devez suivre le lien et le générer dans la section Sécurité.



Ensuite, créez un enregistrement de serveur de génération dans le trousseau avec ce mot de passe. À partir de la version 11 de Xcode, cela peut être fait avec la commande:

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

Où:

$DeveloperNameest le nom du compte développeur iOS utilisé pour se connecter aux services Apple.

$AppPswd- mot de passe spécifique à l'application généré.

Ensuite, nous obtenons la valeur du paramètre asc-provider et vérifions le succès de l'importation du mot de passe avec la commande:

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

Nous obtenons la conclusion:

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

Comme vous pouvez le voir, la valeur souhaitée du nom court (fournisseur asc) correspond au paramètre $ TeamID que nous avons utilisé lors de la création de l'application.

Pour valider et charger l'application dans TestFlight, utilisez la commande:

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

En tant que valeur de paramètre, -pvous pouvez prendre la valeur $AppPswdsous forme non chiffrée (explicite).

Cependant, comme déjà mentionné, du point de vue de l'opérabilité, il est préférable de sélectionner la clé API pour l'autorisation altool, car divers problèmes sont rencontrés dans différentes versions de Xcode (il ne voit pas le trousseau, les erreurs d'autorisation lors du déchargement, etc.).

En fait, c'est tout. Je souhaite à tous ceux qui sont impliqués dans des versions réussies et des versions sans problème sur l'App Store.

All Articles