Características del ensamblaje y entrega de aplicaciones iOS

En este artículo, Maxim Shestakov, ingeniero de DevOps en el estudio Plarium Krasnodar, comparte su experiencia en la creación y entrega de aplicaciones iOS a los usuarios que se acumularon durante la depuración de CI / CD.



Formación


Todos los que están conectados con el desarrollo de aplicaciones para dispositivos Apple ya han logrado apreciar la polémica usabilidad de la infraestructura. Las dificultades están en todas partes: desde el menú del perfil del desarrollador hasta las herramientas de depuración y ensamblaje.

Hay muchos artículos sobre los conceptos básicos en la red, por lo que trataremos de resaltar lo principal. Esto es lo que necesita para construir con éxito la aplicación:

  • Cuenta de desarrollador ;
  • dispositivo basado en macOS que actúa como un servidor de compilación;
  • el certificado de desarrollador generado , que luego se usará para firmar la aplicación;
  • aplicación creada con una ID única (se debe tener en cuenta la importancia del Identificador de paquete, porque el uso de la ID comodín hace que sea imposible usar muchas funciones de la aplicación, por ejemplo: Dominios asociados, Notificaciones push, Inicio de sesión de Apple y otros);
  • perfil de firma de la aplicación.

El certificado de desarrollador debe generarse a través de Keychain en cualquier dispositivo macOS. El tipo de certificado es muy importante. Dependiendo del entorno de la aplicación (Dev, QA, Puesta en escena, Producción), diferirá (Desarrollo o Distribución), así como el tipo de perfil de firma de la aplicación.

Los principales tipos de perfiles:

  • Desarrollo: diseñado para firmar la solicitud del equipo de desarrollo, utilizando el certificado de desarrollo (nombre del formulario iPhone Developer: XXXXX);
  • Ad Hoc: destinado a firmar una solicitud de prueba y verificación interna por parte del departamento de control de calidad, utilizando el certificado de distribución del desarrollador (nombre del tipo de distribución de iPhone: XXXXX);
  • App Store: lanzamiento de la compilación para pruebas externas a través de TestFlight y carga en la App Store, utilizando el certificado de distribución del desarrollador.

Al generar perfiles de desarrollo y ad hoc, también se indica una lista de dispositivos en los que puede instalar la compilación, lo que le permite restringir aún más el acceso de los usuarios. El perfil de la App Store no tiene una lista de dispositivos, ya que TestFlight es responsable del control de acceso durante las pruebas beta cerradas, que se discutirán más adelante.

Para mayor claridad, puede presentar el perfil del desarrollador en la forma de una tableta a continuación. Es más fácil entender qué parámetros para el ensamblaje necesitamos y dónde obtenerlos.



Montaje


Para facilitar la separación de ensamblajes por proyecto y entorno, utilizamos los nombres de los perfiles de la vista ${ProjectName}_${Instance}, es decir, el nombre del proyecto + instancia (depende del entorno de la aplicación: Dev, QA, GD, Staging, Live, etc.).

Al importar a un servidor de compilación, el perfil cambia su nombre a un ID único y se mueve a la carpeta /Users/$Username/Library/MobileDevice/Provisioning Profiles(donde $Usernamecorresponde al nombre de la cuenta de usuario del servidor de compilación).

Hay dos formas de compilar el archivo * .ipa: obsoleto (PackageApplication) y moderno (mediante la creación de XcAchive y la exportación). El primer método se considera obsoleto, ya que desde la versión 8.3 el módulo de empaquetado del archivo de la aplicación se ha eliminado de la distribución Xcode. Para usarlo, debe copiar el módulo del antiguo Xcode (versión 8.2 y anterior) a la carpeta:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/

y luego ejecutar el comando:

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

A continuación, debe recopilar el archivo * .app de la aplicación:

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

Donde:

-workspace- ruta al archivo del proyecto.

-scheme- circuito utilizado especificado en el proyecto.

-derivedDataPath- la ruta para descargar la aplicación ensamblada (* .app).

CODE_SIGN_IDENTITY- el nombre de la cuenta de desarrollador que se puede verificar en Keychain (Desarrollador de iPhone: XXXX XXXXXXX, sin TeamID entre paréntesis).



PROVISIONING_PROFILE- El ID de perfil para firmar la aplicación, que se puede obtener con el comando:

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

Si la aplicación usa un perfil adicional (por ejemplo, para notificaciones push), entonces PROVISIONING_PROFILEindique:

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

A continuación, el archivo * .app resultante debe empaquetarse en * .ipa. Para hacer esto, puede usar un comando del formulario:

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

Sin embargo, este método se considera obsoleto desde el punto de vista de Apple. Es relevante obtener * .ipa exportando desde el archivo de la aplicación.

Primero debe recopilar el archivo con el comando:

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

Las diferencias están en el método de ensamblaje y la opción SYNCHRONOUS_SYMBOL_PROCESSINGque desactiva la descarga de caracteres durante el ensamblaje.

A continuación, necesitamos generar un archivo con la configuración de exportación:

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

Donde:

$Method- el método de entrega corresponde al tipo de perfil de firma de la aplicación, es decir, para Desarrollo, el valor será desarrollo, para Ad Hoc - ad-hoc y para App Store - app-store.

$BundleID- El ID de la aplicación que se especifica en la configuración de la aplicación. Puedes consultar con el comando:

defaults read $ProjectDir/Info CFBundleIdentifier

$DevAccName $ProfileId- configuraciones para el nombre del desarrollador y la identificación del perfil de firma que se usaron anteriormente y deben coincidir con los valores en la configuración de exportación.

$TeamID- ID de diez dígitos entre paréntesis después del nombre del desarrollador, por ejemplo: iPhone Developer: ....... (XXXXXXXXXX); puede verificar en llavero.

Luego, usando el comando de exportación, obtenemos el archivo * .ipa necesario:

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

Entrega


Ahora el archivo ensamblado debe ser entregado al usuario final, es decir, instalado en el dispositivo.

Para la distribución de las versiones de Desarrollo y Ad Hoc, hay muchos servicios como HockeyApp, AppBlade y otros, pero en este artículo hablaremos sobre un servidor independiente para distribuir aplicaciones.

La instalación de la aplicación para iOS se realiza en 2 etapas:

  1. Obtención del manifiesto de instalación de la aplicación a través del Servicio de elementos.
  2. Instalar el archivo * .ipa de acuerdo con la información especificada en el manifiesto a través de HTTPS.

Por lo tanto, para empezar, necesitamos generar el manifiesto de instalación (tipo de archivo * .plist) con el comando:

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

Como puede ver, el manifiesto contiene casi todos los parámetros involucrados en el ensamblaje de la aplicación.

La versión de la aplicación ( $AppVersion) se puede verificar con el comando:

defaults read $ProjectDir/Info CFBundleVersion

El parámetro $ipaUrlcontiene un enlace directo para descargar el archivo * .ipa. Desde la séptima versión de iOS, la aplicación debe instalarse a través de HTTPS. En la octava versión, el formato del manifiesto ha cambiado ligeramente: se han eliminado los bloques con configuraciones para los iconos de aplicaciones del formulario

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

Por lo tanto, para instalar la aplicación, una simple página html con un enlace del formulario es suficiente:

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

Para las necesidades de los departamentos de desarrollo y pruebas, Plarium ha creado su aplicación de instalación de compilación, que nos brinda:

  • autonomía e independencia,
  • control de acceso centralizado e instalación segura de aplicaciones a través de enlaces "temporales", creados dinámicamente,
  • funcionalidad extensible (es decir, el equipo de desarrollo, si es necesario, puede integrar las funciones que faltan en una aplicación existente).

Pruebas


Ahora hablaremos sobre las pruebas de aplicaciones previas al lanzamiento con TestFlight .

Los requisitos previos para la descarga son el tipo de perfil de firma de App Store y la presencia de claves API generadas.

Hay varias formas de descargar la aplicación:

  • a través de Xcode (Organizador),
  • a través del altool,
  • a través de Application Loader para versiones anteriores de Xcode (ahora Transporter).

Para la carga automática, se usa altool, que también tiene dos métodos de autorización:

  • Contraseña específica de la aplicación,
  • Clave API

Es preferible descargar la aplicación utilizando la clave API.

Para obtener la clave API, siga el enlace y genere la clave. Además de la clave en formato * .p8, necesitaremos dos parámetros: IssuerID y KeyID.



A continuación, importamos la clave descargada al servidor de compilación:

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

Antes de cargar la aplicación en TestFlight, debe validar la aplicación, haga esto con el comando:

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

Dónde apiKeyy apiIssuertener valores de campo de la página de generación de claves API.

Luego, después de una validación exitosa, cargamos la aplicación con un comando --upload-appcon los mismos parámetros.

La aplicación será probada por Apple dentro de uno o dos días y luego estará disponible para probadores externos: se les enviarán enlaces de correo electrónico para su instalación.

Otra forma de descargar la aplicación a través de altool es usar la contraseña específica de la aplicación.

Para obtener la contraseña específica de la aplicación, debe seguir el enlace y generarla en la sección Seguridad.



A continuación, cree un registro de servidor de compilación en Keychain con esta contraseña. Desde la versión 11 de Xcode, esto se puede hacer con el comando:

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

Donde:

$DeveloperNamees el nombre de la cuenta de desarrollador de iOS utilizada para iniciar sesión en los servicios de Apple.

$AppPswd- Contraseña específica de la aplicación generada.

A continuación, obtenemos el valor del parámetro asc-provider y verificamos el éxito de importar la contraseña con el comando:

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

Obtenemos la conclusión:

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

Como puede ver, el valor deseado de Nombre corto (asc-provider) coincide con el parámetro $ TeamID que usamos al compilar la aplicación.

Para validar y cargar la aplicación en TestFlight, use el comando:

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

Como valor de parámetro, -ppuede tomar el valor $AppPswden forma no cifrada (explícita).

Sin embargo, como ya se mencionó, desde el punto de vista de la operabilidad, es mejor seleccionar la clave API para la autorización de altool, ya que en diferentes versiones de Xcode se encuentran ciertos problemas (no "ve" el llavero, errores de autorización durante la descarga, etc.).

Eso, de hecho, es todo. Deseo que todos participen en compilaciones exitosas y lanzamientos sin problemas en la App Store.

All Articles