Saltar al contenido

Acciones de GitHub

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:

  • Una cuenta de Capgo con una suscripción activa y un clave API de Capgo
  • Tu app registrada en Capgo (bunx @capgo/cli@latest app add si no lo está)
  • Credenciales de build configuradas localmente con bunx @capgo/cli@latest build init — consulta Gestión de credenciales para el tutorial del wizard
  • Un build local exitoso (bunx @capgo/cli@latest build request com.example.app --platform android --build-mode debug) — el CI no es el lugar para debuggear tu primer build
  • El GitHub CLI (gh) 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.

  1. 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:

    Ventana de terminal
    gh secret set CAPGO_TOKEN --body "your_capgo_api_key_here"

    Genera la clave en el Dashboard de Capgo con subida permisos o superiores.

  2. Exporta tus credenciales a un .env archivo

    Ejecuta el gestor de credenciales interactivo:

    Ventana de terminal
    bunx @capgo/cli@latest build credentials manage --appId com.example.app

    En 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.

  3. 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:

    Ventana de terminal
    gh secret set -f .env.capgo.com.example.app

    Listo: todos los secretos que necesita tu workflow ya están en GitHub. Verifícalo con gh secret list.

  4. 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):

PlataformaSecrets creados
iOSBUILD_CERTIFICATE_BASE64, P12_PASSWORD, CAPGO_IOS_PROVISIONING_MAP_BASE64, APPLE_KEY_ID, APPLE_ISSUER_ID, APPLE_KEY_CONTENT, APP_STORE_CONNECT_TEAM_ID
AndroidANDROID_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.

.github/workflows/capgo-build-manual.yml
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.

.github/workflows/capgo-build-release.yml
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 release

La 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.

.github/workflows/capgo-build-main.yml
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-upload

El 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-release

Pasa --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-bump

bun 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íntomaCausa probable
CAPGO_TOKEN is not setEl secreto no se añadió o el job no tiene acceso (revisa las protecciones de branch/environment)
Errores por credenciales faltantes de iOS / Androidgh 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 localUn 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 ConnectID 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 IDEl 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 fallandoNo 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 combinadoLas 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íaEl 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 schemaVersionEl 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.