Aller au contenu

Déclencher des Native Build via webhook

Capgo Le build est normalement lancé depuis un ordinateur ou un job CI. Les équipes qui déploient depuis un dashboard admin, un CMS ou un portail interne souhaitent souvent un seul webhook HTTP: appuyer sur un bouton dans leur propre interface, et un build natif signé démarre. Ce guide présente le modèle standard — un appel HTTP authentifié léger vers votre hôte code, qui exécute le même workflow Capgo Build que vous utilisez déjà.

Vous pas avez besoin de Capgo pour exposer un « build webhook » public. Votre CI possède déjà les secrets de signature ; le seul rôle du webhook est de lancer ce job CI en toute sécurité.

  • Un workflow Capgo Build qui fonctionne déjà depuis l'interface CI ou lors d'un push (GitHub Actions GitHub)
  • Permission de créer un token GitHub granulaire, un token de déclenchement GitLab ou un équivalent
  • Un secret partagé que votre dashboard admin enverra (header ou body)
Section intitulée « Option A — GitHub repository_dispatch (recommandé) »

GitHub accepte un appel API authentifié qui lance un workflow à l'écoute de repository_dispatch. Tout dashboard capable de POST envoyer du JSON peut l'utiliser.

Valider le payload avant checkout et avant toute étape contenant des secrets. Passez les valeurs acceptées via les outputs de job / variables d'env — n'interpolez jamais client_payload directement dans les run: scripts (guide sur l'injection de 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"

Créez un token d'accès personnel granulaire (ou un token d'installation GitHub App) avec Contenu : Read and write sur le dépôt (requis pour repository_dispatch). Stockez-l’uniquement dans votre backend admin — jamais dans le navigateur.

3. Appeler le webhook depuis votre dashboard admin

Section intitulée « 3. Appeler le webhook depuis votre dashboard admin »

Votre backend (et non le navigateur de l'utilisateur final) doit envoyer :

Fenêtre de terminal
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"
}
}'
ChampObjectif
event_typeDoit correspondre types dans le workflow (capgo-native-build)
client_payload.platformios, android, ou both
client_payload.modedebug ou release
client_payload.refBranche ou tag à build (optionnel)

Reliez le même JSON POST à un bouton de votre interface admin (« Build native apps »). Le dashboard doit seulement atteindre le votre backend ; le backend contient GITHUB_TOKEN.

Option B — Webhook proxy minimal (n'importe quel hôte)

Section intitulée « Option B — Webhook proxy minimal (n'importe quel hôte) »

Si l'outil d'administration ne peut faire que des POST vers une URL que vous contrôlez (Zapier, Make, Cloudflare Worker, route Express), placez un petit proxy devant 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,
})
},
}

Configurez ensuite l'outil d'administration :

ParamètreValeur
URLhttps://your-worker.example.com/native-build
MéthodePOST
En-têtex-webhook-secret: <shared secret>
Corps{ "platform": "both", "mode": "release" }

C'est la structure habituelle pour connecter un webhook à un dashboard d'administration : le dashboard stocke une URL et un secret ; les identifiants Capgo restent dans GitHub Actions.

GitLab expose des tokens de déclenchement de pipeline qui sont des cibles de webhook naturelles.

# .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"'

Créez un token de déclenchement sous Paramètres → CI/CD → Tokens de déclenchement de pipeline, puis depuis le backend d'administration :

Fenêtre de terminal
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

Pour les deux plateformes, déclenchez soit deux triggers, soit étendez le job en une matrice parallèle, comme dans l'exemple GitHub.

PlateformeMécanisme de webhook
BitbucketURL de déclenchement du pipeline or custom pipeline + app password POST
Azure DevOpsExécution de pipeline via l'API REST API avec un PAT ; utilisez le pipeline manuel de Déclencher depuis l'UI CI

Le pattern est identique : admin → votre secret → hôte API → job de Capgo Build.

Lors de la création du formulaire du dashboard, collectez au moins :

  • Plateforme — ios / android / les deux
  • Mode — debug (QA) ou release (store)
  • Ref Git — branche ou tag à compiler
  • Acteur — e-mail ou ID utilisateur pour les logs d'audit (transmis tel quel client_payload)

Optionnel : après l'exécution, demandez à la CI de renvoyer une requête à l'admin API avec l'URL de téléchargement de --output-record / build last-output.

  • Authentifiez chaque webhook (x-webhook-secret, signature HMAC ou mTLS).
  • Allowlist platform, mode, et ref dans le proxy et le job de validate workflow — traitez client_payload comme une entrée non fiable.
  • Passez les valeurs acceptées via des variables d'env / sorties de job ; n'interpolez pas les champs du payload dans les run: scripts.
  • Gardez les tokens GitHub/GitLab uniquement côté serveur.
  • Privilégiez les tokens limités à un seul dépôt.
  • Limitez le débit du proxy ; les builds natifs consomment des minutes de build.
  • Pour les releases soumises aux stores, mappez release vers un environnement GitHub protégé (comme dans l'exemple) ou exigez un flag de confirmation supplémentaire vérifié dans validate.