Guía

Bajar la factura de macOS en GitHub Actions, paso a paso

Casi todas las facturas de macOS en GitHub Actions se inflan con minutos que no aportan nada al equipo. Reconstruir cachés. Ejecutar matrices que nadie mira. Terminar jobs de commits que ya se han sustituido. Esta es una lista de cambios ordenados por lo que ahorran frente al trabajo que cuestan, con el YAML donde ayuda.

1. Cancela las ejecuciones que ya están obsoletas

Cuando alguien hace dos pushes en un minuto, la primera ejecución se desperdicia. Un bloque por workflow lo evita:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

2. Saca de macOS todo lo que no sea un build

El lint, las comprobaciones de formato, las notas de versión y los avisos de Slack funcionan en un runner de Linux a una décima parte del precio. Igual que los tests unitarios de paquetes Swift compartidos que no tocan UIKit. Divide el workflow en un job de Linux y un job de macOS que dependa de él. Así un fallo de lint nunca gasta un minuto de macOS.

3. Guarda en caché las rutas que de verdad cuestan tiempo

En los runners alojados, cada job empieza vacío. Restaura las carpetas caras con una clave ligada a tus lockfiles:

- uses: actions/cache@v4
  with:
    path: |
      ~/Library/Developer/Xcode/DerivedData
      ~/Library/Caches/org.swift.swiftpm
      ~/.cocoapods
      Pods
    key: ${{ runner.os }}-${{ hashFiles('**/Package.resolved', '**/Podfile.lock') }}

DerivedData es la más grande y la más delicada. Si los builds incrementales se comportan de forma rara, sácala de la caché y quédate con las cachés de paquetes.

4. Ejecuta la matriz completa solo en main

Una pull request rara vez necesita cinco simuladores. Compila una configuración en las pull requests y la matriz completa de dispositivos en los merges a main o en una ejecución nocturna.

5. Filtra por rutas

Un cambio en el README no debería lanzar un build de iOS. Usa paths-ignore en el disparador del workflow para la documentación, los scripts y todo lo que quede fuera del target de la app.

6. Pon timeouts

Un simulador colgado puede cobrarte las seis horas del límite por defecto. Pon timeout-minutes en cada job de macOS, un poco por encima de tu tiempo de build normal.

7. Deja de reinstalar herramientas

Instalar CocoaPods, fastlane o una versión concreta de Xcode en cada job quema minutos antes de que empiece el build. Quédate con lo que ya trae la imagen alojada, o guarda la instalación en caché.

8. Reduce la retención de artifacts

Los archivos y los paquetes de tests guardados 90 días suman cargos de almacenamiento que van creciendo. Siete días bastan para todo lo que no se publica en la tienda.

9. Por encima del punto de equilibrio, deja de pagar por minuto

Todo lo anterior recorta la factura. Pero si estás siempre por encima de unos 2,242 minutos de macOS al mes, ningún recorte supera un precio fijo. Un M6 dedicado a $139 al mes ejecuta minutos ilimitados con cachés en caliente. Los puntos 3 y 7 dejan de importar por completo. La calculadora muestra dónde está tu equipo.

Preguntas frecuentes

¿Cuál es el mayor ahorro en una factura de macOS de GitHub Actions?

+

Para la mayoría de los equipos, cancelar las ejecuciones obsoletas con un grupo de concurrency y pasar a Linux el trabajo que no es build. Juntos suelen quitar un tercio de los minutos de macOS cobrados con dos pequeños cambios en el YAML.

¿Vale la pena guardar DerivedData en caché en GitHub Actions?

+

A menudo sí, pero es la delicada. Las cachés de paquetes (SwiftPM, CocoaPods) son seguras y ahorran minutos en cada job. DerivedData ahorra más, pero puede causar fallos raros en builds incrementales. Usa una clave muy ajustada y prepárate para quitarla.

¿Debo ejecutar mi matriz de dispositivos en cada pull request?

+

Normalmente no. Una configuración en las pull requests y la matriz completa en main o por la noche detectan las mismas regresiones con una fracción de los minutos.

¿Cuándo deja de importar todo esto?

+

Por encima de unos 2,242 minutos de macOS al mes, un Mac dedicado a $139 fijos sale más barato que pagar por uso. Eso se cumple por muy optimizada que esté la configuración por uso. Las cachés en caliente eliminan por sí solas la mayor parte del desperdicio.

Guías relacionadas