Dispara Native Builds mediante Webhooks
Copia un prompt de configuración con los pasos de instalación y la guía completa en markdown para este plugin.
Capgo Build normalmente se inicia desde un portátil o un job de CI. Los equipos que despliegan desde un dashboard de administración, CMS o portal interno suelen querer un único webhook HTTP: pulsar un botón en su propia UI y que arranque un build nativo firmado. Esta guía muestra el patrón estándar: una llamada HTTP autenticada y ligera a tu host de code, que ejecuta el mismo flujo de trabajo de Capgo Build que ya usas.
Arquitectura
Sección titulada “Arquitectura”sequenceDiagram participant Admin as Admin dashboard participant Hook as Webhook endpoint participant CI as GitHub / GitLab participant Capgo as Capgo Build Admin->>Hook: POST /native-build (secret) Hook->>CI: repository_dispatch / pipeline trigger CI->>CI: checkout, npm ci, cap sync CI->>Capgo: build request Capgo-->>CI: signed binary / store upload
No necesitas que Capgo exponga un “build webhook” público. Tu CI ya tiene los secrets de firma; el único trabajo del webhook es iniciar ese job de CI de forma segura.
Requisitos
Sección titulada “Prerrequisitos”- Un workflow de Capgo Build que ya funciona desde la CI UI o al hacer push (Acciones de GitHub)
- Permiso para crear un token GitHub granular, un token de trigger de GitLab o equivalente
- Un secreto compartido que enviará tu dashboard de admin (header o body)
Opción A — GitHub repository_dispatch (recomendado)
Sección titulada “Opción A — GitHub repository_dispatch (recomendado)”GitHub acepta una llamada API autenticada que inicia un workflow a la escucha de repository_dispatch. Cualquier dashboard que pueda POST enviar JSON puede hacerlo.
1. Workflow que escucha el webhook
Sección titulada “1. Workflow que escucha el webhook”Valida el payload antes en el checkout y antes de cualquier paso con secretos. Pasa los valores aceptados mediante job outputs / env vars; nunca los interpoles client_payload directamente en run: scripts (guía sobre inyección de scripts).
name: Capgo Build (Webhook)
on: repository_dispatch: types: [capgo-native-build]
jobs: validate: runs-on: ubuntu-latest outputs: platform: ${{ steps.check.outputs.platform }} mode: ${{ steps.check.outputs.mode }} ref: ${{ steps.check.outputs.ref }} platforms_json: ${{ steps.check.outputs.platforms_json }} steps: - id: check env: RAW_PLATFORM: ${{ github.event.client_payload.platform }} RAW_MODE: ${{ github.event.client_payload.mode }} RAW_REF: ${{ github.event.client_payload.ref }} DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} run: | PLATFORM="${RAW_PLATFORM:-android}" MODE="${RAW_MODE:-release}" REF="${RAW_REF:-$DEFAULT_BRANCH}" case "$PLATFORM" in ios|android|both) ;; *) echo "Invalid platform: $PLATFORM" >&2; exit 1;; esac case "$MODE" in debug|release) ;; *) echo "Invalid mode: $MODE" >&2; exit 1;; esac # Allowlist branches / tags / full SHAs only if [[ ! "$REF" =~ ^(main|master|production|release/[A-Za-z0-9._-]+|[0-9a-f]{40})$ ]]; then echo "Ref not allowlisted: $REF" >&2 exit 1 fi if [ "$PLATFORM" = "both" ]; then PLATFORMS_JSON='["ios","android"]' else PLATFORMS_JSON=$(printf '["%s"]' "$PLATFORM") fi { echo "platform=$PLATFORM" echo "mode=$MODE" echo "ref=$REF" echo "platforms_json=$PLATFORMS_JSON" } >> "$GITHUB_OUTPUT"
build: needs: validate runs-on: ubuntu-latest environment: ${{ needs.validate.outputs.mode == 'release' && 'production' || 'build-debug' }} strategy: fail-fast: false matrix: platform: ${{ fromJSON(needs.validate.outputs.platforms_json) }} steps: - uses: actions/checkout@v4 with: ref: ${{ needs.validate.outputs.ref }}
- uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm'
- run: npm ci - run: npm run build - name: Sync native project env: PLATFORM: ${{ matrix.platform }} run: npx cap sync "$PLATFORM"
- name: Capgo Build 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 }} 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 }} PLATFORM: ${{ matrix.platform }} MODE: ${{ needs.validate.outputs.mode }} run: | npx @capgo/cli@latest build request com.example.app \ --platform "$PLATFORM" \ --build-mode "$MODE"2. Crea un token de GitHub
Sección titulada “2. Crea un token de GitHub”Crea un token de acceso personal con permisos granulares (o un token de instalación de GitHub App) con Contenido: Read and write en el repositorio (requerido para repository_dispatch). Guárdalo solo en tu backend de administración; nunca en el navegador.
3. Llama al webhook desde tu dashboard de administración
Sección titulada “3. Llama al webhook desde tu dashboard de administración”Tu backend (no el navegador del usuario final) debe enviar:
curl -X POST \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer $GITHUB_TOKEN" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/OWNER/REPO/dispatches \ -d '{ "event_type": "capgo-native-build", "client_payload": { "platform": "both", "mode": "release", "ref": "main", "requested_by": "admin@example.com" } }'| Campo | Propósito |
|---|---|
event_type | Debe coincidir types en el workflow (capgo-native-build) |
client_payload.platform | ios, android, o both |
client_payload.mode | debug o release |
client_payload.ref | Rama o tag a build (opcional) |
Conecta el mismo JSON POST a un botón en tu UI de admin (“Build native apps”). El dashboard solo necesita llegar al tus backend; el backend contiene el GITHUB_TOKEN.
Opción B — Proxy webhook ligero (cualquier host)
Sección titulada “Opción B — Proxy webhook ligero (cualquier host)”Si la herramienta de administración solo puede hacer POST a una URL que controles (Zapier, Make, Cloudflare Worker, ruta de Express), coloca un proxy corto delante de GitHub:
// Example Cloudflare Worker / Node handler (sketch)export default { async fetch(request, env) { if (request.method !== 'POST') { return new Response('Method not allowed', { status: 405 }) } if (request.headers.get('x-webhook-secret') !== env.WEBHOOK_SECRET) { return new Response('Unauthorized', { status: 401 }) } const body = await request.json().catch(() => ({})) const platform = body.platform || 'both' const mode = body.mode || 'release' const ref = body.ref || 'main' if (!['ios', 'android', 'both'].includes(platform)) { return new Response('Invalid platform', { status: 400 }) } if (!['debug', 'release'].includes(mode)) { return new Response('Invalid mode', { status: 400 }) } if (!/^(main|master|production|release\/[A-Za-z0-9._-]+|[0-9a-f]{40})$/.test(ref)) { return new Response('Ref not allowlisted', { status: 400 }) } const res = await fetch( `https://api.github.com/repos/${env.GITHUB_OWNER}/${env.GITHUB_REPO}/dispatches`, { method: 'POST', headers: { Accept: 'application/vnd.github+json', Authorization: `Bearer ${env.GITHUB_TOKEN}`, 'X-GitHub-Api-Version': '2022-11-28', }, body: JSON.stringify({ event_type: 'capgo-native-build', client_payload: { platform, mode, ref }, }), }, ) return new Response(res.status === 204 ? 'Build queued' : await res.text(), { status: res.status === 204 ? 200 : res.status, }) },}Luego configura el producto de administración:
| Configuración | Valor |
|---|---|
| URL | https://your-worker.example.com/native-build |
| Método | POST |
| Header | x-webhook-secret: <shared secret> |
| Body | { "platform": "both", "mode": "release" } |
Esta es la estructura habitual para conectar un webhook a un dashboard de administración: el dashboard guarda una URL y un secret; las credenciales de Capgo permanecen en GitHub Actions.
Disparador de GitLab Pipeline
Sección titulada “Disparador de GitLab Pipeline”GitLab ofrece tokens de disparo de pipeline que funcionan como objetivos de webhook nativos.
# .gitlab-ci.yml fragmentcapgo_native_webhook: stage: build script: - npm ci && npm run build - npx cap sync "${PLATFORM:-android}" - npx @capgo/cli@latest build request com.example.app --platform "${PLATFORM:-android}" --build-mode "${BUILD_MODE:-release}" rules: - if: '$CI_PIPELINE_SOURCE == "trigger"'Crea un token de disparo en Configuración → CI/CD → Tokens de activación de pipeline, y luego desde el backend de administración:
curl -X POST \ -F token=$GITLAB_TRIGGER_TOKEN \ -F ref=main \ -F "variables[PLATFORM]=android" \ -F "variables[BUILD_MODE]=release" \ https://gitlab.com/api/v4/projects/PROJECT_ID/trigger/pipelinePara ambas plataformas, lanza dos disparadores o expande el job en una matriz paralela, igual que en el ejemplo de GitHub.
Bitbucket y Azure
Sección titulada “Bitbucket y Azure”| Plataforma | Mecanismo de Webhook |
|---|---|
| Bitbucket | URL de trigger del pipeline o pipeline personalizado + app password POST |
| Azure DevOps | REST API de ejecución de pipeline con un PAT; usa el pipeline manual de Disparar desde la UI de CI |
El patrón es idéntico: admin → tu secret check → host API → job de Capgo Build.
Checklist de payload para herramientas de admin
Sección titulada “Checklist de payload para herramientas de admin”Al construir el formulario del dashboard, recolecta al menos:
- Plataforma — ios / android / ambos
- Modo — debug (QA) o release (store)
- Ref de Git — branch o tag a buildear
- Actor — email o user id para audit logs (pass through)
client_payload)
Opcional: tras la ejecución, que el CI notifique al admin API con la URL de descarga de --output-record / build last-output.
Seguridad
Sección titulada “Seguridad”- Autentica cada webhook (
x-webhook-secret, firma HMAC o mTLS). - Allowlist
platform,mode, yreftanto en el proxy como en el workflowvalidatejob — trataclient_payloadcomo entrada no confiable. - Pasa los valores aceptados mediante env vars / job outputs; no interpoles campos del payload en
run:scripts. - Mantén los tokens de GitHub/GitLab solo en el servidor.
- Es preferible usar tokens con alcance a un solo repositorio.
- Aplica rate-limit al proxy; los Native Build consumen minutos de build.
- Para lanzamientos enviados a la tienda, mapea
releasea un entorno GitHub protegido (como en el ejemplo) o requiere un flag de confirmación extra envalidate.