跳过内容

自动选择实时更新或native构建

大多数 Capacitor 发布都是 JavaScript-only,应该以 实时更新的形式发布。有些变更涉及本机 code,需要从 code Build Capgo Build本指南展示了如何让 GitHub Actions、GitLab CI 或任何其他 CI/CD 平台在每次推送时都选择正确的路径——无需人类介入。

Capgo 已经知道哪条路径是安全的。完成您的 Web 构建(在上传或请求本机构建之前),运行:

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

OTA 表示原生包与已发布的频道匹配。 native 表示插件、Capacitor版本或其他原生依赖发生了变化——仅通过OTA包无法安全地更新设备。

releaseType 比较 原生包元数据 (Capacitor/Cordova插件和版本)。它 查看 ios/, android/,或 capacitor.config.*,请在Git中先将这些路径屏蔽,然后使用 releaseType 以确保依赖项兼容性——以下示例都做到了这点。

查看 原生兼容性 查看完整规则和手册 bundle compatibility 提示

终端窗口
npx @capgo/cli@latest channel set production com.example.app --disable-auto-update metadata

管道应该如何工作

管道应该如何工作
  1. 按照正常流程构建Web资源
  2. 如果提交涉及 ios/, android/,或 capacitor.config.*强制使用原生路径
  3. 否则询问Capgo releaseType 是否提交是OTA安全的
  4. 如果 OTA,上传 --fail-on-incompatible 并且 --auto-min-update-version.
  5. If native, run Capgo Build, then upload the matching bundle with --auto-min-update-version 上传匹配的捆绑包 这样通道的本地元数据就会更新。 不要 使用 --fail-on-incompatible 为此基线上传 — 新的本地包应该有所不同。 请参阅 Native + OTA Channel Workflow 关于通道级FAQ

GitHub Actions

GitHub Actions

一个工作流程,控制原生路径,然后根据 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

替换 com.example.app 并将签名密钥连接起来,正如在 GitHub Actions for Capgo Build.

GitLab评估 rules 当管道创建时,分支内使用shell if 内部一个部署作业(或生成一个 动态子管道 如果您需要单独的本机矩阵作业):

.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

保存 CAPGO_TOKEN 并且 Capgo 将签名变量作为掩码/保护的CI/CD变量。

在任何地方都可以使用相同的三个步骤:

步骤命令
结果npx @capgo/cli@latest bundle releaseType APP_ID --channel production
OTA路径npx @capgo/cli@latest bundle upload APP_ID --channel production --fail-on-incompatible --auto-min-update-version
原生路径npx @capgo/cli@latest build request APP_ID --platform ios (或 android) --build-mode release

将shell退出/标准输出映射到您的平台的条件语句(或保留一个shell if,如GitLab上面那样:

  • Azure Pipelines — 从脚本步骤中设置一个输出变量,然后使用 condition: eq(variables['releaseType'], 'OTA')
  • Bitbucket Pipelines — 写 RELEASE_TYPE=…$BITBUCKET_PIPELINES_VARIABLES_PATHoutput-variables,并在后续步骤中使用 condition: state: RELEASE_TYPE == "OTA" (仅文件存档无法驱动 condition)
  • CircleCIwhen 在配置编译时间评估,因此使用一个运行时shell(或动态配置/继续),而不是工作区值在 if Jenkins when
  • live_update_dynamic_label_to — 将 stdout 捕获到环境变量中并使用 when { environment name: 'RELEASE_TYPE', value: 'OTA' }

路径过滤器(可选加速)

标题:路径过滤器(可选加速)

路径过滤器是一种成本优化,而不是Capgo检查的替代品。更倾向于排除仅用于文档的路径,而不是维护一个脆弱的白名单 —— 网络构建通常还依赖于 vite.config.*, tsconfig*.json, 和框架配置文件:

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

如果您使用白名单代替,请包含您的网络和本机构建读取的所有输入,而不仅仅是 src/package.json.

标题:CI 选择本机后

  1. Capgo Build produces signed binaries and can submit to TestFlight / Play (see 配置).
  2. 上传匹配的 JS 包裹文件 --auto-min-update-version (元数据策略) 以便渠道记录新的本机包裹 — 否则下一个仅 JS 提交仍然返回 native.
  3. 用户安装新二进制文件后,后续的 JavaScript-only 提交将返回 OTA 再次。
相关指南