Desde Xojo 2024r4 el IDE permite aplicar el Sandboxing, Hardened Runtime y notarizar automáticamente las apps macOS. ¿No sería genial completar el paso final y ser capaz de enviar el bundle creado directamente a la AppStore Connect? Continúa leyendo y te mostraré como hacerlo.
Por supuesto existen excelentes herramientas creadas con Xojo que facilitan este proceso, como por ejemplo AppWrapper de Ohanaware; pero si eres el tipo de persona que le gusta saber “cómo funcionan las cosas bajo el capó” entonces puedes seguir los siguientes pasos para hacerlo manualmente desde la línea de comandos (o bien convertir las siguientes instrucciones en los correspondientes scripts de Xojo que se ejecuten como parte de la compilación desde el IDE).
Ciertamente, existen algunos requerimientos para que todo esto pueda funcionar, pero estoy seguro de que ya los has cumplido en el caso de que hayas leído mi anterior artículo sobre cómo aplicar Sandboxing, Hardened Runtime y Notarización a tus apps macOS. Quizá el requerimiento más importante sea el de contar con una membresía de pago en el Programa de Desarrolladores de Apple (lo que supone un coste aproximado de 90 euros anuales).
Por ejemplo, es preciso que Xcode esté instalado en tu Mac dado que necesitaremos utilizar las herramientas altool y productbuild desde la línea de comandos, y estas se incluyen con Xcode. De igual modo es preciso crear una contraseña específica para la aplicación altool, pero puedes ahorrarte este paso en el caso de que ya la hubieses creado para usar la herramienta notarytool empleada en el mencionado artículo sobre Sandboxing, Hardened Runtime y Notarización.
De igual modo, mientras que a la hora de distribuir tus apps macOS desde tu sitio web estas han de firmarse utilizando el certificado “Apple Development”, cuando se trata de compilar tus apps para que se distribuyan en la Mac AppStore, tendrás que firmarlas utilizando el certificado “Apple Distribution”; de modo que tendrás que asegurarte de utilizar dicho valor en el campo macOS > Signing > Developer ID en el IDE de Xojo.
Igualmente importante, para que podamos subir la app a la AppStore Connect tendremos que crear un archivo de paquete a partir del bundle de la app, y dicho archivo de paquete (con la extensión .pkg) ha de firmarse utilizando el certificado “3rd Party Mac Developer Installer”. Por tanto, asegúrate de que tengas este certificado instalado también en el llavero de tu Mac.
Primero… lo primero
Pero antes de que puedas subir tu archivo .pkg al sitio web de la AppStore Connect, hay algunas cosas que debes de tener en cuenta primero, y que son requeridas por Apple para cualquier app que se vaya a distribuir a través de la Mac AppStore.
Lo primero consiste en registrar un App ID (o Identificado, Identifier en inglés) en el Apple Developer Portal. Cuando estés en ello, asegúrate de crear un Identificador explícito en vez de uno de tipo comodín (wildcard, en inglés). También importante, asegúrate de que dicho identificador (en la forma de un DNS inverso) es el mismo que vayas a utilizar o estés utilizando ya en el campo macOS > Build > Bundle Identifier de tu proyecto Xojo. Si no se corresponden, entonces puedes esperar algunos problemas durante el proceso.
Lo segundo consiste en crear un nuevo registro para la aplicación propiamente dicha en el sitio web de la AppStore Connect. Aquí es donde tendrás que proporcionar toda la información requerida por Apple, principalmente en dos áreas: toda la información que será visible en el registro de la aplicación cuando el usuario la consulte en la AppStore (tal como descripción, imágenes, precio, etc.), y la solicitada de forma interna por parte de Apple para el proceso de revisión. En fin, asegúrate de crear el registro para tu app macOS y de rellenar toda la información solicitada.
Una vez hayas completado estos pasos ya podrás centrarte en la línea de comandos para crear el archivo .pkg y subirlo manualmente (o bien utilizando opcionalmente la app Transporter para ello).
Canta, canta, canta… ¡la canción de re-firmar!
Cuando se compila una app macOS desde el IDE de Xojo este se encargará de firmarla correctamente basándose en los ajustes seleccionados en la sección Build Settings > Sign. Pero dado que Apple requiere que algunas entradas del archivo Info.Plist estén formateadas de una forma concreta (especialmente los valores asociados a las claves CFBundleShortVersionString y CFBundleVersion), y el hecho de que también se requiere la presencia de la clave LSApplicationCategoryType junto a cualquiera de los valores correspondientes a la categoría de producto, esto significa que hemos de editar manualmente el archivo Info.Plist generado para la aplicación compilada.
Sí, claro que podemos crear un archivo de texto adicional con el nombre Info.Plist que contenga las claves y valores esperados/apropiados junto con sus valores y arrastrarlo sobre el navegador del IDE para nuestro proyecto de forma que dicha información sea añadida o modificada, como por ejemplo este:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleShortVersionString</key> <string>1.0.0</string> <key>CFBundleVersion</key> <string>1.0.0</string> <key>LSApplicationCategoryType</key> <string>public.app-category.business</string> </dict> </plist>
La mala noticia es que el valor correspondiente a la clave CFBundleVersion permanecerá inalterado.
¿Cuál es la desventaja de tener que editar manualmente el archivo Info.Plist en la app ya compilada? Bueno, tan pronto como realices cualquier cambio y lo guardes a disco… se invalidará la firma del bundle. Pero no te asustes… ya sabemos como volver a firmar el bundle, ¿verdad? (si no, te sugiero que leas primero el ya mencionado artículo sobre cómo aplicar Sandboxing, Hardened Runtime y Notarización a las apps macOS).
Por tanto, adelante, selecciona tu app compilada en el Finder, haz clic sobre su icono y selecciona la opción “Mostrar Contenidos” en el menú contextual. Esta acción te mostrará los “archivos internos” del bundle que compone tu app macOS. Dentro de la carpeta Contents podrás ver el archivo Info.Plist. Haz clic sobre su icono y selecciona la opción que te permita abrirlo y editarlo con tu editor de textos favorito (personalmente utilizo BBEdit de BareBones Software).
- Ubica la clave CFBundleVersion y cambia su valor de cadena de forma que no tenga más de tres números separados por puntos (tal y como se muestra en el anterior archivo Plist de ejemplo).
- Ubica la clave CFBundleShortVersionString y cambia su valor de cadena para que tenga tres números separados entre sí por un punto.
Por supuesto, y para los valores de ambas claves, asegúrate de que dichos valores de versión se correspondan con la versión de tu App (en el ejemplo he utilizado 1.0.0 como el valor de versión típico para el lanzamiento inicial de cualquier app).
- A continuación, añade la clave requerida LSApplicationCategoryType con el valor que mejor encaje en la categoría de producto para tu app de entre las disponibles en la Documentación de Apple (en el anterior ejemplo de archivo Plist he utilizado la correspondiente a la categoría Business):
<key>LSApplicationCategoryType</key> <string>public.app-category.business</string>
- Guarda los cambios del archivo Info.Plist modificado. Ahora es el momento de volver a firmar el bundle.
¿Y qué pasa con los Entitlements de la app?
¡Hey… espera! Dado que tenemos que volver a firmar de nuevo el bundle de la app… ¡también necesitaremos volver a asociar los entitlements esperados y/o requeridos para su funcionamiento! Esto significa que por lo menos hemos de añadir un entitlement requerido-y-muy-importante: ¡activar el Sandboxing! (esto es necesario para cualquier app enviada para su distribución en la Mac AppStore).
Si bien Xojo 2024r4+ se encarga de añadir esta información automáticamente por nosotros, ahora tendremos que hacerlo manualmente. Esto significa crear nuestro propio archivo .entitlements que se utilizará durante el re-firmado de la app. Por ejemplo, para una app típica (y realmente simple), sólo tendría que activarse la capacidad que permita al usuario abrir y guardar archivos:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.files.user-selected.read-write</key> <true/> </dict> </plist>
Guarda este archivo con el nombre “myEntitlements.entitlements” en el disco de tu Mac. Por supuesto, en el caso de que tu app requiera de más entitlements o capacidades, siéntete libre de añadirlo sobre la anterior plantilla.
Bien, ahora mismo tenemos nuestro archivo .Plist modificado y el archivo .entitlements requerido… de modo que ya contamos con todo lo necesario para volver a firmar el bundle de la app nuevamente.
Abre una ventana del Terminal y escribe el siguiente comando:
codesign --force --timestamp --entitlements path-to-your-myEntitlements.entitlements-file -s "Apple Distribution: whatever-name-you-use (BZXXXXXXX)" path-to-the-bundle-of-the-compiled-app.app
Observa como estamos haciendo referencia al archivo de entitlements y que también estamos usando el certificado “Apple Distribution” en vez del correspondiente a “Apple Development”.
Paquetes Acme
Todo bien hasta ahora. Tenemos el bundle de nuestra app firmado de nuevo, de modo que ya podemos crear el archivo .pkg a partir de él. Todo lo que necesitas es escribir el siguiente comando desde una ventana del Terminal:
productbuild --sign "3rd Party Mac Developer Installer: whatever-name-you-use (BZXXXXXXX)" --component path-to-the-bundle-of-the-compiled-app.app /Applications path-to-the-generated-package-file.pkg
Como puedes ver, en este caso estamos utilizando el certificado “3rd Party Mac Developer Installer” para firmar el paquete creado.
¡Hora de subirlo!
Con el paquete creado ya tenemos todos lo necesario para subirlo al sitio web de la AppStore Connect. En este punto puedes tomar dos caminos. El primero consiste en utilizar la app Transporter que puedes descargar desde la Mac AppStore propiamente dicha (en el caso de que no lo tuvieses ya instalado). En este caso:
- Abre la app Transporter.
- Haz clic sobre el icono “+”. Dicha acción mostrará un diálogo en el que puedes seleccionar el archivo “.pkg” creado en el paso anterior.
- Una vez que se haya añadido, Transporter hará algunas comprobaciones iniciales sobre los contenidos del paquete. Si todo va bien, deberías de ver algo similar a esto:
Lo interesante de utilizar Transporter es que podrás seleccionar la opción “Verify” desde el menú contextual asociado (el que tiene un icono de tres puntos suspensivos). Dicha acción realizará comprobaciones más en profundidad de modo que puedas obtener información sobre cualquier problema detectado y puedas corregirlos antes de que la app se envíe a la AppStore Connect. Por ejemplo, intencionado para el propósito de este artículo:
La segunda opción cosiste en utilizar la herramienta de la línea de comandos altool, mencionada anteriormente, para subir manualmente el paquete al sitio web de la AppStore Connect. Si te decides por esta ruta, todo lo que necesitas es escribir el siguiente comando en una ventana del Terminal:
xcrun altool --upload-package path-to-the-package-file.pkg -u your-apple-developer-login-id-goes-here -p "your-app-specific-password-goes-here" --type osx -apple-id "6111111111" --bundle-id "com.yourcomany.yourIdentifier" --bundle-short-version-string "1.0.0" --bundle-version "1.0.0"
Algunas consideraciones sobre las opciones y valores proporcionados en dicho comando:
- -u: Este es el identificador de logado que utilizas cuando accedes al Portal de Desarrolladores de Apple.
- -p: Esta es la contraseña específica de la aplicación que tendrás que crear siguiendo los pasos proporcionados en el blog mencionado sobre Sandboxing (o bien utilizar la que ya hubieses creado).
- -apple-id: Este es el valor numérico que puedes encontrar en la sección General > App Information en el registro de tu app creado en appstoreconnect.apple.com:
Dicha información también se puede obtener utilizando:
xcrun altool --list-apps -u your-apple-developer-login-id-goes-here -p "your-app-specific-password-goes-here" --output-format json
- –bundle-id: Asegúrate de proporcionar el mismo valor que el empleado cuando creaste el Identificador para la app y, por tanto, el mismo utilizado en el campo Build Settings > macOS > Build > Build Identifier de tu proyecto Xojo.
- –bundle-short-version-string: Asegúrate de que sea el mismo valor utilizado en la clave CFBundleShortVersionString del archivo .Plist.
- –bundle-version: Asegúrate de utilizar el mismo valor que el empleado para la clave CFBundleVersion en el archivo .Plist.
Una vez que se haya ejecutado el comando, tu archivo de paquete se subirá a la AppStore Connect y, una vez completado, estará disponible como nueva Build que puedas añadir al registro de tu app para el proceso de revisión y aprobación por parte del equipo de Apple.
Conclusión
Como has podido ver, son varios los detalles que debes de considerar… pero una vez que te acostumbres a ellos se simplifica el proceso a la hora de cubrir “la última milla” para que tu app compilada se envíe para su revisión en el sitio Web de la AppStore Connect.