Zum Inhalt springen

Automatische Wahl zwischen Live Update oder Native Build

Die meisten Capacitor Releases bestehen nur aus JavaScript und sollten als live update. Einige Änderungen betreffen nativen code und erfordern ein neues Binary von Capgo Build. Dieser Guide zeigt, wie GitHub Actions, GitLab CI oder jede andere CI/CD-Plattform bei jedem Push den richtigen Pfad wählt – ganz ohne manuelles Eingreifen.

Capgo weiß bereits, welcher Pfad sicher ist. Führe nach deinem Web-Build (und vor dem Upload oder der Anfrage eines Native Build) folgenden Befehl aus:

Terminalfenster
npx @capgo/cli@latest bundle releaseType com.example.app --channel production
# → OTA ship with bundle upload
# → native ship with Capgo Build

OTA bedeutet, dass die nativen Packages mit dem übereinstimmen, was bereits live auf dem Channel ist. native bedeutet, dass sich ein Plugin, die Capacitor-Version oder eine andere native Dependency geändert hat – ein Over-the-Air-Bundle allein kann diese Geräte nicht sicher aktualisieren.

releaseType vergleicht Native Package-Metadaten (Capacitor/Cordova-Plugins und Versionen). Es es nicht erfasst jede Änderung unter ios/, android/, oder capacitor.config.*. Sperre diese Pfade zuerst in Git und nutze dann releaseType für die Dependency-Kompatibilität – die folgenden Beispiele zeigen beides.

Siehe Native-Kompatibilität für die vollständigen Regeln und die manuelle bundle compatibility Tabelle.

  • Capgo App registriert und ein Capgo API Key ein in den CI-Secrets als CAPGO_TOKEN
  • Live Updates Upload funktioniert (bundle upload) — siehe CI/CD-Integration
  • Capgo Build-Credentials in der CI, wenn du Native Jobs erwartest — siehe GitHub Aktionen oder Credentials
  • Ein bereits existierender Channel, der der Production entspricht (Beispiele nutzen production)
  • Channel auf dem metadata Strategie, damit jeder Upload --auto-min-update-version (einmalig):
Terminalfenster
npx @capgo/cli@latest channel set production com.example.app --disable-auto-update metadata
  1. Web-Assets wie gewohnt builden.
  2. Wenn der Commit Änderungen an ios/, android/, oder capacitor.config.*erfordert, erzwinge den Native Build-Pfad.
  3. Andernfalls frage Capgo, releaseType ob der Commit OTA-safe ist.
  4. Wenn OTAlade stattdessen mit --fail-on-incompatible und --auto-min-update-version.
  5. Wenn nativeführe den Capgo Build aus und lade das passende Bundle mit --auto-min-update-version so die native Metadaten des Channels aktualisiert werden. Do es nicht mit --fail-on-incompatible für diesen Baseline-Upload – die neuen Native Packages sollen sich unterscheiden. Siehe Native + OTA Channel Workflow für die Channel-level FAQs.

Ein Workflow, der native Pfade steuert und dann verzweigt auf releaseType:

.github/workflows/capgo-release.yml
name: Capgo Release
on:
push:
branches: [main]
jobs:
decide:
runs-on: ubuntu-latest
outputs:
release_type: ${{ steps.verdict.outputs.type }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Decide OTA vs native
id: verdict
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
run: |
BEFORE="${{ github.event.before }}"
if [ -z "$BEFORE" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then
BEFORE="$(git rev-parse HEAD~1 2>/dev/null || echo '')"
fi
if [ -z "$BEFORE" ] || git diff --name-only "$BEFORE" "${{ github.sha }}" \
| grep -qE '^(ios/|android/|capacitor\.config\.)'; then
TYPE=native
echo "Native path/config changed (or no prior commit) — forcing native"
else
TYPE=$(npx @capgo/cli@latest bundle releaseType com.example.app --channel production | tr -d '[:space:]')
fi
echo "type=$TYPE" >> "$GITHUB_OUTPUT"
echo "Capgo release type: $TYPE"
live_update:
needs: decide
if: needs.decide.outputs.release_type == 'OTA'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Upload live update
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
run: |
npx @capgo/cli@latest bundle upload com.example.app \
--channel production \
--fail-on-incompatible \
--auto-min-update-version
native_build:
needs: decide
if: needs.decide.outputs.release_type == 'native'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform: [ios, android]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'npm'
- run: npm ci
- run: npm run build
- run: npx cap sync ${{ matrix.platform }}
- name: Capgo Build ${{ matrix.platform }}
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 }}
run: |
npx @capgo/cli@latest build request com.example.app \
--platform ${{ matrix.platform }} \
--build-mode release
native_bundle:
needs: [decide, native_build]
if: needs.decide.outputs.release_type == 'native'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Upload bundle for new native baseline
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
run: |
# Channel must already be on metadata (see Prerequisites above)
npx @capgo/cli@latest bundle upload com.example.app \
--channel production \
--auto-min-update-version

Ersetze com.example.app und die Signing Secrets einbindet, wie in GitHub Actions für den Capgo Build beschrieben.

GitLab wertet rules aus, wenn die Pipeline erstellt wird, also ein Branch mit einer Shell if innerhalb eines Deploy-Jobs (oder erstelle eine dynamische Child-Pipeline falls du separate Native-Matrix-Jobs benötigst):

.gitlab-ci.yml
image: node:24
stages:
- build
- deploy
variables:
APP_ID: com.example.app
CHANNEL: production
build_web:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
- node_modules/
expire_in: 1 hour
only:
- main
deploy:
stage: deploy
needs: [build_web]
script:
- |
BEFORE="${CI_COMMIT_BEFORE_SHA:-}"
if [ -z "$BEFORE" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then
BEFORE="$(git rev-parse HEAD~1 2>/dev/null || echo '')"
fi
if [ -z "$BEFORE" ] || git diff --name-only "$BEFORE" "$CI_COMMIT_SHA" \
| grep -qE '^(ios/|android/|capacitor\.config\.)'; then
TYPE=native
else
TYPE=$(npx @capgo/cli@latest bundle releaseType "$APP_ID" --channel "$CHANNEL" | tr -d '[:space:]')
fi
echo "Capgo release type: $TYPE"
if [ "$TYPE" = "OTA" ]; then
npx @capgo/cli@latest bundle upload "$APP_ID" \
--channel "$CHANNEL" \
--fail-on-incompatible \
--auto-min-update-version
elif [ "$TYPE" = "native" ]; then
npx cap sync
npx @capgo/cli@latest build request "$APP_ID" --platform ios --build-mode release
npx @capgo/cli@latest build request "$APP_ID" --platform android --build-mode release
npx @capgo/cli@latest bundle upload "$APP_ID" \
--channel "$CHANNEL" \
--auto-min-update-version
else
echo "Unexpected release type: $TYPE" >&2
exit 1
fi
only:
- main

Speichere CAPGO_TOKEN und Capgo Build-Signing-Variablen als maskierte/geschützte CI/CD-Variablen.

Die gleichen drei Schritte funktionieren überall:

SchrittBefehl
Fazitnpx @capgo/cli@latest bundle releaseType APP_ID --channel production
OTA-Pfadnpx @capgo/cli@latest bundle upload APP_ID --channel production --fail-on-incompatible --auto-min-update-version
Native-Pfadnpx @capgo/cli@latest build request APP_ID --platform ios (oder android) --build-mode release

Mappe den Shell-Exit / stdout auf die Conditionals deiner Plattform (oder nutze einen einzelnen Job mit einer Shell if, wie oben bei GitLab):

  • Azure Pipelines — setze eine Output-Variable in einem Script-Step und nutze sie dann condition: eq(variables['releaseType'], 'OTA')
  • Bitbucket Pipelines — schreibe RELEASE_TYPE=… zu $BITBUCKET_PIPELINES_VARIABLES_PATH, deklariere sie unter output-variables, und später Branch-Steps mit condition: state: RELEASE_TYPE == "OTA" (nur Datei-Artefakte können keinen condition)
  • CircleCI — when wird zur config-compile Zeit ausgewertet, also Branch mit einer Runtime-Shell if (oder dynamischer Config / Continuation), kein Workspace-Wert in when
  • Jenkins — stdout in einer Env-Var erfassen und nutzen when { environment name: 'RELEASE_TYPE', value: 'OTA' }

Path Filters dienen der Kostenoptimierung, nicht als Ersatz für den Capgo Check. Es ist besser, reine Docs-Pfade auszuschließen, statt eine fehleranfällige Allowlist zu pflegen — Web-Builds hängen oft auch von vite.config.*, tsconfig*.json, und Framework-Config-Dateien ab:

on:
push:
branches: [main]
paths-ignore:
- '**.md'
- 'docs/**'
- '.github/**'

Wenn du stattdessen eine Allowlist nutzt, musst du alle Inputs einbeziehen, die deine Web- und Native Builds lesen, nicht nur src/ und package.json.

Wenn die CI Native wählt:

  1. Capgo Build erstellt signierte Binaries und kann diese an TestFlight / Play senden (siehe Konfiguration).
  2. Lade das passende JS-Bundle mit --auto-min-update-version (Metadata-Strategie) hoch, damit der Channel die neuen Native-Packages registriert – andernfalls liefert der nächste JS-only Commit weiterhin native.
  3. Sobald User die neue Binary installiert haben, kehren spätere JavaScript-only Commits zu OTA erneut aus.