Releases sin intervención
Etiqueta un release en Git y tus binarios firmados de iOS y Android se envían automáticamente a TestFlight y Play Store.
Copia un prompt de configuración con los pasos de instalación y la guía completa en markdown para este plugin.
Automatiza tus builds de iOS y Android directamente desde tu repositorio de GitHub. Con un solo archivo de workflow y unos pocos secrets del repositorio, cada push, tag o disparo manual puede generar apps firmadas y listas para las tiendas, sin que nadie en el equipo necesite tener Mac, Xcode o Android Studio instalados.
Respuesta corta: para Capacitor CI/CD en GitHub Actions, añade un workflow que ejecute Capgo CLI: Capgo Builder produce los builds firmados de iOS y Android y puede hacer upload a las tiendas, y, con un job adicional bundle upload (ver OTA automático o nativo), el mismo workflow puede desplegar cambios solo de web como Capgo live updates.
Releases sin intervención
Etiqueta un release en Git y tus binarios firmados de iOS y Android se envían automáticamente a TestFlight y Play Store.
Sin configuración local
Los colaboradores en Windows o Linux pueden iniciar builds de iOS. Sin Xcode, sin problemas de provisioning y sin certificados de firma compartidos flotando por las laptops.
Secretos con alcance limitado
Las credenciales se guardan en los secretos del repositorio de GitHub, con alcance limitado a tu repo y visibles solo para el workflow runner. Fáciles de rotar y auditar.
Builds en paralelo
Compila iOS y Android al mismo tiempo con un job de matriz. Un release típico termina en menos de 10 minutos.
Antes de configurar el workflow, asegúrate de tener:
bunx @capgo/cli@latest app add si no lo está)bunx @capgo/cli@latest build init — consulta Gestión de credenciales para el tutorial del wizardbunx @capgo/cli@latest build request com.example.app --platform android --build-mode debug) — el CI no es el lugar para debuggear tu primer buildgh) instalado y autenticado (gh auth login)El Capgo CLI puede exportar tus credenciales locales como un .env archivo listo para usar. Combinado con gh secret set -f, esto convierte todo el setup de CI/CD en tres comandos: sin codificación base64 manual, sin lidiar con JSON y sin copiar secretos uno por uno.
Añade tu clave Capgo API como secret del repositorio
La clave API no forma parte del almacén de credenciales por app, así que añádela una vez manualmente:
gh secret set CAPGO_TOKEN --body "your_capgo_api_key_here"Genera la clave en el Dashboard de Capgo con subida permisos o superiores.
Exporta tus credenciales a un .env archivo
Ejecuta el gestor de credenciales interactivo:
bunx @capgo/cli@latest build credentials manage --appId com.example.appEn la TUI, selecciona Exportar a .env. El CLI escribe .env.capgo.<appId> en tu directorio actual con modo 0600 (solo lectura para el propietario) — por ejemplo, .env.capgo.com.example.app. Cuando iOS y Android están configurados, los secretos de ambas plataformas se guardan en el mismo archivo bajo # === IOS === y # === ANDROID === encabezados de sección. Los nombres de variables de entorno de iOS y Android son distintos, por lo que combinarlos no genera conflictos.
Sube el .env archivo a los secrets de GitHub Actions
El gh secret set -f El comando lee un archivo dotenv y crea un secreto de repositorio por KEY=value línea:
gh secret set -f .env.capgo.com.example.appListo: todos los secretos que necesita tu workflow ya están en GitHub. Verifícalo con gh secret list.
Crea el archivo del workflow
Añadir .github/workflows/capgo-build.yml en tu repositorio. Elige uno de los tres patrones de trigger de abajo según cómo quieras disparar los builds.
Como referencia, gh secret set -f creará estos repository secrets (tu YAML del workflow los referencia con estos nombres exactos):
| Plataforma | Secrets creados |
|---|---|
| iOS | BUILD_CERTIFICATE_BASE64, P12_PASSWORD, CAPGO_IOS_PROVISIONING_MAP_BASE64, APPLE_KEY_ID, APPLE_ISSUER_ID, APPLE_KEY_CONTENT, APP_STORE_CONNECT_TEAM_ID |
| Android | ANDROID_KEYSTORE_FILE, KEYSTORE_KEY_ALIAS, KEYSTORE_KEY_PASSWORD, KEYSTORE_STORE_PASSWORD, PLAY_CONFIG_JSON |
| (añadido manualmente) | CAPGO_TOKEN |
No necesitas memorizarlos: los ejemplos de workflow a continuación ya los incluyen todos.
Los tres ejemplos a continuación cubren los patrones más comunes. Todos siguen la misma estructura: clonar el repo, instalar dependencias, compilar los assets web, sincronizar con native y luego llamar a Capgo Build pasando las credenciales como variables de entorno.
Permite a cualquier persona con acceso de escritura iniciar un build desde Acciones pestaña en GitHub con un desplegable de plataforma. Útil para builds de prueba ad hoc o para iniciar un release bajo demanda.
name: Capgo Build (Manual)
on: workflow_dispatch: inputs: platform: description: 'Platform to build' required: true default: 'android' type: choice options: [ios, android, both] mode: description: 'Build mode' required: true default: 'debug' type: choice options: [debug, release]
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 with: bun-version: latest
- run: bun install --frozen-lockfile - run: bun run build - run: bunx cap sync
- name: Trigger Capgo Build env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} CAPGO_IOS_PROVISIONING_MAP_BASE64: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP_BASE64 }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | bunx @capgo/cli@latest build request com.example.app \ --platform ${{ inputs.platform }} \ --build-mode ${{ inputs.mode }}Reemplazar com.example.app con tu app ID. Una vez commitado, ve a Actions → Capgo Build (Manual) → Ejecutar workflow para dispararlo.
Compila y publica ambas plataformas en paralelo cada vez que envías una etiqueta de versión como v1.4.0. Esta es la configuración de producción más común — git tag v1.4.0 && git push --tags se convierte en tu comando de release.
name: Capgo Build (Release)
on: push: tags: - 'v*'
jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: platform: [ios, android] steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 with: bun-version: latest
- run: bun install --frozen-lockfile - run: bun run build - run: bunx cap sync ${{ matrix.platform }}
- name: Build ${{ matrix.platform }} env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} # iOS BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} CAPGO_IOS_PROVISIONING_MAP_BASE64: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP_BASE64 }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} # Android ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | bunx @capgo/cli@latest build request com.example.app \ --platform ${{ matrix.platform }} \ --build-mode releaseLa matriz ejecuta iOS y Android en paralelo en runners separados. Establecer fail-fast: false significa que un build de iOS fallido no cancelará el build de Android en curso (y viceversa), útil cuando una plataforma tiene un problema temporal de firma.
Detecta regresiones del build nativo de forma temprana generando un build Android de debug con cada push a main. Es económico, ofrece feedback rápido y puedes omitir el upload a la Play Store para que sea solo un smoke test.
name: Capgo Build (Main)
on: push: branches: [main] paths: - 'src/**' - 'android/**' - 'ios/**' - 'package.json' - 'capacitor.config.*'
jobs: smoke-build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 with: bun-version: latest
- run: bun install --frozen-lockfile - run: bun run build - run: bunx cap sync android
- name: Smoke build (Android debug) env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} run: | bunx @capgo/cli@latest build request com.example.app \ --platform android \ --build-mode debug \ --no-playstore-upload \ --output-uploadEl paths filter garantiza que el workflow no se ejecute en cambios solo de documentación. --no-playstore-upload omite el envío a Play Store (no se PLAY_CONFIG_JSON necesita) y --output-upload genera una URL de descarga para el APK resultante para que puedas instalarlo en un dispositivo de prueba.
Para builds de prueba, omite el envío a la tienda: Android usa --no-playstore-upload; para iOS, compila en modo ad-hoc con --ios-distribution ad_hoc (que nunca se envía a la App Store). Combina cualquiera de ellos con --output-upload para obtener una URL de descarga temporal para el binario.
Por defecto, las builds de release suben el artefacto firmado y dejan la acción final de la tienda bajo tu control. Para releases de CI que deben pasar directamente al flujo de revisión de la tienda, añade --submit-to-store-review.
Android usa tu PLAY_CONFIG_JSON cuenta de servicio. Sin un track explícito, --submit-to-store-review por defecto usa el track de producción con release_status: completed. Es preferible indicar el track en el punto de llamada con --android-track (o PLAY_STORE_TRACK), y sobrescribir el estado con --android-release-status / PLAY_STORE_RELEASE_STATUS cuando sea necesario:
- name: Submit Android release for review env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | npx @capgo/cli@latest build request com.example.app \ --platform android \ --build-mode release \ --submit-to-store-review \ --android-track production \ --store-release-name "${GITHUB_REF_NAME}" \ --store-release-notes "Release ${GITHUB_REF_NAME}" \ --store-release-notes-locale "en-US=Release ${GITHUB_REF_NAME}"Para una release interna completada en lugar de producción:
- name: Submit Android internal release env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | npx @capgo/cli@latest build request com.example.app \ --platform android \ --build-mode release \ --submit-to-store-review \ --android-track internal \ --store-release-name "${GITHUB_REF_NAME}"iOS utiliza la ruta de la clave API de App Store Connect y envía el build procesado de TestFlight a la revisión de App Store. Requiere app_store distribución; --ios-testflight-groups es opcional para la distribución beta externa y no es necesario para la revisión de App Store:
- name: Submit iOS build to App Store review env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} run: | npx @capgo/cli@latest build request com.example.app \ --platform ios \ --build-mode release \ --ios-distribution app_store \ --submit-to-store-review \ --store-release-name "${GITHUB_REF_NAME}" \ --store-release-notes "Release ${GITHUB_REF_NAME}" \ --store-release-notes-locale "en-US=Release ${GITHUB_REF_NAME}" \ --no-ios-automatic-releasePasa --output-record <path> para persistir en disco la URL del artefacto de build y el QR code cuando el build tenga éxito, y luego leerlos en pasos posteriores con build last-output. Sin scraping de logs ni regex.
- name: Build env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} # ...credentials... run: | bunx @capgo/cli@latest build request com.example.app \ --platform android --build-mode debug \ --output-upload --output-retention 1d \ --output-record /tmp/build.json
- name: Comment on PR with build URL env: GH_TOKEN: ${{ github.token }} run: | URL=$(bunx @capgo/cli@latest build last-output --path /tmp/build.json --field outputUrl) if [ -n "$URL" ]; then gh pr comment ${{ github.event.pull_request.number }} \ --body "Debug build ready: $URL" fi--output-record /tmp/build.json escribe un registro JSON (con jobId, status, outputUrl, qrCodeAscii, qrCodePngPath, finishedAt) y un QR code en PNG junto a /tmp/build.json.qr.png. build last-output lo vuelve a leer:
--field outputUrl imprime solo la URL de descarga (terminada en salto de línea; segura para URL=$(...)).--field qrCodePngPath imprime la ruta del PNG para que puedas subirlo como adjunto en el PR.--qr imprime el QR ASCII renderizado — pégalo dentro de un bloque de código Markdown code en el comentario del PR para escanearlo directamente.Por defecto, cada release build incrementa el número de build. Para fijarlo a un valor que controles (por ejemplo, el tag de Git), pasa --skip-build-number-bump:
- name: Set version from tag run: | VERSION="${GITHUB_REF#refs/tags/v}" # Update package.json or your version source here bun pm version "$VERSION" --no-git-tag-version
- name: Build env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} # ...credentials... run: | bunx @capgo/cli@latest build request com.example.app \ --platform ios --build-mode release \ --skip-build-number-bumpbun install ya es lo bastante rápido como para que la caché de JS-deps rara vez compense, pero las dependencias nativas de Capacitor (CocoaPods, Gradle) sí merecen cachearse en proyectos grandes:
- uses: actions/cache@v4 with: path: | ~/.bun/install/cache ios/App/Pods android/.gradle key: ${{ runner.os }}-capgo-${{ hashFiles('**/bun.lock', '**/Podfile.lock') }}| Síntoma | Causa probable |
|---|---|
CAPGO_TOKEN is not set | El secreto no se añadió o el job no tiene acceso (revisa las protecciones de branch/environment) |
| Errores por credenciales faltantes de iOS / Android | gh secret set -f no se ejecutó, o se ejecutó contra otro repo. Verifica con gh secret list |
cap sync falla en CI pero funciona en local | Un plugin nativo no está en package.json, o te olvidaste de bun install antes cap sync |
| El build fue exitoso pero la app no aparece en App Store Connect | ID de equipo incorrecto, o el registro de la app aún no existe en App Store Connect. Verifica localmente con bunx @capgo/cli@latest build credentials manage |
| El build se queda colgado tras “Uploading project” | El archivo del proyecto es inusualmente grande: comprueba que node_modules no se esté subiendo (por defecto no debería) |
Provisioning profile doesn't match bundle ID | El mapa de aprovisionamiento apunta a un bundle ID diferente al que Xcode está firmando. Vuelve a ejecutar build init para actualizar el perfil y luego volver a exportar con build credentials manage |
| Las credenciales se cambiaron en local, pero CI sigue fallando | No olvides volver a exportar y a hacer push: bunx @capgo/cli@latest build credentials manage → gh secret set -f .env.capgo.<appId> |
| El manager se niega a escribir el archivo combinado | Las claves de configuración compartida difieren entre plataformas: el manager avisa y pide confirmación. Confirma para sobrescribir (uno gana) o vuelve a exportar por plataforma con --platform ios / --platform android |
build last-output muestra una URL vacía | El build no pasó --output-upload, o falló antes de generar un artifact. outputUrl será null en el registro. Bifurca según [ -n "$URL" ] antes de usarlo |
build last-output da error con Unsupported record schemaVersion | El runner está en una versión más antigua de CLI que la que escribió el registro. Fija tanto el productor como el lector a la misma versión explícita (p. ej. bunx @capgo/cli@7.104.0 … en ambos lados) en lugar de @latest, que flota y puede variar entre jobs |
Para fallos de build específicos de la plataforma, consulta guía de solución de problemas.