移动端 CI/CD:自动化构建、测试与分发

FreeGuideOnline 最新 2026-06-17

移动端 CI/CD:自动化构建、测试与分发

什么是移动端 CI/CD

CI/CD 是一套软件开发实践,包含持续集成(Continuous Integration)持续交付/部署(Continuous Delivery/Deployment)。在移动应用开发中,它的目标是让代码提交后自动完成构建、测试、签名、打包,并推送到测试分发平台或应用商店,从而减少人工操作、尽早发现错误、加快交付速度。

  • 持续集成(CI):开发者频繁地将代码合并到主干分支,每次合并都会触发自动化构建和测试,以便快速发现集成问题。
  • 持续交付(CD):在 CI 通过后,自动将应用打包成可安装的产物,并上传到内部测试分发平台(如 TestFlight、Firebase App Distribution),供测试人员或产品经理随时获取最新版本。
  • 持续部署(CD):更高阶的阶段,自动将通过所有测试的版本直接发布到 Google Play 或 App Store,通常用于灰度或内部发布。

本教程将引导你从零搭建一套适用于 Android 和 iOS 项目的 CI/CD 流程,即使没有 DevOps 经验也能跟随操作。


为什么移动端需要 CI/CD

移动应用构建环境复杂,依赖特定的操作系统、SDK 版本、签名证书、配置文件等。手动构建和分发常会遇到:

  • 开发机器环境不一致,导致“在我电脑上能跑”的问题。
  • 打包、测试、上传重复性劳动耗时且容易出错。
  • 证书和配置文件管理混乱,经常过期或错误签署。
  • 测试反馈缓慢,难以频繁发布 Beta 版本。

引入 CI/CD 可以:

  • 统一构建环境:所有构建在隔离的、可复现的容器或虚拟机中运行。
  • 自动化门禁:每次提交必然经过编译检查、静态分析、单元测试,不合格的代码无法进入测试分发。
  • 解放生产力:开发者专注代码,构建与分发由机器自动完成。
  • 快速反馈:几分钟内就能知道改动是否编译成功、测试是否通过,测试人员也能第一时间获得安装包。

核心概念与流程概览

一个典型的移动端 CI/CD 流水线包含如下阶段:

  1. 触发器:代码推送到仓库、PR 创建、标签推送或定时计划。
  2. 环境准备:拉取依赖镜像(如 Android SDK、Xcode 环境),安装必要工具。
  3. 代码检出:克隆仓库,切换到对应分支。
  4. 安装依赖与预处理:运行 npm install(React Native/Flutter)、pod install(iOS)或 Gradle 依赖解析。
  5. 静态检查与测试:Lint 检查、代码风格、单元测试、UI 测试。
  6. 编译与打包:调用 Gradle 或 xcodebuild 生成 APK/AAB/IPA。
  7. 签名:使用预先配置的密钥库或 Apple 证书对应用签名。
  8. 上传分发:将包上传到测试平台(Firebase App Distribution、TestFlight、App Center 等)或应用商店。
  9. 通知:通过 Slack、邮件等告知团队新构建已就绪。

下面将以工具选择和具体实现为主线展开。


工具选择

构建执行环境

  • GitHub Actions:免费额度友好,与 GitHub 深度集成,社区 Action 丰富。
  • GitLab CI/CD:自托管或 SaaS,配置灵活,Runner 可自定义。
  • Jenkins:历史悠久,高度可定制,适合复杂场景;需自行维护服务器。
  • Bitrise:专为移动端设计,可视化配置,自带 macOS 和 Android 环境。
  • CircleCI / Travis CI:提供 macOS 构建机,适合需要 iOS 构建的团队。

本教程选用 GitHub Actions 作为示例,同时使用 fastlane 来简化构建、签名和分发任务。

自动化工具

  • fastlane:移动端 CI/CD 的事实标准,提供 gym(构建 iOS)、gradle(构建 Android)、match(管理证书)、pilot(TestFlight)、supply(Google Play)等一整套工具链。
  • Gradle + Shell:Android 构建可直接通过 Gradle 命令行完成,配合 Shell 脚本上传。
  • xcodebuild + xcrun:iOS 纯命令行方案,适合不依赖 fastlane 的场景。

环境准备与签名配置

Android 签名配置

Android 应用发布需要签名证书(.jks 或 .keystore 文件)。安全起见,不应将证书文件提交到代码仓库。在 CI 环境中通常采用以下方式:

  1. 将证书文件用 base64 编码后保存在 CI 的 Secrets 中。
  2. 在 CI 作业中解码恢复,写入临时目录。
  3. 通过 Gradle 属性或环境变量传递密码和别名。

Gradle 配置示例(app/build.gradle 或 gradle.properties):

android {
    signingConfigs {
        release {
            storeFile file(System.getenv("KEYSTORE_PATH") ?: "debug.keystore")
            storePassword System.getenv("KEYSTORE_PASSWORD")
            keyAlias System.getenv("KEY_ALIAS")
            keyPassword System.getenv("KEY_PASSWORD")
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

iOS 签名与证书管理

iOS 构建必须使用 Apple Developer 账号生成的 Provisioning Profile 和证书。手动管理极易出错,推荐使用 fastlane 的 matchsigh 工具。

match 会将证书和配置文件加密存储在 Git 仓库中,CI 机器第一次配置后即可自动拉取和解密,保证团队使用相同的签名材料。

初始化 match 并配置仓库:

fastlane match init

随后在 CI 中使用 match 获取证书:

fastlane match appstore --readonly

(首次运行可能需要交互,需在 CI 环境提供 MATCH_PASSWORD 等环境变量)


实施步骤:从零搭建 GitHub Actions + fastlane 流水线

以下演示将用 GitHub Actions 触发构建、运行测试、打包并上传到 Firebase App Distribution(Android)和 TestFlight(iOS)。请确保项目根目录已初始化 fastlane。

步骤 1:配置 fastlane

在项目根目录创建 fastlane/Fastfile,内容如下:

Android 的 Fastfile(片段):

default_platform(:android)

platform :android do
  desc "Build and upload to Firebase"
  lane :firebase_distribution do
    gradle(task: "clean assembleRelease")
    firebase_app_distribution(
      app: "1:123456789:android:abcde12345",
      service_credentials_file: "firebase_credentials.json",
      groups: "qa-team",
      release_notes: "Automated build"
    )
  end
end

iOS 的 Fastfile(片段):

default_platform(:ios)

platform :ios do
  lane :testflight do
    match(type: "appstore", readonly: true)
    gym(scheme: "YourApp", export_method: "app-store")
    pilot
  end
end

步骤 2:存储敏感信息到 GitHub Secrets

在仓库 Settings → Secrets and variables → Actions 中添加:

  • KEYSTORE_BASE64:用 base64 编码后的 Android keystore 文件内容
  • KEYSTORE_PASSWORDKEY_ALIASKEY_PASSWORD
  • MATCH_PASSWORD:用于解密 match 仓库
  • APP_STORE_CONNECT_API_KEY_JSON:App Store Connect API 密钥(用于上传),或使用 APP_STORE_CONNECT_ISSUER_IDKEY_ID 和私钥
  • FIREBASE_CREDENTIALS_JSON:Firebase 服务帐号凭证内容
  • 其他必要的环境变量

步骤 3:编写 GitHub Actions 工作流文件

.github/workflows/ 下创建 mobile-ci.yml

Android CI 示例:

name: Android CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-upload:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          distribution: 'zulu'
          java-version: '17'

      - name: Decode Keystore
        run: |
                    echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > android/app/release.keystore

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Run unit tests
        run: ./gradlew testDebugUnitTest

      - name: Build Release APK
        env:
          KEYSTORE_PATH: "android/app/release.keystore"
          KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
          KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
        run: ./gradlew assembleRelease

      - name: Upload to Firebase App Distribution
        # 假设 fastlane 已配置,需要设置 firebase_credentials 文件
        env:
          FIREBASE_CREDENTIALS_CONTENT: ${{ secrets.FIREBASE_CREDENTIALS_JSON }}
        run: |
          echo "$FIREBASE_CREDENTIALS_CONTENT" > firebase_credentials.json
          bundle exec fastlane android firebase_distribution          

iOS CI 示例(需要在 macOS runner 上运行):

name: iOS CI

on:
  push:
    branches: [ main, develop ]

jobs:
  build-and-upload:
    runs-on: macos-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'

      - name: Install Fastlane & Cocoapods
        run: |
                    bundle install
      - name: Run tests
        run: xcodebuild test -scheme YourApp -destination 'platform=iOS Simulator,name=iPhone 15'

      - name: Build and upload to TestFlight
        env:
          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
          APP_STORE_CONNECT_API_KEY_JSON: ${{ secrets.APP_STORE_CONNECT_API_KEY_JSON }}
        run: bundle exec fastlane ios testflight

步骤 4:触发并验证

将上述文件推送到 GitHub,查看 Actions 选项卡中的运行情况。若出现错误,根据日志调整。


自动化测试集成

CI 流水线应强制运行测试,避免携带破坏性修改的构建进入分发。

Android 测试

  • 单元测试:使用 ./gradlew testDebugUnitTest,报告可生成 HTML 或 JUnit XML。
  • 仪器测试(UI 测试):需启动模拟器或连接到真实设备。可在 CI 中使用 Android Emulator Action 或借助 Firebase Test Lab。

GitHub Actions 中启动模拟器的示例:

- name: Run instrumentation tests
  uses: reactivecircus/android-emulator-runner@v2
  with:
    api-level: 34
    target: google_apis
    arch: x86_64
    script: ./gradlew connectedCheck

iOS 测试

默认的 xcodebuild 测试命令可运行单元测试和 UI 测试。UI 测试需要模拟器,macOS runner 默认已包含 Xcode 和模拟器。使用 xcodebuild test 指定 -destination 参数即可。若使用 fastlane,可调用 scan

scan(scheme: "YourApp")

代码质量检查

在构建之前集成静态分析,可以及早发现潜在 bug 和风格问题。

  • Android:可在 Gradle 中配置 Lint 检查,并运行 ./gradlew lint。也可集成 Detekt、Ktlint 等。
  • iOS:使用 SwiftLint,通过脚本或构建阶段执行。
  • 通用:SonarQube、CodeClimate 等平台可接入 CI 流程,提供可视化质量报告。

分发到测试平台与应用商店

Android

  • 内部/封闭测试:通过 fastlane 的 supply 或 Gradle Play Publisher 插件上传到 Google Play Console 的 Alpha/Beta 轨道。
  • Firebase App Distribution:适合快速分发给测试人员,无需等待商店审核。使用 fastlane 插件 firebase_app_distribution 或直接调用 Firebase CLI。
  • App Center:微软提供的替代方案,功能类似,支持崩溃分析。

iOS

  • TestFlight:苹果官方分发渠道,外部测试邀请需要经过 Beta 审核。通过 fastlane pilot 上传 ipa,自动填写测试信息。
  • Firebase App Distribution:同样支持 iOS,需提供 Ad Hoc 或 Development Provisioning Profile 签名的 IPA。
  • App Center:同样可用。

最佳实践与常见问题

  1. 密钥管理:绝不将任何明文密码或证书文件提交到仓库。所有敏感数据通过 CI Secrets 注入,证书可通过 match 加密存储。
  2. 构建缓存:利用 CI 的缓存机制,缓存 Gradle、CocoaPods、npm 等依赖,加速后续构建。
    • GitHub Actions 示例:actions/cache@v3 缓存 ~/.gradle/cachesPods 目录。
  3. 分支策略:推荐采用 Git Flow 或 Trunk-Based 开发,将 CI 与 PR 检查结合,确保合并到主分支的代码总是可构建、可测试。
  4. 矩阵构建:如需同时构建多个 SDK 版本或架构,使用 CI 提供的矩阵策略,例如多个 API level 测试。
  5. 环境一致性:在 CI 中明确指定 Java 版本、Ruby 版本、Xcode 版本,避免因环境差异导致构建突然失败。
  6. 通知与反馈:构建结束后通过 Slack、钉钉、邮件等发送结果。fastlane 也有内置的通知机制。
  7. 监控失败:尽快修复 CI 失败,避免坏构建堆积。鼓励团队将 CI 失败视为最高优先级的事项。

小结

移动端 CI/CD 的落地并不复杂,关键在于选择合适的工具链并逐步推进。通过 GitHub Actions 结合 fastlane,你可以在几小时内为 Android 和 iOS 项目搭建起从代码提交到测试分发的一站式自动化管道。随着团队成熟,还可扩展为自动截图、翻译更新、多版本发布等高级能力。现在就从添加一个简单的工作流文件开始,享受自动化带来的开发效率提升吧。