自动选择 Live Update 或 Native Build
复制包含安装步骤和该插件完整 Markdown 指南的配置 prompt。
大多数 Capacitor 版本仅包含 JavaScript,应当以 live update. 某些更改涉及原生 code,需要从 Capgo 构建。本指南将介绍如何让 GitHub Actions、GitLab CI 或任何其他 CI/CD 平台在每次推送时自动选择正确路径,无需人工干预。
决策
“决策过程”章节Capgo 已经知道哪条路径是安全的。在完成 Web build 之后(且在 upload 或请求 Native Build 之前),请运行:
npx @capgo/cli@latest bundle releaseType com.example.app --channel production# → OTA ship with bundle upload# → native ship with Capgo BuildOTA 意味着原生 package 与当前 channel 已发布的版本一致。 native 意味着 plugin、Capacitor 版本或其他原生依赖项发生了变化 —— 仅靠 OTA bundle 无法安全地更新这些设备。
releaseType 用于比较 原生包元数据 (Capacitor/Cordova 插件及其版本)。它会 不会 查看以下路径下的所有编辑 ios/, android/,或 capacitor.config.*。先在 git 中对这些路径进行限制,然后使用 releaseType 来确保依赖兼容性 —— 下面的示例均包含这两项。
查看 原生兼容性 查看完整规则和手动 bundle compatibility 表格。
前提条件
“前提条件”章节- 已注册 Capgo 应用并已在 Capgo API 密钥 中将 CI secrets 设置为
CAPGO_TOKEN - ,Live Updates upload 运行正常(
bundle upload)—— 详见 CI/CD 集成 - 。如果需要执行 native 任务,请在 CI 中配置 Capgo Build 凭据 —— 详见 GitHub 操作 或 凭据
- 一个已存在且与生产环境匹配的 channel(示例中使用
production) - 上的 channel
metadata策略,以便每次 upload 都能携带--auto-min-update-version(仅限一次):
npx @capgo/cli@latest channel set production com.example.app --disable-auto-update metadataPipeline 应如何工作
标题为“Pipeline 应如何工作”的部分flowchart TD A[Push / merge] --> B[Install + web build] B --> C["bundle releaseType"] C -->|OTA| D["bundle upload"] C -->|native| E["build request iOS + Android"] E --> F[Store / TestFlight / Play]
- 照常构建 web assets。
- 如果 commit 涉及
ios/,android/,或capacitor.config.*,请强制使用 Native 路径。 - 否则请询问 Capgo
releaseType该 commit 是否符合 OTA 安全标准。 - 如果
OTA,使用--fail-on-incompatible以及--auto-min-update-version. - 如果
native,运行 Capgo Build,然后使用匹配的 bundle 进行 upload,--auto-min-update-version以便推进该 channel 的 native 元数据。执行 不会 使用--fail-on-incompatible对于该基准上传 —— 新的 Native packages 应当有所不同。请参阅 Native + OTA Channel 工作流 查看频道层级的常见问题解答。
GitHub 操作
标题为“GitHub 操作”的章节一种工作流可以管控 Native 路径,然后基于 releaseType:
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 用于 Capgo Build 的操作.
GitLab CI
标题为 “GitLab CI” 的章节GitLab 会在 rules 创建 pipeline 时进行评估,因此带有 shell 的分支 if 在一个部署任务中(或生成一个 动态子流水线 如果你需要独立的 Native Build 矩阵任务):
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 Build 签名变量,并将其设为 Masked/Protected 的 CI/CD 变量。
其他 CI 平台
标题为 “Other CI Platforms” 的章节同样的三个步骤适用于任何环境:
| 步骤 | 命令 |
|---|---|
| 结论 | 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 |
| Native 路径 | npx @capgo/cli@latest build request APP_ID --platform ios (或 android) --build-mode release |
将 shell 的退出码 / stdout 映射到平台的条件判断中(或保留一个带 shell 的单一 job if,就像上面的 GitLab 那样):
- Azure Pipelines — 在脚本步骤中设置输出变量,然后使用
condition: eq(variables['releaseType'], 'OTA') - Bitbucket Pipelines — 写入
RELEASE_TYPE=…改为$BITBUCKET_PIPELINES_VARIABLES_PATH,然后在下面声明它output-variables,并随后通过以下方式进行分支处理:condition: state: RELEASE_TYPE == "OTA"(仅凭文件产物无法驱动condition) - CircleCI —
when是在配置编译时评估的,因此请使用运行时 shell 进行分支判断if(或动态配置/延续),而不是使用 workspace 中的值when - Jenkins — 将 stdout 捕获到环境变量中并使用
when { environment name: 'RELEASE_TYPE', value: 'OTA' }
路径过滤(可选加速)
“路径过滤器 (可选加速)”章节路径过滤器是一种成本优化手段,不能替代 Capgo 检查。建议优先排除仅包含文档的路径,而不是维护一个脆弱的白名单 —— Web 构建通常还依赖于 vite.config.*, tsconfig*.json,以及框架配置文件:
on: push: branches: [main] paths-ignore: - '**.md' - 'docs/**' - '.github/**'如果您改用白名单,请包含 Web 和 Native Build 读取的所有输入,而不仅仅是 src/ 以及 package.json.
Native 判定后
“Native Verdict 之后”章节当 CI 选择 Native 时:
- Capgo Build 会生成已签名的二进制文件,并可提交至 TestFlight / Play(参见 配置).
- 使用以下方式上传匹配的 JS bundle
--auto-min-update-version(metadata 策略)以便 Channel 记录新的 Native 包 —— 否则下次仅包含 JS 的 commit 仍会返回native. - 一旦用户安装了新的二进制文件,后续仅包含 JavaScript 的 commit 将返回至
OTA再次尝试。