Construyendo una Pokédex en iOS — Parte 10: CI/CD con GitHub Actions
Última parte de la serie PokeTracker: configuramos un pipeline de CI/CD con GitHub Actions que compila y prueba la app en cada push. Y el repositorio.
En los nueve posts anteriores construimos la app completa. Este es el último paso: automatizar el build y las pruebas para que cada cambio en el repositorio se verifique sin intervención manual.
Por qué CI/CD desde el primer día
La conversación sobre CI/CD suele quedar para “cuando el proyecto crezca”. El problema es que configurarlo en un proyecto grande con deuda técnica acumulada es mucho más difícil. En un proyecto pequeño cuesta 20 minutos y desde el primer commit te da:
- Confirmación de que el código compila en una máquina limpia (no solo en la tuya)
- Las pruebas corren automáticamente — sin depender de que alguien se acuerde de
⌘U - Un historial de si el código estaba verde o rojo en cada commit
GitHub Actions para iOS
GitHub Actions tiene runners con macOS y Xcode preinstalados. No necesitas ningún servicio externo.
Crea el archivo .github/workflows/ci.yml en la raíz del repositorio de PokeTracker:
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
build-and-test:
name: Build & Test
runs-on: macos-15
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_16.3.app
- name: Build
run: |
xcodebuild build \
-project PokeTracker.xcodeproj \
-scheme PokeTracker \
-destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \
CODE_SIGNING_ALLOWED=NO \
| xcpretty
- name: Run Tests
run: |
xcodebuild test \
-project PokeTracker.xcodeproj \
-scheme PokeTracker \
-destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \
CODE_SIGNING_ALLOWED=NO \
| xcpretty
Algunas decisiones en este archivo:
macos-15 es el runner con Xcode 16. Si necesitas una versión específica, GitHub publica la lista de runners disponibles en su documentación.
CODE_SIGNING_ALLOWED=NO evita el problema de firma de código en CI. En un runner de GitHub no tienes certificados instalados. Esta flag desactiva el code signing para builds de test y simulador.
xcpretty formatea la salida de xcodebuild, que por defecto es muy verbosa. Para instalarlo agrega este step antes del build:
- name: Install xcpretty
run: gem install xcpretty
O puedes omitirlo y pasar la salida sin formatear — funciona igual, solo es más difícil de leer.
Agregar un badge al README
El README puede mostrar el estado actual del CI. Agrega esta línea al principio del README.md del proyecto:

El badge se actualiza automáticamente — verde si el último build pasó, rojo si falló.
El pipeline completo
Con este workflow, cada push a main o develop, y cada Pull Request hacia esas ramas, dispara:
- Checkout del código
- Build del proyecto sin firma de código
- Ejecución de todos los tests del target
PokeTrackerTests
Si algo falla, el commit o el PR quedan marcados en rojo en GitHub. Si pasa, queda verde. Simple.
El repositorio
A lo largo de esta serie construimos cada pieza explicando el por qué detrás de cada decisión. Si seguiste los posts, tienes el proyecto funcionando. Si quieres comparar con la implementación completa o simplemente explorarlo:
El repositorio incluye todo lo que vimos en la serie más las vistas Atoms y Molecules de Atomic Design que no cubrimos en detalle por espacio. Si tienes dudas sobre cualquier parte del código, puedes escribirme desde el chat en slekens.dev.
Resumen de la serie
| Post | Tema |
|---|---|
| 1 | Estructura del proyecto y decisiones de arquitectura |
| 2 | Capa de red: APIClient, Endpoint, NetworkError |
| 3 | DTOs y el contrato con la API |
| 4 | Repository Pattern |
| 5 | Modelos de dominio y Use Cases |
| 6 | Persistencia offline con SwiftData |
| 7 | Caché de imágenes con NSCache + FileManager |
| 8 | ViewModel con @Observable |
| 9 | Pruebas unitarias con Swift Testing |
| 10 | CI/CD con GitHub Actions |
Gracias por leer la serie.