跳转至正文
CI/CD

使用 GitHub actions 实现 Capacitor Android 自动化构建

如何用 fastlane 和 GitHub Actions 在 5 分钟内为你的 Android Capacitor 应用搭建 CI/CD pipeline

使用 GitHub actions 实现 Capacitor Android 自动化构建

为 Capacitor 应用配置 CI/CD 可能既复杂又耗时。你需要了解这些:

我们现在推荐使用 配合 Capgo CLI 使用 Capgo Build 用于 Native Capacitor 构建。 本 Fastlane 指南旨在帮助维护现有 GitHub Actions pipeline 的团队;但对于新的 Android 构建,建议使用 Capgo CLI,这样你就无需亲自维护 Fastlane、Gradle runner、keystore 以及 upload 脚本。

前提条件

在开始之前,你需要准备:

  • 具有管理员权限的 GitHub 账号
  • 已通过正确签名发布到 Google Play Store 的应用
  • Android 签名密钥和 keystore 文件
  • 已启用 Play Store API 的 Google Cloud Console 项目
  • 具有相应权限的服务账号 (Service account)
  • 了解 GitHub Actions workflow
  • 熟悉 Fastlane 配置
  • 用于维护和调试 pipeline 的时间

Capgo 通过 Capgo 进行 CI/CD 构建

省去 Fastlane、Gradle runner、keystore 和上传脚本的维护。 Capgo 构建 从你现有的 CI/CD 流水线运行已签名的原生 Android 构建:

  • 适配你的流水线:在 Web 构建完成后,通过 GitHub Actions、GitLab CI、Jenkins 或本地脚本触发 Capgo Build,并 npx cap sync.
  • 通过 CI secrets 签名:将 Android keystores、key aliases、密码以及 Play Console 服务账号 JSON 保存在你自己的 CI secrets 中。
  • 无需维护原生 runner:Capgo Build 提供持续维护的 Android 构建环境,因此你无需管理 SDK 镜像、Gradle 缓存问题或 Fastlane lanes。
  • 产物与提交:下载已签名的产物用于 QA,或通过 Capgo CLI 提交发布构建。

定价

  • Capgo 套餐 $12/月起
  • 包含 OTA 更新和每月约 15 次 Native Build
  • 额外的构建分钟数通过 credits 按分钟计费

在 CI/CD 中配置 Capgo Build

手动配置指南

你需要做的是:

GitHub Actions 定价

GitHub Action 价格

GitHub Actions 根据你的仓库类型提供免费分钟数:

  • 公开仓库:2,000 分钟/月
  • 私有仓库:2,000 分钟/月(Linux runners)

对于私有项目,费用约为 $0.008/分钟。一次典型构建耗时 3-5 分钟。

手动配置步骤

  1. 创建 Android Keystore
  2. 配置 Google Play 服务账号
  3. 配置 Fastlane
  4. 配置 GitHub secrets
  5. 创建 GitHub Actions 工作流

1. 创建 Android Keystore

在签名并发布 Android 应用之前,你需要创建一个 keystore 文件。这是一次性设置。

使用 keytool 生成 Keystore

在终端中运行此命令:

keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

系统将提示你输入:

  • Keystore 密码:请设置一个强密码(之后会用到 KEYSTORE_STORE_PASSWORD)
  • Key 密码:请设置一个强密码(之后会用到 KEYSTORE_KEY_PASSWORD)
  • 你的姓名、组织等:填写你的详细信息

重要注意事项

  • 请妥善保存这些值:

    • Keystore 文件路径(例如 my-release-key.keystore)
    • Key 别名(例如 my-key-alias)— 之后会用到 KEYSTORE_KEY_ALIAS
    • Keystore 密码 — 之后会用到 KEYSTORE_STORE_PASSWORD
    • 密钥密码 - 你需要将其用作 KEYSTORE_KEY_PASSWORD
  • 备份 keystore 文件:如果丢失,你将无法更新已发布的 App

  • 严格保密:切勿将 keystore 文件提交到 git

  • 妥善保存:在安全位置保留多份备份

备选方案:使用现有 Keystore

如果你已经发布过 App,就必须使用最初使用的同一个 keystore。你可以在以下位置找到它:

  • 在你首次构建 App 的本地机器上
  • 在 Play Console → Setup → App signing 中(如果你使用的是 Google Play App Signing)

2. 配置 Google Play 服务账号

若要允许 GitHub Actions 将构建版本上传至 Google Play,您需要一个服务账号。

步骤 2.1:创建 Google Cloud 项目

  1. 前往 Google Cloud Console
  2. 创建新项目或选择现有项目
  3. 记下项目 ID

步骤 2.2:启用 Google Play Developer API

  1. 在 Google Cloud Console 中,前往 API 与服务 → Library
  2. 搜索 “Google Play Android Developer API”
  3. 点击 启用

步骤 2.3:创建服务账号

  1. 前往 IAM 和管理 → 服务账号
  2. 点击 创建服务账号
  3. 输入详细信息:
    • 名称: github-actions-uploader
    • 描述:“用于 GitHub Actions 上传 build 的服务账号”
  4. 点击 创建并继续
  5. 暂时跳过角色分配(点击 继续,然后 完成)

步骤 2.4:创建服务账号密钥

  1. 点击新创建的服务账号
  2. 前往 密钥 选项卡
  3. 点击 添加密钥 → 创建新密钥
  4. 选择 JSON 格式
  5. 点击 创建
  6. 将下载一个 JSON 文件 - 请妥善保存,后续会用到

步骤 2.5:在 Play Console 中授予访问权限

  1. 前往 Google Play Console
  2. 前往 配置 → API 访问权限
  3. 在 服务账号,点击 授予访问权限 为您的服务账号
  4. 在 应用权限 标签页,添加您的应用
  5. 在 账号权限 请授予以下权限:
    • 查看应用信息并下载批量报告(只读)
    • 创建、编辑和删除草稿应用
    • 将应用发布至测试轨道
    • 将应用发布至正式版、排除版及其他轨道
  6. 点击 邀请用户
  7. 点击 发送邀请

步骤 2.6:验证 JSON Key

下载的 JSON 文件应如下所示:

{
  "type": "service_account",
  "project_id": "your-project-id",
  "private_key_id": "...",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
  "client_email": "github-actions-uploader@your-project-id.iam.gserviceaccount.com",
  "client_id": "...",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "..."
}

你将在 GitHub secrets 设置步骤中将其转换为 base64。

3. 配置 Fastlane

创建一个 fastlane 项目根目录下的文件夹,并添加一个 Fastfile 内容如下:

default_platform(:android)

KEYSTORE_KEY_ALIAS = ENV["KEYSTORE_KEY_ALIAS"]
KEYSTORE_KEY_PASSWORD = ENV["KEYSTORE_KEY_PASSWORD"]
KEYSTORE_STORE_PASSWORD = ENV["KEYSTORE_STORE_PASSWORD"]

platform :android do
    desc "Deploy a beta version to the Google Play"
    private_lane :verify_changelog_exists do |version_code: |
      changelog_path = "android/metadata/en-US/changelogs/#{version_code}.txt"
      UI.user_error!("Missing changelog file at #{changelog_path}") unless File.exist?(changelog_path)
      UI.message("Changelog exists for version code #{version_code}")
    end

    private_lane :verify_upload_to_staging do |version_name: |
      UI.message "Skipping staging verification step"
    end
    
    lane :beta do
        keystore_path = "#{Dir.tmpdir}/build_keystore.keystore"
        File.write(keystore_path, Base64.decode64(ENV['ANDROID_KEYSTORE_FILE']))
        json_key_data = Base64.decode64(ENV['PLAY_CONFIG_JSON'])
        
        # Get previous build number and increment
        previous_build_number = google_play_track_version_codes(
            package_name: ENV['DEVELOPER_PACKAGE_NAME'],
            track: "internal",
            json_key_data: json_key_data,
        )[0]
        current_build_number = previous_build_number + 1
        sh("export NEW_BUILD_NUMBER=#{current_build_number}")
        
        # Build the app
        gradle(
          task: "clean bundleRelease",
          project_dir: 'android/',
          print_command: false,
          properties: {
            "android.injected.signing.store.file" => "#{keystore_path}",
            "android.injected.signing.store.password" => "#{KEYSTORE_STORE_PASSWORD}",
            "android.injected.signing.key.alias" => "#{KEYSTORE_KEY_ALIAS}",
            "android.injected.signing.key.password" => "#{KEYSTORE_KEY_PASSWORD}",
            'versionCode' => current_build_number
          })
        
        # Upload to Play Store
        upload_to_play_store(
            package_name: ENV['DEVELOPER_PACKAGE_NAME'],
            json_key_data: json_key_data,
            track: 'internal',
            release_status: 'completed',
            skip_upload_metadata: true,
            skip_upload_changelogs: true,
            skip_upload_images: true,
            skip_upload_screenshots: true,
        )
    end
end

4. 配置 GitHub Secrets

现在你已经有 keystore 和 service account JSON,需要将它们安全地存储在 GitHub 中。

步骤 4.1:访问 GitHub Secrets

  1. 前往 GitHub 上的代码仓库
  2. 点击 设置 → Secrets 和变量 → 操作
  3. 点击 新建 Repository Secret

步骤 4.2:添加必要的 Secrets

请依次添加以下 Secrets:

PLAY_CONFIG_JSON

  1. 获取你在步骤 2.4 中下载的服务账号 JSON 文件
  2. 将其转换为 base64 格式:

在 macOS/Linux 上:

base64 service_account_key.json | pbcopy

在 Windows (PowerShell) 上:

[Convert]::ToBase64String([IO.File]::ReadAllBytes("service_account_key.json")) | Set-Clipboard
  1. 创建一个名为以下名称的新 Secret PLAY_CONFIG_JSON 并粘贴 base64 字符串

ANDROID_KEYSTORE_FILE

  1. 将 keystore 转换为 base64:

在 macOS/Linux 上:

base64 my-release-key.keystore | pbcopy

在 Windows (PowerShell) 上:

[Convert]::ToBase64String([IO.File]::ReadAllBytes("my-release-key.keystore")) | Set-Clipboard
  1. 创建一个名为新的 secret ANDROID_KEYSTORE_FILE 并粘贴 base64 字符串

KEYSTORE_KEY_ALIAS

创建一个新的 Secret,填入生成 keystore 时使用的 key alias(例如: my-key-alias)

KEYSTORE_KEY_PASSWORD

创建一个新的 Secret,填入生成 keystore 时设置的 key password

KEYSTORE_STORE_PASSWORD

创建一个新的 Secret,填入生成 keystore 时设置的 keystore password

开发者包名

使用应用的包名创建一个新的 Secret(例如: com.example.app)

你可以在以下位置找到包名: android/app/build.gradle 在……下 applicationId

步骤 4.3:验证所有 Secret

请确保已配置好以下 6 个 Secret:

  • ✅ PLAY_CONFIG_JSON
  • ✅ ANDROID_KEYSTORE_FILE
  • ✅ KEYSTORE_KEY_ALIAS
  • ✅ KEYSTORE_KEY_PASSWORD
  • ✅ KEYSTORE_STORE_PASSWORD
  • ✅ DEVELOPER_PACKAGE_NAME

5. 创建 GitHub Actions Workflow

创建 .github/workflows/build-upload-android.yml:

name: Build and Deploy Android App

on:
  push:
    tags:
      - '*'

jobs:
  build_android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      
      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: npm
          
      - name: Install dependencies
        run: npm ci
        
      - name: Cache Gradle
        uses: actions/cache@v5
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            ${{ runner.os }}-gradle-
            
      - name: Build app
        run: npm run build
        
      - name: Sync Capacitor
        run: npx cap sync
        
      - name: Setup Java
        uses: actions/setup-node@v5
        with:
            distribution: 'zulu'
            java-version: '17'
            
      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.0'
          bundler-cache: true
          
      - name: Run Fastlane
        uses: maierj/fastlane-action@v3.1.0
        env:
          PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }}
          ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }}
          DEVELOPER_PACKAGE_NAME: ${{ secrets.DEVELOPER_PACKAGE_NAME }}
          KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }}
          KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
          KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }}
        with:
          lane: android beta
          
      - name: Upload artifact
        uses: actions/upload-artifact@v2
        with:
          name: android-release
          path: ./android/app/build/outputs/bundle/release/app-release.aab
          retention-days: 10

工作原理

  1. 创建 Git tag 以触发工作流
  2. GitHub Actions 构建您的应用
  3. Fastlane 将其上传至 Google Play 测试渠道
  4. 您的应用将自动完成更新

构建耗时与成本

  • 构建时间:3-5 分钟
  • 私有仓库成本:每次构建约 $0.04
  • 开源项目免费使用

CI/CD 配置指南

其他 CI/CD 平台

Live Updates 与部署

资源

继续使用 GitHub actions 自动完成 Capacitor Android build

如果你正在使用 使用 GitHub actions 实现 Capacitor Android 自动化构建 规划 CI/CD 自动化,并将其与 Capgo CI/CD 用于 Capgo CI/CD 中的产品工作流, Capgo Native Build 用于 Capgo Native Builds 中的产品工作流, Capgo 集成 用于 Capgo 集成中的产品工作流, CI/CD 集成 了解 CI/CD 集成的实现细节,以及 GitHub Actions 集成 有关 GitHub Actions 集成的实现细节。

为 Capacitor 应用提供 Live Updates

当 Web 层出现线上 Bug 时,通过 Capgo 发布修复,而不用等 App Store 审核好几天。用户会在后台收到更新,原生变更则仍走正常审核流程。

博客最新动态

Capgo 为你提供打造真正专业的移动应用所需的最有价值的洞察。