Fastlane para CI/CD en iOS: automatizar compilación, firma y envío
Fastlane convierte el ciclo de archivar, firmar y subir en lanes con nombre que tu CI puede ejecutar. Esta es la configuración que funciona: Bundler, clave de API, match y pilot.

Introducción
Fastlane automatiza los tres trabajos que más frenan un lanzamiento de iOS: compilar la app, firmarla y subirla a App Store Connect. Describes cada trabajo como un lane en un único Fastfile, y tu CI lo ejecuta siempre igual. Esta guía recorre la configuración en el orden en que la vas a necesitar. Refleja la documentación de fastlane a octubre de 2026.
Los lanzamientos manuales fallan de formas previsibles. El certificado vive en un solo portátil. La subida necesita el Apple ID de alguien. Nadie recuerda los ajustes de exportación. Un lane elimina los tres problemas. Si todavía estás dimensionando el proyecto, cuánto cuesta desarrollar una app para iOS explica dónde encaja el trabajo de lanzamiento dentro del presupuesto.
Instalar y estructurar el proyecto
Instala fastlane con Bundler. La guía de configuración de fastlane lo señala como el método preferido: añade un Gemfile con gem "fastlane", ejecuta bundle update, sube al repositorio tanto el Gemfile como el Gemfile.lock, y llama a los lanes con bundle exec fastlane [lane]. Versionar el lockfile fija la versión de fastlane, así que tu portátil y tu CI se comportan igual.
Homebrew y el Ruby del sistema también funcionan. La guía desaconseja el Ruby del sistema por problemas de permisos de archivos. Indica que fastlane admite Ruby 3.2 o superior y prefiere 3.3 o posterior.
Ejecuta fastlane init y corrige la configuración regional
Ejecuta fastlane init en el directorio del proyecto. Crea la carpeta fastlane, y fastlane/Fastfile contiene todo lo necesario para distribuir la app. Cada lane es un bloque con nombre que llamas desde la línea de comandos o desde el CI.
Fastlane también necesita una configuración regional UTF-8. Define LC_ALL y LANG como en_US.UTF-8. La guía de CI de fastlane advierte que muchos sistemas de CI usan por defecto una configuración sin definir o ASCII, así que compruébala en el runner.
Autenticar con una clave de API de App Store Connect
Usa una clave de API de App Store Connect en lugar de un Apple ID y una contraseña. La guía de claves de API de fastlane dice que la clave evita las solicitudes de verificación en dos pasos, rinde mejor y se apoya en una API documentada. Un runner de CI no puede responder a una solicitud de 2FA, así que esta decisión determina si las ejecuciones sin supervisión funcionan o no.
Crea la clave
En App Store Connect, abre Usuarios y acceso, luego la pestaña Integraciones, y crea una clave de equipo. Anota el issuer ID y descarga el archivo .p8 de inmediato. No se puede volver a descargar después de actualizar la página. Usa una clave de equipo: las claves individuales no llegan a los endpoints de aprovisionamiento que necesita match.
Cárgala en el Fastfile
La acción app_store_connect_api_key recibe key_id, issuer_id y key_filepath, además de un duration opcional de hasta 1200 segundos. Si la llamas sin asignar el resultado, guarda la clave en el contexto del lane y las acciones siguientes la cargan solas. Pilot, deliver, sigh, cert, match, download_dsyms y app_store_build_number admiten claves de API. Produce y pem no.
Guarda el contenido de la clave y los identificadores como secretos del CI. Nunca subas el archivo .p8 al repositorio.
Firma de código con match
Match saca tu identidad de firma de las máquinas individuales. Según la documentación de match, guarda certificados y perfiles cifrados en un repositorio git privado (el valor por defecto), en Google Cloud Storage o en Amazon S3. La opción type acepta development (por defecto), appstore, adhoc o enterprise. Define MATCH_PASSWORD como secreto para que el descifrado nunca pida la contraseña.
Pasar a match exige revocar antes tus certificados actuales, como indica la guía de firma de código de fastlane. Planifícalo para una semana tranquila, y lee antes el artículo sobre la configuración de APNs si los certificados de push forman parte de tus perfiles.
Usa readonly y setup_ci en el CI
En el CI, ejecuta match con readonly en true. Así solo descarga los certificados y perfiles existentes y nunca genera nuevos, de modo que una ejecución fallida no puede ensuciar tu cuenta de desarrollador. La documentación muestra match(type: "appstore", readonly: is_ci).
Pon setup_ci al principio del Fastfile. Según la documentación de setup_ci, crea un llavero temporal (llamado fastlane_tmp_keychain por defecto, desbloqueado durante 3600 segundos por defecto) y cambia match a modo de solo lectura. El llavero temporal mantiene las identidades de firma fuera del llavero de sesión del runner.
Un detalle práctico de la documentación de match: GitHub no permite la misma deploy key en varios repositorios. Si varios proyectos comparten un repositorio de certificados, usa una cuenta de solo lectura aparte.
Compilar y enviar a TestFlight
Dos acciones hacen el trabajo. build_app (también llamada gym) archiva la app con xcodebuild, la exporta y devuelve la ruta del ipa firmado. Según la documentación de build_app, el scheme debe estar marcado como Shared, y export_method acepta valores como app-store, ad-hoc y development. El output_directory es por defecto el directorio actual.
Un lane beta mínimo se ve así:
lane :beta do
setup_ci
app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_filepath: ENV["ASC_KEY_PATH"]
)
match(type: "appstore", readonly: true)
build_app(scheme: "App", export_method: "app-store")
upload_to_testflight(changelog: "Build from main")
end
Sustituye el scheme y los nombres de variables por los tuyos. La acción upload_to_testflight (pilot) define el texto "Qué probar" con changelog. Su opción skip_waiting_for_build_processing, false por defecto, importa cuando los minutos de CI se facturan. La documentación de pilot dice que, con ella en true, no se distribuye ninguna compilación a los testers y distribute_external deja de funcionar. Con un changelog definido, espera solo hasta que la compilación aparece para poder asociarle el changelog.
Enviar a revisión con deliver
Deliver, también llamado upload_to_app_store, sube metadatos, capturas, previsualizaciones y binarios. La documentación de deliver indica que submit_for_review es false por defecto, así que un lane nunca envía por accidente. Ponlo en true cuando quieras que el lane envíe la última compilación después de subirla.
Hay dos valores por defecto más que importan aquí. automatic_release controla si la app sale para todos los usuarios cuando Apple la aprueba. Y run_precheck_before_submit es true por defecto, así que deliver ejecuta precheck para detectar causas comunes de rechazo antes de enviar. El nivel de regla por defecto de precheck es :warn.
Pasa force en true en el CI. Sin él, deliver muestra una vista previa HTML y espera confirmación.
Conectar los lanes al CI
Fastlane funciona con GitHub Actions, GitLab CI, CircleCI, Bitrise, Codemagic y Jenkins, entre otros. El patrón es el mismo en todos: descargar el código, ejecutar bundle install, exportar los secretos como variables de entorno y llamar a bundle exec fastlane beta.
Mantén corta la lista de secretos. Necesitas el key ID, el issuer ID y el contenido de la clave de API, además de MATCH_PASSWORD. Define LANG y LC_ALL en el trabajo.
No publiques en App Store con cada commit. La guía de CI de fastlane señala que la revisión puede tardar de 1 a 2 días, y recomienda usar etiquetas de git o un trabajo de lanzamiento manual. Un reparto razonable es TestFlight en cada merge a main y un lane de lanzamiento con etiqueta para deliver. Trata la duración de las compilaciones como cualquier otro presupuesto, igual que aplicarías presupuestos en CI en un proyecto web.
Conclusión
Empieza con Bundler y un lockfile versionado, autentica con una clave de API, deja que match gestione la firma en modo de solo lectura y separa las subidas a TestFlight de los envíos a App Store. Con eso tienes un proceso de lanzamiento que no depende del portátil de una persona. Si quieres una segunda opinión sobre tu pipeline, nuestro equipo de desarrollo iOS lo configura como parte de la entrega de la app.
Preguntas frecuentes
¿Necesito la contraseña de un Apple ID para ejecutar fastlane en el CI?
No. Una clave de API de App Store Connect (key ID, issuer ID y el archivo .p8) autentica pilot, deliver, match y otras acciones sin solicitudes de 2FA. Produce y pem no admiten claves de API.
¿Qué hace el modo readonly de match?
El modo readonly descarga los certificados y perfiles existentes y nunca genera nuevos. Es el ajuste seguro para el CI, y setup_ci lo activa por ti.
¿Deliver envía mi app a revisión automáticamente?
Solo si defines submit_for_review en true. El valor por defecto es false, y deliver ejecuta precheck antes de enviar salvo que lo desactives.
¿Cada commit debe ir a App Store?
No. La revisión puede tardar de 1 a 2 días, y fastlane aconseja lanzar desde una etiqueta de git o un trabajo manual. Envía cada merge a TestFlight y reserva el lane de App Store para lanzamientos deliberados.