Reduciendo tiempos de compilación en proyectos iOS

Una de las primeras cosas que recomiendo e intento hacer cuando empezamos un desarrollo es configurar las builds de integración y despliegue continuos desde el minuto 0. Hay que tener en cuenta que tiempo que tarda en ejecutarse una build es, cómo decirlo, oro.

Y es que tras configurar una github action para un proyecto de iOS me sorprendió la cantidad de tiempo que tardaba en ejecutarse… Casi 30 minutos. Así que tocaba “arremangarse” y buscar cómo optimizarlo.

Da igual si lo haces con githubactions, Jenkins, Teamcity, Azure Devops, etcc … Hay que hacer dos cosas:

Cachear el contenido de “derivedData”

Busca la forma de cachear ese directorio, de lo contrario, en cada build que se ejecute se descargará y compilará todas las referencias que tengas en tu proyecto.

Aquí os pongo cómo puedes hacerlo si usas githubactions:

- uses: actions/cache@v2.1.7
  name: "Cache: Expensive Dependencies "        
  with:
    path: |
      ./DerivedData/Build
      ./DerivedData/SourcePackages            
    key: ${{ runner.os }}-expensive-dependencies-${{ hashFiles('**/Podfile.lock','**/Package.resolved') }}
    restore-keys: |
       ${{ runner.os }}-expensive-dependencies-

Estamos cacheando ese directorio, que en mi caso está en la raíz del proyecto porque cuando ejecuto el comando xcodebuild, le indico que use ese directorio como derivedDataPath. Esto se consigue añadiendo al comando xcodebuild el parámetro “-derivedDataPath ./DerivedData”, o el directorio que quieras. Si no se lo indicas, el directorio derived data se encuentra en /Library/Developer/Xcode/DerivedData/”miproyecto”

Os recomiendo que sólo cacheéis los directorios de Build y SourcePackages, ya que son los que contienen el código y el resultado de las compilaciones de las dependencias. El resto es para cache de símbolos logs, resultados de tests.. que si los incluís en la cache se va a estar invalidando en cada build y la volverá a guardar… y eso aunque no es mucho, es tiempo… y el tiempo es…

Prestad especial atención también a cómo se generan las claves para la cache, estamos aprovechando el hash del archio podfile.lock para generar una nueva entrada en la cache cuando se añada un nuevo paquete.

Añadir un parámetro a xcodebuild.

El segundo punto importante y que no se nos debe olvidar es pasarle al comando xcodebuild el parámetro:

-IgnoreFileSystemDeviceInodeChanges=YES”

Con este parámetro le estamos diciendo a xcode que desactive una opción interna que hace que el Swift Package Manager invalide lo que haya en DerivedData porque se está ejecutando en una máquina diferente… o algo así he entendido de esto https://stackoverflow.com/questions/53753511/is-it-possible-to-copy-an-xcode-derived-data-cache/54055857#54055857 

También está la otra opción que se describe en el post de stackoverflow:

defaults write com.apple.dt.XCBuild IgnoreFileSystemDeviceInodeChanges -bool YES

Pero esto último no lo he probado. Así que si queréis probarlo genial, así no hay que pasarlo al comando xCodebuild.

 

Espero que os sirva.

Azure Devops, Xcode y el error IPA processing failed

Seguramente por mi «L» de desarrollador iOS he estado un día entero investigando porqué después de añadir los paquetes de Firebase Crashlytics y FirebaseAnalytics, la pipeline que genera el IPA empezó a fallar. Compilaba el paquete, hacia el Archive, pero cuando hacía el export, termina dando el error Error Domain=IDEFoundationErrorDomain Code=1 «IPA processing failed» UserInfo={NSLocalizedDescription=IPA processing failed}

Despues de un día intentando reproducirlo en local y viendo que todo funcionaba perfectamente me dí cuenta que la versión del sdk iphoneos que tiene instalada la máquina de azure era la 14.4. y yo en local lo tengo todo a la última….

Jugando a detective colombo, pensé «¿y si no le gusta que halla añadido la referencia a traves del package manager?» … pues por probar y ya que no se me ocurría nada más, instalé las dependencias como paquetes POD … y ALELUYA!!!

Por fin me genera el ipa como $Deity manda

 

Espero que le sirva a alguien que como yo aún va con la L

 

Aprendiendo Swift TDDando

Bueno, ¡cuánto ha llovido desde el último post!

Sólo quería dejar aquí presente algo que he estado haciendo y es aprender ha desarrollar aplicaciones nativas en iOS con Swift. Y para eso aquí tenéis un repo donde voy metiendo cositas de vez en cuando: https://github.com/juanlao/BenfordsLaw

El objetivo de este repositorio es aprender plataformas nuevas e ir descubriendo los intríngulis de cada una de ellas con TDD (Test Drive Development) que tengo la sensación de que no va a ser un mal camino para aprender  los entresijos de un nuevo lenguaje/plataforma. Y además seguro que aprendo cosas nuevas sobre cómo hacer tests unitarios 🙂

Espero que os sirva