Conceptos básicos de CI/CD móvil
10 ejemplos para entender comprobaciones de PR, canalizaciones de lanzamiento y compilaciones nocturnas para aplicaciones de Expo SDK 57 - 7 básicos y 3 intermedios.
Busca en todas las páginas de la documentación
10 ejemplos para entender comprobaciones de PR, canalizaciones de lanzamiento y compilaciones nocturnas para aplicaciones de Expo SDK 57 - 7 básicos y 3 intermedios.
CI/CD para React Native difiere de web: envías binarios nativos (compilaciones de tienda) y opcionalmente paquetes de JavaScript OTA (Conceptos básicos de actualizaciones OTA). Las compilaciones en la nube vía Conceptos básicos de EAS Build mantienen las claves de firma fuera de los portátiles.
npx create-expo-app@latest ShipApp --template blank-typescript
cd ShipApp
npx expo install eas-cli --save-dev
npx eas-cli@latest build:configureEstandariza los scripts que CI llamará:
{
"scripts": {
"lint": "expo lint",
"typecheck": "tsc --noEmit",
"test": "jest",
"format:check": "prettier --check ."
}
}Tooling: Estos ejemplos están orientados a Expo SDK 57 (
expo~57.0.4), React Native 0.86.0, y React 19.2.3. Los fragmentos E2E asumen compilaciones dev o preview - no solo Expo Go.
Los equipos móviles ejecutan tres carriles de automatización distintos con diferentes objetivos de velocidad, costo y radio de acción.
┌─────────────────────────────────────────────────────────────┐
│ Comprobaciones de PR │ Cada PR │ 2–8 min │ Bloquear fusión │
├──────────────────────┼──────────┼──────────┼────────────────┤
│ Canalización de lanz.│ Tag/main │ 20–60 min│ Tienda + OTA │
├──────────────────────┼──────────┼──────────┼────────────────┤
│ Nocturna │ Cron 02:00│ 30–90 min│ Señal desviación│
└─────────────────────────────────────────────────────────────┘| Carril | Desencadenadores | Trabajos típicos | Bloquea |
|---|---|---|---|
| Comprobaciones de PR | pull_request | lint, tsc, Jest | Fusión a main |
| Lanzamiento | push tag v*, manual | EAS build, Maestro smoke, submit | Promoción de tienda |
| Nocturna | schedule: cron | Compilación de matriz completa, pruebas de contrato | Nada - solo alertas |
Relacionado: Compuertas de calidad de CI - script que llaman las comprobaciones de PR
La automatización de PR responde: "¿Es seguro fusionar este diff?" - no "¿Está listo para la App Store?"
# .github/workflows/pr-checks.yml
name: PR Checks
on:
pull_request:
branches: [main]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: npm }
- run: npm ci
- run: npx expo customize tsconfig.json
- run: npm run format:check
- run: npm run lint
- run: npm run typecheck
- run: npm run test -- --ciquality - política, no sistema de honornpm run lint && npm run typecheck && npm testRelacionado: Conceptos básicos de pruebas móviles - capas de pirámide que cubren las comprobaciones de PR
La automatización de lanzamiento responde: "Compila y envía la versión que etiquetamos."
# .github/workflows/release.yml
name: Release
on:
push:
tags: ["v*"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- run: npm ci
- run: npm run typecheck && npm run test -- --ci
- run: eas build --profile production --platform all --non-interactive// eas.json (extracto)
{
"build": {
"production": {
"autoIncrement": true,
"channel": "production"
}
}
}v2.4.0) - etiqueta ↔ trazabilidad de binariosEXPO_TOKEN cuenta robot - nunca contraseñas personales en CI (GitHub Actions + EAS)production se mapea a credenciales de firma de tienda en EASRelacionado: Perfiles de compilación y sabores -
previewvsproduction
Cuando el volumen de PR es alto, las comprobaciones verdes individuales ocultan fallos de integración entre ramas. Las nocturnas se ejecutan en un horario sin bloquear fusiones.
# .github/workflows/nightly.yml
name: Nightly Integration
on:
schedule:
- cron: "0 6 * * 1-5" # lunes-viernes 06:00 UTC
workflow_dispatch:
jobs:
nightly:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { ref: main }
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- run: npm ci
- run: npx expo-doctor
- run: npm run test -- --ci
- run: eas build --profile preview --platform android --non-interactive#mobile-ci) en caso de fallo - no bloques fusiones durante el díanpx expo-doctor - detecta desviación de SDK que nadie tocó en los PRs de hoyNo todo PR necesita un binario nativo. Separa compuertas rápidas de compilaciones preview opcionales.
| Señal | Solo comprobación de PR | + Compilación preview |
|---|---|---|
Cambio de copia en Text | ✓ | ✗ |
Nuevo módulo nativo (expo-camera) | lint/tsc | ✓ |
| Refactor de navegación | pruebas unitarias | ✓ (Maestro smoke) |
| Cambio de plugin de configuración | tsc + doctor | ✓ |
# Vista previa controlada por etiqueta - ahorra créditos de EAS
on:
pull_request:
types: [labeled]
jobs:
preview:
if: contains(github.event.pull_request.labels.*.name, 'needs-preview')
# ... eas build --profile previewpaths para directorios que impacten nativosneeds-previewLas correcciones solo JS envían vía eas update dentro de la canalización de lanzamiento - los cambios nativos aún necesitan eas build.
# .eas/workflows/release-ota.yml (extracto)
jobs:
quality:
steps:
- uses: eas/checkout
- uses: eas/install_node_modules
- run: npm run typecheck && npm run test -- --ci
update_production:
needs: [quality]
type: update
params:
channel: production
message: ${{ github.sha }}runtimeVersion debe coincidir con el binario de tienda que los usuarios instalaron - Política de versión de runtimeeas update --roll-back - Runbook de retornoEl anti-patrón: QA prueba una compilación de portátil; las tiendas reciben una compilación en la nube diferente.
❌ Compilación de portátil → Aprobación de QA → Recompilar en CI → Tienda
✅ ID de compilación de EAS abc123 → Aprobación de QA → eas submit --id abc123 → Tienda# Promueve la compilación exacta que QA probó
eas submit --platform ios --id <BUILD_ID> --non-interactive
eas submit --platform android --id <BUILD_ID> --non-interactiveeas submit --latest es conveniente pero riesgoso si una compilación más nueva se encoló después de QARelacionado: EAS Submit - Entrega de App Store Connect y Play Console
Los monorepos Turborepo no deben ejecutar CI móvil cuando solo el sitio de marketing cambió.
on:
pull_request:
paths:
- "apps/mobile/**"
- "packages/ui/**"
- "package-lock.json"# O acción de filtro de ruta
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
mobile:
- 'apps/mobile/**'
- 'packages/**'
- if: steps.changes.outputs.mobile == 'true'
run: npm run typecheck -w apps/mobileturbo run lint typecheck test --filter=mobile se abanica con caché - GitHub Actions + EASLos equipos avanzados encadenan quality → build → E2E → submit en un archivo de flujo de trabajo.
# .eas/workflows/store-release.yml (esquema)
name: Store Release
on:
push:
tags: ["v*"]
jobs:
quality:
steps:
- uses: eas/checkout
- uses: eas/install_node_modules
- run: npm run lint && npm run typecheck && npm run test -- --ci
build_ios:
needs: [quality]
type: build
params: { platform: ios, profile: production }
smoke_ios:
needs: [build_ios]
type: maestro
params:
build_id: ${{ needs.build_ios.outputs.build_id }}
flow_path: [".maestro/smoke.yml"]
submit_ios:
needs: [smoke_ios]
type: submit
params:
platform: ios
build_id: ${{ needs.build_ios.outputs.build_id }}needs encadena el orden - submit no puede ejecutarse si Maestro fallóLos lanzamientos móviles raramente se envían solos. Documenta dependencias de despliegue en un calendario de lanzamientos.
Tren de lanzamiento semana 12
Mar - API backend v3 se deploya a staging (pruebas de contrato verdes)
Mié - eas build production (JS nativo + incrustado)
Jue - eas update production (hotfix JS si se necesita, mismo runtimeVersion)
Vie - eas submit después de Maestro + QA manual
Lun - Lanzamiento por etapas 10% → 50% → 100%| Tipo de cambio | Se envía vía | Dependencia de backend |
|---|---|---|
| Color de botón | OTA | Ninguna |
| Campo de API nuevo (opcional) | OTA | Backend activo primero |
| Nuevo módulo nativo | Compilación de tienda | Feature flag apagado hasta que binario esté activo |
| API rompedora | Tienda + backend misma ventana | Coordinar congelación |
| Anti-patrón | Por qué falla |
|---|---|
eas build en cada commit de PR | Quema créditos; bucles de retroalimentación de 20 minutos |
| Saltar pruebas en etiquetas de lanzamiento | Las etiquetas "hotfix" envían regresiones |
| Archivo de portátil a TestFlight | No reproducible; desviación de firma |
| OTA sin disciplina de canal | Paquete de staging golpea usuarios de producción |
| Un pipeline para todo | PR espera 45 minutos; el equipo desactiva CI |
PR: lint, format, tsc, pruebas unitarias, pruebas de contrato opcional. Lanzamiento: EAS build, E2E smoke, submit, OTA al canal de producción.
Entre semana para equipos activos; semanales para aplicaciones pequeñas. Aumenta la frecuencia después de actualizaciones de SDK o migraciones de monorepo.
Los flujos de trabajo de EAS honran [eas skip] en disparadores de push. Prefiere previews controladas por etiqueta sobre tokens de skip de rutina - la protección de rama aún debe requerir comprobaciones de PR.
Muchos equipos usan GitHub Actions para comprobaciones de PR y flujos de trabajo de EAS para cadenas de compilación/prueba/submit. Mantén los scripts npm idénticos en ambos.
eas.jsonVersiones de stack: Esta página fue escrita para React 19.2.3, React Native 0.86.0, y Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última actualización: 16 jul 2026