5 min read

使用 Fastlane 配置 React Native App 打包自动化

Table of Contents

引言

在 React Native 开发中,打包和发布流程往往是重复且耗时的手动操作。每次发布新版本都需要手动执行一系列命令:编译 iOS 包、签名、生成 APK、上传 App Store… 这不仅繁琐,还容易出错。

Fastlane 是 iOS 和 Android 自动化的终极工具,它可以帮你自动化整个构建、签名和发布流程。本文将详细介绍如何为 React Native 项目配置 Fastlane,实现一键打包自动化。


什么是 Fastlane?

Fastlane 是一个开源的工具链,用于自动化 iOS 和 Android 的构建、测试和发布流程。它由一系列「actions」组成,每个 action 完成特定的任务,如:

  • 编译代码
  • 生成截图
  • 管理证书和描述文件
  • 上传到 TestFlight / App Store / Google Play
  • 等等…

使用 Fastlane,你可以用配置文件(Fastfile)定义整个发布流程,然后只需一个命令即可完成。


环境准备

1. 安装 Fastlane

# 使用 Ruby gem 安装(推荐)
sudo gem install fastlane -NV

# 或者使用 Homebrew
brew install fastlane

# 或者使用 npm(适用于 CI/CD 环境)
npm install -g fastlane

2. 初始化 Fastlane

进入你的 React Native 项目目录:

cd your-react-native-project
fastlane init

初始化过程中,Fastlane 会询问你选择哪个平台:

  • iOS
  • Android
  • 两者都

对于 React Native 项目,建议选择 iOSAndroid,这样可以为两个平台分别配置自动化流程。

初始化完成后,项目目录会新增一个 fastlane 文件夹:

your-react-native-project/
├── fastlane/
│   ├── Appfile          # 应用配置
│   └── Fastfile         # 自动化流程定义
├── ios/
├── android/
└── src/

配置 iOS 自动化

Appfile 配置

编辑 fastlane/Appfile,填入你的应用信息:

app_identifier("com.yourcompany.yourapp")
apple_id("your-apple-id@email.com")
team_id("YOUR_TEAM_ID")

# 如果有多个开发者,可以指定不同的证书
# for more information about the available options
# for_perform_actions:
#   a

Fastfile 定义

编辑 fastlane/Fastfile,定义你的自动化流程:

default_platform(:ios)

platform :ios do
  desc "构建 iOS 测试包"
  lane :build_test do
    # 获取版本号
    version = get_version_number(target: "YourAppTarget")
    build = get_build_number(target: "YourAppTarget")

    # 匹配证书和描述文件
    match(type: "development", readonly: true)

    # 编译项目
    gym(
      scheme: "YourAppScheme",
      configuration: "Debug",
      export_method: "development"
    )
  end

  desc "构建 App Store 发布包"
  lane :build_release do
    version = get_version_number(target: "YourAppTarget")
    build = get_build_number(target: "YourAppTarget")

    # 使用 match 管理证书
    match(type: "appstore", readonly: true)

    gym(
      scheme: "YourAppScheme",
      configuration: "Release",
      export_method: "appstore",
      build_number: build
    )

    # 输出构建信息
    puts "✅ 构建完成!版本: #{version}, Build: #{build}"
  end

  desc "上传到 TestFlight"
  lane :upload_testflight do
    build_release

    pilot(
      distribute_external: true,
      notify_external_testers: true
    )
  end

  desc "发布到 App Store"
  lane :publish do
    build_release

    deliver(
      skip_screenshots: true,
      skip_metadata: true,
      force: true
    )
  end
end

配置 Android 自动化

Appfile 配置

json_key_file("./google-play-api-key.json")
package_name("com.yourcompany.yourapp")

Fastfile 定义

default_platform(:android)

platform :android do
  desc "构建测试包"
  lane :build_test do
    gradle(
      task: "assembleDebug",
      build_type: "Debug"
    )
  end

  desc "构建 release 包并签名"
  lane :build_release do
    gradle(
      task: "assembleRelease",
      build_type: "Release"
    )
  end

  desc "上传到 Google Play internal testing"
  lane :publish_internal do
    build_release

    supply(
      track: "internal",
      apk: "./android/app/build/outputs/apk/release/app-release.apk"
    )
  end

  desc "上传到 Google Play production"
  lane :publish_production do
    build_release

    supply(
      track: "production",
      apk: "./android/app/build/outputs/apk/release/app-release.apk",
      skip_upload_images: true,
      skip_upload_screenshots: true
    )
  end
end

在 React Native 中使用

集成到 package.json

package.json 中添加脚本,方便团队成员使用:

{
  "scripts": {
    "ios:build:test": "fastlane ios build_test",
    "ios:build:release": "fastlane ios build_release",
    "ios:testflight": "fastlane ios upload_testflight",
    "ios:publish": "fastlane ios publish",
    "android:build:test": "fastlane android build_test",
    "android:build:release": "fastlane android build_release",
    "android:publish": "fastlane android publish_internal"
  }
}

触发打包

现在,只需一个命令即可完成打包:

# iOS 测试包
npm run ios:build:test

# iOS 发布包
npm run ios:build:release

# 上传到 TestFlight
npm run ios:testflight

# Android 测试包
npm run android:build:test

# Android 发布到 Google Play
npm run android:publish

CI/CD 集成

GitHub Actions 示例

name: Build and Release

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  ios:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Install Fastlane
        run: brew install fastlane
      
      - name: Build iOS
        run: fastlane ios build_release
        env:
          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
          APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
          APPLE_CERTIFICATE_PWD: ${{ secrets.APPLE_CERTIFICATE_PWD }}

  android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build Android
        run: fastlane android build_release
        env:
          GOOGLE_PLAY_KEY: ${{ secrets.GOOGLE_PLAY_KEY }}

最佳实践

1. 使用 Match 管理证书

Fastlane Match 是管理 iOS 证书和描述文件的最佳方式:

fastlane match init

Match 会将你的证书存储在 Git 仓库中,团队成员只需运行 match 即可自动配置正确的证书。

2. 环境变量管理敏感信息

使用 .env 文件或 CI/CD 的 secrets 管理敏感信息:

# Fastfile
api_key = ENV["APPSTORE_API_KEY"]
google_play_key = ENV["GOOGLE_PLAY_KEY"]

3. 版本号管理

在 React Native 中,可以结合 react-native-version 或手动更新版本:

# 自动递增版本号
increment_version_number(
  bump_type: "patch"  # patch, minor, major
)

increment_build_number(
  build_number: latest_testflight_build_number + 1
)

常见问题

Q: 编译失败,提示证书找不到?

确保运行过 fastlane match 或在 CI 中正确配置了证书。

Q: Android 打包提示签名失败?

检查 android/app/build.gradle 中的签名配置,确保 release 构建类型配置了正确的签名密钥。

Q: 如何查看 Fastlane 的调试信息?

使用 --verbose 参数:

fastlane ios build_test --verbose

总结

Fastlane 是 React Native 项目自动化不可或缺的工具。通过本文的配置,你可以实现:

  • ✅ 一键构建 iOS/Android 测试包
  • ✅ 自动管理证书和描述文件
  • ✅ 一键上传到 TestFlight / Google Play
  • ✅ 集成 CI/CD,实现自动化发布

把重复性的打包工作交给 Fastlane,把时间留给更有价值的开发工作吧!


参考链接: