Vai al contenuto

Avvia Native Build tramite Webhook

Capgo Build viene solitamente avviata da un laptop o da un job CI. I team che rilasciano da un dashboard admin, CMS o portale interno spesso desiderano un singolo webhook HTTP: premendo un tasto nella propria UI, parte un native build firmato. Questa guida mostra il pattern standard — una semplice chiamata HTTP autenticata verso il tuo host code, che esegue lo stesso workflow di Capgo Build che già utilizzi.

Non hai serve Capgo per esporre un “build webhook” pubblico. La tua CI ha già i segreti di firma; il compito del webhook è solo avviare quel job della CI in sicurezza.

  • Un workflow di build Capgo che funziona già da UI CI o al push (Azioni GitHub)
  • Permesso per creare un token GitHub fine-grained, un token trigger GitLab o equivalente
  • Un segreto condiviso che la tua dashboard admin invierà (header o body)
Sezione intitolata “Opzione A — GitHub repository_dispatch (consigliata)”

GitHub accetta una chiamata API autenticata che avvia un workflow in ascolto di repository_dispatch. Qualsiasi dashboard in grado di POST inviare JSON può attivarlo.

Valida il payload prima del checkout e prima di qualsiasi step che contenga segreti. Passa i valori accettati tramite job outputs / env vars — non interpolare mai client_payload direttamente in run: script (guida all'iniezione di script).

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

Crea un personal access token granulare (o un token di installazione GitHub App) con Contenuto: Read e write sul repository (necessario per repository_dispatch). Conservalo solo nel tuo backend admin — mai nel browser.

Il tuo backend (non il browser dell'utente finale) deve inviare:

Finestra del terminale
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"
}
}'
CampoScopo
event_typeDeve corrispondere types nel workflow (capgo-native-build)
client_payload.platformios, android, o both
client_payload.modedebug o release
client_payload.refBranch o tag da buildare (opzionale)

Collega lo stesso JSON POST a un pulsante nella tua UI admin (“Build native apps”). La dashboard deve solo raggiungere il tuo backend; il backend contiene GITHUB_TOKEN.

Opzione B — Webhook proxy minimale (qualsiasi host)

Sezione intitolata “Opzione B — Webhook proxy minimale (qualsiasi host)”

Se lo strumento admin può inviare solo una POST a un URL sotto il tuo controllo (Zapier, Make, Cloudflare Worker, route Express), inserisci un proxy minimale davanti a 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,
})
},
}

Configura quindi il prodotto admin:

ImpostazioneValore
URLhttps://your-worker.example.com/native-build
MetodoPOST
Headerx-webhook-secret: <shared secret>
Body{ "platform": "both", "mode": "release" }

Questa è la struttura tipica per collegare un webhook a una dashboard admin: la dashboard memorizza un URL e un secret; le credenziali Capgo restano in GitHub Actions.

GitLab espone token per il trigger della pipeline che sono target webhook nativi.

# .gitlab-ci.yml fragment
capgo_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 di trigger in Impostazioni → CI/CD → Token di trigger della pipeline, quindi dal backend di amministrazione:

Finestra del terminale
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/pipeline

Per entrambe le piattaforme, puoi attivare due trigger separati o espandere il job in una matrice parallela, proprio come nell'esempio GitHub.

PiattaformaMeccanismo webhook
BitbucketURL di trigger della pipeline o pipeline custom + app password POST
Azure DevOpsREST API per eseguire la pipeline con un PAT; usa la pipeline manuale da Trigger dalla UI CI

Il pattern è lo stesso: admin → tuo controllo segreto → host API → job di build Capgo.

Quando viene creato il form della dashboard, raccogli almeno:

  • Piattaforma — ios / android / entrambi
  • Modalità — debug (QA) o release (store)
  • Ref Git — branch o tag da buildare
  • Actor — email o user id per gli audit log (passa tramite client_payload)

Opzionale: al termine dell'esecuzione, fai in modo che la CI invii un post all'admin API con l'URL di download da --output-record / build last-output.

  • Autentica ogni webhook (x-webhook-secret, firma HMAC o mTLS).
  • Allowlist platform, mode, e ref sia nel proxy che nel workflow validate job — tratta client_payload come input non attendibile.
  • Passa i valori accettati tramite env vars / job outputs; non interpolare i campi del payload in run: script.
  • Mantieni i token GitHub/GitLab solo lato server.
  • Preferisci token con scope su un singolo repository.
  • Applica un rate-limit al proxy; i Native Build consumano minuti di build.
  • Per le release inviate agli store, mappa release su un Environment GitHub protetto (come nell'esempio) o richiedi un flag di conferma aggiuntivo verificato in validate.