跳过主要内容
CI/CD

自动Capacitor Android构建与GitLab

如何在5分钟内使用fastlane和GitLab为您的Android Ionic应用设置CI/CD管道

文章来源

马丁·多纳迪厄

作者

瓦莱里亚

审阅者

乔丹

编辑

自动Capacitor Android构建与GitLab

GitLab CI自动化安卓构建

设置CI/CD:Capacitor应用的设置可能会很复杂和耗时。以下是您需要了解的内容:

前提条件

开始之前,您需要设置:

  • GitLab账户(具有管理员权限)
  • 已发布在Google Play商店中的应用(签名正确)
  • 安卓签名密钥和keystore文件
  • Google Cloud Console项目(Play StoreAPI已启用)
  • 具有适当权限的服务账户
  • GitLab CI/CD工作流程的理解
  • Fastlane配置的知识
  • 维护和调试管道的时间

Capgo Build for CI/CD by Capgo

跳过Fastlane、Gradle runner、keystore和上传脚本的维护。 Capgo Build 从您的CI/CD管道中运行已有的签名原生Android构建:

  • 与您的管道兼容: 从GitLab CI、GitHub Actions、Jenkins或本地脚本中触发Capgo Build npx cap sync.
  • 从CI密钥中签名: 在CI密钥中保留Android密钥库、密钥别名、密码和Play Console服务账户JSON。
  • 无native runner维护: Capgo Build提供维护的Android构建环境,因此您不需要管理SDK镜像、Gradle缓存问题或Fastlane通道。
  • 工件和提交: 下载用于QA的签名工件或通过Capgo CLI提交发布版本。

价格计划

  • Capgo 计划从每月 12 美元开始
  • 包括 OTA 更新和每月约 15 个本机构建
  • 额外的构建分钟按分钟计费,通过积分

在 CI/CD 中设置 Capgo 构建

手动设置指南

以下是您需要做的事情:

请遵循以下步骤

  1. 复制 Fastlane 文件
  2. 在 GitLab 中存储加密的机密
  3. 创建并存储 Google Play 服务帐户密钥
  4. 存储您的 Android 签名密钥
  5. 设置您的 GitLab 工作流 .yml 文件

1. 复制 Fastlane 文件

Fastlane 是一款 Ruby 库,用于自动化常见的移动开发任务。使用 Fastlane,可以配置自定义的“道线”(lanes),这些道线包含一系列的“动作”(actions),这些动作执行您通常使用 Android Studio 执行的任务。您可以使用 Fastlane 做很多事情,但在本教程中,我们将仅使用一小部分核心动作。

创建一个 Fastlane 文件夹,位于您的项目根目录,并复制以下文件: Fastlane

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'])
				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}")
        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(
					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
    lane :build do
      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}",
        })
    end
    lane :prod_release do
      build_gradle = File.read("../android/app/build.gradle")

      verify_changelog_exists(version_code: build_gradle.match(/versionCode (\d+)/)[1])
      verify_upload_to_staging(version_name: build_gradle.match(/versionName '([\d\.]+)'/)[1])

      supply(
        track_promote_to: 'beta',
        skip_upload_apk: true,
        skip_upload_aab: true,
        skip_upload_metadata: false,
        skip_upload_changelogs: false,
        skip_upload_images: false,
        skip_upload_screenshots: false
      )
    end
end

在 GitLab CI/CD 变量中存储您的机密信息

GitLab 提供了一个存储加密的 CI/CD 变量的方式,类似于 GitHub 的仓库机密。要安全地存储您的敏感信息。

  1. 前往您的 GitLab 项目的设置。
  2. 导航到 CI/CD > 变量
  3. 添加以下变量:
  • ANDROID_KEYSTORE_FILE: 基于 64 位编码的 .jks.keystore 您可以选择使用 Appflow、Capawesome 或其他替代方案。
  • KEYSTORE_KEY_PASSWORD: 与密钥库文件相关的密码
  • KEYSTORE_KEY_ALIAS: 密钥库别名
  • KEYSTORE_STORE_PASSWORD: 私钥密码
  • DEVELOPER_PACKAGE_NAME: 你的 Android 应用程序 ID,如 com.example.app
  • PLAY_CONFIG_JSON: 基于 64 位的服务帐户密钥 JSON。

创建 Google Play 服务帐户密钥

要生成密钥,请遵循以下步骤: PLAY_CONFIG_JSON 访问 Google Cloud 控制台

  1. 创建一个新项目或选择一个现有的项目 启用 Google Play Android 开发者 __CAPGO_KEEP_0__
  2. Creating a Google Play Service Account Key
  3. Enable the Google Play Android Developer API
  4. 创建一个服务账户:
    • 转到 “IAM & Admin” > “服务账户”
    • 点击 “创建服务账户”
    • 为其命名并添加描述
    • 点击 “创建并继续”
    • 跳过角色赋予并点击 “完成”
  5. 生成 JSON 密钥:
    • 在列表中找到您的服务账户
    • 点击三点菜单 > “管理密钥”
    • 点击 “添加密钥” > “创建新密钥”
    • 选择 JSON 格式
    • 点击 “创建”
  6. 为您的应用程序在 Play Console 中授予服务帐户访问权限:
    • 前往 Play Console
    • 导航到“用户和权限”
    • 点击“邀请新用户”
    • 输入服务帐户电子邮件(以 @*.iam.gserviceaccount.com 结尾)
    • 授予“发布到生产环境”权限
    • 点击“邀请用户”
  7. 将 JSON 密钥转换为 base64:
    base64 -i path/to/your/service-account-key.json | pbcopy
  8. 将 base64 编码的字符串添加为 GitLab 变量 PLAY_CONFIG_JSON 设置您的 GitLab CI/CD pipeline

Set Up Your GitLab CI/CD Pipeline

创建一个 .gitlab-ci.yml 文件,放在项目的根目录中,来定义你的 CI/CD pipeline。以下是一个如何结构你的 pipeline 的例子:


image: mingc/android-build-box:latest

stages:
  - build
  - upload_to_capgo
  - build_and_upload_android

build:
  stage: build
  tags:
    - saas-linux-xlarge-amd64
  cache:
    - key:
        files:
          - bun.lockb
      paths:
        - .node_modules/
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - node_modules/
      - dist/
  only:
    - master

upload_to_capgo:
  stage: upload_to_capgo
  tags:
    - saas-linux-xlarge-amd64
  script:
    - npx @capgo/cli@latest bundle upload -a $CAPGO_TOKEN -c dev
  dependencies:
    - build
  when: manual
  only:
    - master

build_and_upload_android:
  tags:
    - saas-linux-xlarge-amd64
  stage:    build_and_upload_android
  cache:
    - key:
        files:
          - android/gradle/wrapper/gradle-wrapper.properties
      paths:
        - ~/.gradle/caches/
  script:
    - npx cap sync android
    - npx cap copy android
    - bundle exec fastlane android beta # We do create a tag for the build to trigger XCode cloud builds
  dependencies:
    - build
  when: manual
  only:
    - master

触发 Pipeline

当你推送一个新的标签到你的 GitLab 仓库时,GitLab CI/CD 会自动触发定义的 pipeline,pipeline 会使用 Fastlane 来构建和部署你的 Android app。

确保根据你的项目结构和需求调整路径和依赖项。这一设置会帮助你在 GitLab CI/CD 中自动部署你的 Android app。

结论

通过使用 mingc/android-build-box Docker 镜像来配置 GitLab CI/CD,你可以自动化 Android app 的构建过程,使你的开发流程更加高效和可靠。这一自动化会释放你的时间,让你专注于 app 开发的核心方面,从而帮助你更高效地交付高质量的 Android app。

继续阅读 Automatic Capacitor Android build with GitLab

如果你正在使用 Automatic Capacitor Android build with GitLab 来规划 CI/CD 自动化,连接它与 Capgo CI/CD 来实现产品工作流程在 Capgo CI/CD 中 Capgo 原生构建 为产品工作流程在 Capgo 原生构建 Capgo 集成 为产品工作流程在 Capgo 集成 CI/CD 集成 为 CI/CD 集成的实现细节 GitHub 动作集成 为 GitHub 动作集成的实现细节

实时更新Capacitor应用

当 Web 层 bug 活跃时,通过 Capgo 直接将修复推送给用户,而不是等待 App Store 审批几天。用户可以在后台接收更新,而原生代码的变更仍然在正常的审查路径中。

人工支持来自Martin

立即开始

最新博客

Capgo 为您提供了创建真正专业的移动应用所需的最佳见解。