La mayoría de los errores de CI/CD de Capacitor provienen de la misma lista corta: firma de iOS code, herramientas macOS faltantes o desactualizadas, una compilación web que nunca llegó al proyecto nativo, números de compilación reutilizados y requisitos de tienda que solo fallan en el momento de subir.
Si está configurando una pipeline desde cero, lea Configurando CI/CD para aplicaciones Capacitor primero, y luego utilice esta lista para endurecerla.
Etapa 1: Construcción de la capa web
Problema: la aplicación nativa envía una compilación web antigua
Síntoma: CI tiene éxito, la aplicación se instala, pero muestra la interfaz de usuario de ayer.
Causa: cap sync copias lo que está en webDir en ese momento. Si se ejecuta el pipeline cap sync antes de la compilación web, o la compilación web escribe a un carpeta diferente que webDir Solución: capacitor.config.tsEl proyecto nativo obtiene archivos obsoletos.
Fix: Siempre ejecuta los pasos en este orden, y falla si el carpeta de salida está vacía.
bun install --frozen-lockfile
bun run build
test -f dist/index.html || { echo "web build missing"; exit 1; }
bunx cap sync
para Vite, webDir coincide con tu salida del empaquetador (dist para Rollup, www para Angular con Ionic, build para algunas configuraciones de React).
Pitfall: dev server URL left in the config
Síntoma: la compilación de lanzamiento muestra una pantalla en blanco o intenta cargar http://192.168.x.x:5173.
Causa: server.url en capacitor.config.ts se configuró para el recarga en vivo y se comprometió.
Solución: nunca se comite server.url. Leerlo de una variable de entorno que CI nunca establece:
import type { CapacitorConfig } from '@capacitor/cli'
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'Example',
webDir: 'dist',
...(process.env.LIVE_RELOAD_URL && {
server: { url: process.env.LIVE_RELOAD_URL, cleartext: true },
}),
}
export default config
Trampa: las variables de entorno se hornearon en el momento equivocado
Síntoma: the production app talks to the staging API.
Causa: Vite, webpack y Angular establecen variables de entorno inline en tiempo de compilación. El valor presente cuando bun run build ran es el que se encuentra en el binario, y en cualquier live update construido a partir del mismo trabajo.
Fix: Establezca variables de entorno específicas para el ambiente antes de la compilación web, por tarea, y compile bundles separados para staging y producción. No intente intercambiarlos después. cap sync.
Trampa: desfase de archivo de bloqueo
Síntoma: Una versión del plugin en CI difiere de la instalada en tu máquina, y la compilación nativa falla por faltantes de símbolos.
Fix: Pitfall: drift del archivo de bloqueo bun install --frozen-lockfile (o npm ci). Pestaña @capacitor/core, @capacitor/ios, @capacitor/android, y @capacitor/cli hasta la misma versión. Las versiones desincronizadas son una fuente frecuente de errores nativos; consulte Corregir errores de versión de Capacitor.
Etapa 2: La herramienta de cadena nativa
Trampa: versión de Node, JDK o Xcode incorrecta
Síntoma: Unsupported class file major version, The engine "node" is incompatible, o errores de Xcode sobre SDK características.
Causa: imagenes de ejecución de corredor hospedado cambian, y Capacitor 8 tiene firmes mínimos.
| Tool | Capacitor 8 requisito |
|---|---|
| Node.js | 22 o más reciente |
| JDK | 21 |
| Xcode | 26 o más reciente |
| Objetivo de compilación para iOS | 15.0 |
Android minSdkVersion / targetSdkVersion |
24 / 36 |
Solución: pinar cada versión explícitamente en la canalización en lugar de confiar latest:
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '26'
Pitfall: construir contra un Xcode Apple ya no acepta
Síntoma: el subir falla con un mensaje que indica que la aplicación se construyó con un SDK no soportado.
Causa: desde el 28 de abril de 2026, App Store Connect requiere Xcode 26 y el iOS 26 SDK. Los Macs autoadministrados y las imágenes de ejecución más antiguas siguen utilizando Xcode 16.
Solución: seleccione una macos-26 imagen o instale Xcode 26 en sus ejecutores. Detalles en Requisito de Xcode 26 de Apple para Capacitor apps.
Pitfall: confusión entre CocoaPods y SPM
Síntoma: xcodebuild: error: 'App.xcworkspace' does not existo no se encuentran los pods.
Causa: nuevos Capacitor 8 proyectos utilizan el gestor de paquetes Swift y se construyen ios/App/App.xcodeprojProyectos más antiguos usan CocoaPods y construyen ios/App/App.xcworkspace después pod install. Las pipelines copiadas de tutoriales más antiguos asumen el workspace.
Solución: verifique qué una utiliza su proyecto y construya el archivo correcto. Si está migrando, consulte Cómo migrar su Capacitor aplicación a SPM.
Fallas comunes: Los plugins de Android rompen después de una actualización de Gradle
Síntoma: Namespace not specified, package attribute is deprecated, o errores de un plugin’s build.gradle después de actualizar Android Studio.
Solución: pinche el plugin de Gradle de Android en android/build.gradleactualiza en una rama, y actualiza los plugins primero. Los errores específicos se cubren en Soluciona errores de compilación del plugin Capacitor con AGP 9.
Etapa 3: Code de firma
Trampa: la firma de iOS funciona solo en tu Mac
Síntoma: No signing certificate "iOS Distribution" found, No profiles for 'com.example.app' were foundo errSecInternalComponent.
Causa: La llave de tu Mac almacena el certificado y Xcode descarga perfiles para ti. Un ejecutor de CI no tiene ninguno, y su llave de acceso está bloqueada en una sesión no interactiva.
Solución: importa el certificado en una llave de acceso temporal desbloqueada e instala el perfil donde Xcode 16 y posteriores buscan:
security create-keychain -p "$KEYCHAIN_PASSWORD" ci.keychain
security set-keychain-settings -lut 21600 ci.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" ci.keychain
security import dist.p12 -k ci.keychain -P "$P12_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" ci.keychain
security list-keychains -d user -s ci.keychain login.keychain
PROFILES="$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles"
mkdir -p "$PROFILES"
cp app.mobileprovision "$PROFILES/"
Utiliza el nombre de identidad Apple Distribution, no la legado iOS Distribution. fastlane’s setup_ci plus match automates this. Capgo Build takes the certificate and profile as environment variables and does the keychain work on its own machines, so the Linux job never touches security.
Pitfall: certificados expirados o revocados
Symptom: Un pipeline que funcionaba durante un año falla de repente.
Cause: Apple distribution certificates and provisioning profiles expire after a year. A teammate creating a new certificate in Xcode can also invalidate the profile your CI uses.
Fix: Coloque las fechas de vencimiento en el calendario de su equipo, mantenga un certificado de distribución compartido para CI y revise antes de compilar. bunx @capgo/cli@latest build prescan --platform ios Verifica la expiración del certificado, la contraseña y la pareja de perfil antes de subir cualquier cosa.
Pitfall: Apple ID logins and two-factor prompts
Síntoma: fastlane se queda esperando un code de 6 dígitos.
Solución: utilice una clave de App Store Connect API.p8, key ID, issuer ID) instead of an Apple ID and password. It does not require two-factor authentication and can be scoped to App Manager. If authentication still fails with a correct key, check the runner clock: the token is signed with the local time, and Apple rejects tokens with a skewed timestamp.
Trampa: secretos base64 que no se pueden descodificar
Síntoma: MAC verification failed, invalid keystore formatCausa: base64: invalid input.
Cause: generado con OpenSSL 3 por defecto que macOS no puede leer. .p12 creado con OpenSSL 3 por defecto que macOS no puede leer.
Solución: codificar en una sola línea, y usar -legacy cuando se crea un .p12 con OpenSSL 3:
base64 -i dist.p12 | tr -d '\n' > dist.p12.b64
openssl pkcs12 -export -legacy -inkey key.pem -in cert.pem -out dist.p12
Pitfall: un keystore de Android perdido
Síntoma: no puedes firmar una actualización porque nadie tiene el keystore.
Solución: con Play App Signing, el keystore es la clave de carga, y el soporte de la consola de Play puede registrar una nueva. Almacena el keystore en tus secretos de CI y en un respaldo offline. Nunca lo dejes vivo solo en una laptop. El generador de keystore de Android crea uno nuevo si estás empezando de nuevo.
Etapa 4: Diseño de la canalización
Pitfall: compilaciones nativas en cada solicitud de extracción
Síntoma: revisión de PR lenta y un gran cargo por minutos en macOS.
Causa: Los builds de iOS en ejecutores macOS hospedados son los minutos más costosos en la mayoría de los planes de CI, y la mayoría de los commits solo tocan JavaScript.
Solución: ejecutar lint, pruebas y la construcción web en cada PR. Ejecutar builds nativos en etiquetas de lanzamiento o fusiones para mainPara PR previas, envía el paquete web a un canal Capgo en lugar de construir un binario, como se describe en Comparando plataformas de CI/CD para aplicaciones Capacitor.
Comparar plataformas CI/CD para aplicaciones __CAPGO_KEEP_0__
Solución: utilice una matriz para que tanto las plataformas construyan en paralelo, y configure fail-fast: false Un problema de firmado de iOS no cancela un buen build de Android.
strategy:
fail-fast: false
matrix:
platform: [ios, android]
Pitfall: sin caché, o el caché equivocado
Simptomá: cada compilación descarga dependencias de Gradle y CocoaPods desde cero, o una compilación de staging envía la configuración de producción desde una caché obsoleta.
Solución: caché ~/.gradle/caches, ~/.gradle/wrapper, y ios/App/Pods Almacenar cachés por entorno. Con Capgo Build, se puede dividir la caché de compilación por aplicación. --cache-key prod y --cache-key staging, o saltarse con --no-cache para una construcción limpia.
Pitfall: rutas de repositorio único
Simptomá: could not find capacitor.config o plugins faltantes en el proyecto nativo.
Solución: run Capacitor commands from the app package, and point tools at hoisted node_modulesEl Capgo CLI acepta --path y --node-modules para esto.
Etapa 5: Envío de la tienda
Trampa: números de compilación reutilizados
Síntoma: “La versión del paquete debe ser mayor que la versión subida anteriormente” en iOS, o “La versión code ya ha sido utilizada” en Google Play.
Solución: generar el número en CI. Con fastlane, leer la última compilación de TestFlight y sumar uno. Con Capgo Build, esto es el default: obtiene el último número de compilación de App Store Connect o el más alto versionCode desde Google Play y lo incrementa.
Pitfall: compilaciones atascadas en TestFlight
Síntoma: el subir tiene éxito pero los probadores nunca ven la compilación.
Causa: falta de cumplimiento de exportación.
Solución: decláralo una vez en ios/App/App/Info.plist si solo usas cifrado estándar:
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
Pitfall: rechazos del manifiesto de privacidad
Síntoma: correo electrónico de Apple sobre la razón requerida faltante API (ITMS-91053).
Solución: agregar un PrivacyInfo.xcprivacy a la configuración de destino de la aplicación y actualizar los plugins que envían sus propios. guía de privacidad para aplicaciones Capacitor.
Fallas: tipo de artefacto incorrecto
Solución: Google Play necesita un AAB (bundleRelease), no un APK. bundleRelease sigue teniendo éxito sin un release configura la firma y produce un AAB sin firmar que Play rechaza, así que signingConfigs.release in android/app/build.gradle Primero. iOS requiere una exportación a la Tienda de Aplicaciones, no un IPA de desarrollo o ad hoc. Verifique el método de exportación en su paso de compilación.
Etapa 6: Actualizaciones en vivo
Obstáculo: enviar un live update que requiere una nueva compilación nativa
Síntoma: después de una actualización por aire, la aplicación se bloquea al llamar a un método de plugin que no existe en el binario instalado.
Causa: la biblioteca web depende de una versión de plugin más nueva que la compilada en la aplicación en los dispositivos de los usuarios.
Solución: deje que el pipeline decida. build needed sale 0 cuando las dependencias nativas coinciden con lo que está vivo en el canal y 1 cuando se requiere un nuevo binario:
if bunx @capgo/cli@latest build needed com.example.app --channel production; then
bunx @capgo/cli@latest bundle upload com.example.app --channel production
else
bunx cap sync
bunx @capgo/cli@latest build request com.example.app --platform ios
bunx @capgo/cli@latest build request com.example.app --platform android
fi
también fuerza el camino nativo cuando los archivos bajo ios/, android/o capacitor.config.* cambian. El patrón completo está en Elija automáticamente live update o compilación nativay las reglas de compatibilidad están en compatibilidad nativa.
La solución que elimina más obstáculos
Si solo cambias una cosa, mueve la compilación y firma de iOS fuera de tus ejecutores de CI. La configuración de Keychain, las actualizaciones de Xcode, los costos de macOS y la instalación de perfiles desaparecen de tu pipeline cuando un trabajo de Linux le entrega el proyecto preparado a Capgo Construcción:
bun install --frozen-lockfile && bun run build
bunx cap sync ios
bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release
La mayoría de los obstáculos en las etapas 1, 5 y 6 siguen siendo aplicables, ya que se refieren a tu proyecto, no al ejecutor. Para más información sobre depuración de tareas fallidas, consulta Corrigiendo errores de compilación en pipelines CI/CD de Capacitor.
Referencia rápida
| Error | Trampa | Sección |
|---|---|---|
| Interfaz antigua en una nueva compilación | cap sync antes de la compilación web |
Etapa 1 |
No profiles for ... were found |
Perfil no instalado o no coincidente | Etapa 3 |
errSecInternalComponent |
Cadena de claves bloqueada | Etapa 3 |
MAC verification failed |
Contraseña incorrecta o OpenSSL 3 .p12 |
Etapa 3 |
Unsupported class file major version |
JDK incorrecto | Etapa 2 |
| SDK demasiado antiguo en carga | Xcode mayor a 26 | Etapa 2 |
| La versión del paquete debe ser mayor | Número de compilación reutilizado | Etapa 5 |
| La versión code ya se ha utilizado | Reutilizado versionCode |
Etapa 5 |
| Crash después de live update | Cambios nativos enviados por aire | Etapa 6 |