Langsung ke konten

Trigger Native Build via Webhook

Capgo Build biasanya dimulai dari laptop atau job CI. Tim yang melakukan rilis dari dashboard admin, CMS, atau portal internal sering kali menginginkan satu Webhook HTTP: cukup tekan tombol di UI mereka sendiri, dan signed native build akan dimulai. Panduan ini menunjukkan pola standarnya — sebuah panggilan HTTP terautentikasi ke host code Anda, yang menjalankan workflow Capgo Build yang sama dengan yang sudah Anda gunakan.

Anda tidak perlu mengekspos “build webhook” publik di Capgo. CI Anda sudah memiliki signing secrets; tugas webhook hanyalah memulai job CI tersebut dengan aman.

  • Workflow Capgo Build yang sudah berjalan dari UI CI atau saat push (Aksi GitHub)
  • Izin untuk membuat fine-grained GitHub token, GitLab trigger token, atau setara
  • Shared secret yang akan dikirim oleh admin dashboard Anda (header atau body)
Bagian berjudul “Opsi A — GitHub repository_dispatch (direkomendasikan)”

GitHub menerima panggilan API terautentikasi yang memulai workflow untuk mendengarkan repository_dispatch. Dashboard apa pun yang bisa POST JSON dapat memicunya.

Validasi payload sebelum checkout dan sebelum langkah yang mengandung secret. Teruskan nilai yang diterima melalui job outputs / env vars — jangan pernah melakukan interpolasi client_payload secara langsung ke dalam run: script (panduan script injection).

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

Buat personal access token yang spesifik (atau token instalasi GitHub App) dengan Isi: Read and write pada repositori (diperlukan untuk repository_dispatch). Simpan hanya di backend admin Anda — jangan pernah di browser.

3. Panggil webhook dari dashboard admin Anda

Bagian berjudul “3. Panggil webhook dari admin dashboard Anda”

Backend Anda (bukan browser end-user) harus mengirim:

Jendela 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"
}
}'
KolomTujuan
event_typeHarus cocok types di workflow (capgo-native-build)
client_payload.platformios, android, atau both
client_payload.modedebug atau release
client_payload.refBranch atau tag untuk build (opsional)

Hubungkan JSON POST yang sama ke tombol di admin UI Anda (“Build native apps”). Dashboard hanya perlu mengakses URL backend; backend tersebut menyimpan GITHUB_TOKEN.

Opsi B — Tiny proxy webhook (host apa pun)

Bagian berjudul “Opsi B — Tiny proxy webhook (host apa pun)”

Jika admin tool hanya bisa melakukan POST ke URL yang Anda kontrol (Zapier, Make, Cloudflare Worker, Express route), pasang proxy singkat di depan 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,
})
},
}

Kemudian konfigurasi produk admin:

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

Ini adalah format umum untuk menghubungkan webhook ke dashboard admin: dashboard menyimpan satu URL dan satu secret; kredensial Capgo tetap berada di GitHub Actions.

GitLab menyediakan token trigger pipeline yang berfungsi sebagai target webhook.

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

Buat trigger token di Pengaturan → CI/CD → Token pemicu Pipeline, lalu dari admin backend:

Jendela 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

Untuk kedua platform, gunakan dua trigger atau perluas job menjadi parallel matrix seperti contoh GitHub.

PlatformMekanisme Webhook
BitbucketURL trigger pipeline atau custom pipeline + app password POST
Azure DevOpsREST API run pipeline dengan PAT; gunakan manual pipeline dari Trigger dari UI CI

Polanya sama: admin → secret check Anda → host API → Capgo Build job.

Saat membuat form dashboard, kumpulkan minimal:

  • Platform — ios / android / keduanya
  • Mode — debug (QA) atau release (store)
  • Ref Git — branch atau tag yang akan di-build
  • Actor — email atau user id untuk audit log (teruskan client_payload)

Opsional: setelah run selesai, minta CI mengirim balik ke admin API dengan URL download dari --output-record / build last-output.

  • Autentikasi setiap webhook (x-webhook-secret, tanda tangan HMAC, atau mTLS).
  • Allowlist platform, mode, dan ref baik di proxy maupun di workflow validate job — perlakukan client_payload sebagai input yang tidak terpercaya.
  • Teruskan nilai yang diterima melalui env vars / job outputs; jangan interpolasi field payload ke dalam run: scripts.
  • Simpan token GitHub/GitLab hanya di sisi server.
  • Utamakan token yang cakupannya hanya satu repositori.
  • Beri rate limit pada proxy; native build memakan build minutes.
  • Untuk rilis yang di-submit ke store, petakan release ke Environment GitHub yang terlindungi (seperti pada contoh) atau wajibkan flag konfirmasi tambahan yang dicentang di validate.