名称: Fastlane/移动端CI-CD 描述: 使用Fastlane实现移动端自动化构建、测试和部署 版本: 1.0.0 类别: 移动DevOps 标识符: fastlane-cicd 状态: 活跃
Fastlane/移动端CI-CD技能
概述
本技能提供使用Fastlane进行移动端CI/CD自动化的全面能力。它支持iOS和Android平台的自动化构建、测试、代码签名、Beta分发和应用商店部署。
允许的工具
bash- 执行Fastlane命令、Ruby和bundlerread- 分析Fastfile、Appfile和配置文件write- 生成Fastlane配置和通道edit- 更新现有Fastlane配置glob- 搜索Fastlane和CI配置文件grep- 在CI/CD配置中搜索模式
能力
Fastlane配置
-
Fastfile设置
- 创建平台特定通道
- 配置before_all和after_all钩子
- 使用error块实现错误处理
- 设置环境变量
- 配置通道选项和参数
-
Appfile配置
- 配置应用标识符
- 设置Apple ID和团队设置
- 配置Google Play凭证
- 设置环境特定值
iOS代码签名
-
Match(代码签名)
- 配置基于Git的证书存储
- 设置开发、adhoc和应用商店配置文件
- 实现自动证书续订
- 处理多团队配置
- 为CI配置只读模式
-
手动代码签名
- 使用cert操作导入证书
- 使用sigh生成配置文件
- 配置权利
- 处理企业分发
构建自动化
-
iOS构建
- 配置gym进行归档创建
- 设置构建配置
- 处理bitcode设置
- 配置导出选项
- 实现构建号自动化
-
Android构建
- 配置gradle操作
- 构建APK和AAB文件
- 处理签名配置
- 配置构建变体
- 实现版本代码自动化
测试
-
测试自动化
- 运行scan进行iOS测试
- 配置测试方案和目标
- 处理测试并行化
- 生成测试报告
- 实现重试逻辑
-
Android测试
- 运行gradle测试任务
- 配置仪器测试
- 与Firebase Test Lab集成
- 生成覆盖率报告
Beta分发
-
TestFlight
- 配置pilot进行TestFlight上传
- 管理测试组
- 处理更新日志更新
- 配置外部测试
- 实现等待处理
-
Firebase应用分发
- 配置firebase_app_distribution
- 管理测试人员组
- 处理发布说明
- 配置Android和iOS分发
应用商店部署
-
App Store Connect
- 配置deliver处理元数据
- 使用snapshot上传截图
- 提交审核
- 处理分阶段发布
- 管理应用版本
-
Google Play商店
- 配置supply处理Play商店
- 管理发布轨道
- 上传AAB文件
- 处理分阶段推出
- 配置应用内更新
CI集成
-
GitHub Actions
- 配置工作流文件
- 设置密钥管理
- 实现缓存策略
- 配置矩阵构建
- 处理工件
-
其他CI平台
- Bitrise集成
- CircleCI配置
- Jenkins流水线设置
- Azure DevOps集成
目标流程
本技能与以下流程集成:
mobile-cicd-fastlane.js- CI/CD流水线设置automated-release-management.js- 发布自动化ios-appstore-submission.js- iOS部署android-playstore-publishing.js- Android部署beta-testing-setup.js- Beta分发
依赖项
必需
- Ruby 3.0+
- Bundler
- Fastlane
- Xcode(用于iOS)
- Android SDK(用于Android)
可选
- Firebase CLI
- GitHub CLI
- AWS CLI(用于S3存储)
配置
项目结构
项目根目录/
├── fastlane/
│ ├── Fastfile
│ ├── Appfile
│ ├── Matchfile
│ ├── Pluginfile
│ ├── Gymfile
│ ├── Scanfile
│ ├── Deliverfile
│ ├── metadata/
│ │ ├── en-US/
│ │ │ ├── description.txt
│ │ │ ├── keywords.txt
│ │ │ └── release_notes.txt
│ │ └── review_information/
│ └── screenshots/
├── Gemfile
└── Gemfile.lock
Gemfile
# Gemfile
source "https://rubygems.org"
gem "fastlane"
gem "cocoapods" # 用于iOS
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)
使用示例
基础Fastfile
# fastlane/Fastfile
default_platform(:ios)
before_all do
ensure_git_status_clean
git_pull
end
platform :ios do
desc "运行测试"
lane :test do
scan(
scheme: "MyApp",
devices: ["iPhone 15 Pro"],
code_coverage: true,
output_directory: "./fastlane/test_output"
)
end
desc "构建并上传到TestFlight"
lane :beta do
increment_build_number(xcodeproj: "MyApp.xcodeproj")
match(type: "appstore", readonly: true)
gym(
scheme: "MyApp",
export_method: "app-store",
output_directory: "./build"
)
pilot(
skip_waiting_for_build_processing: true,
changelog: "Bug fixes and improvements"
)
commit_version_bump(
message: "Bump build number [skip ci]",
xcodeproj: "MyApp.xcodeproj"
)
push_to_git_remote
end
desc "部署到App Store"
lane :release do
capture_screenshots
increment_version_number(bump_type: "patch")
increment_build_number
match(type: "appstore", readonly: true)
gym(scheme: "MyApp", export_method: "app-store")
deliver(
submit_for_review: true,
automatic_release: false,
force: true,
precheck_include_in_app_purchases: false
)
end
error do |lane, exception|
slack(
message: "Lane #{lane} failed: #{exception.message}",
success: false
)
end
end
platform :android do
desc "运行测试"
lane :test do
gradle(task: "testDebugUnitTest")
end
desc "构建并上传到Firebase应用分发"
lane :beta do
gradle(
task: "bundle",
build_type: "Release"
)
firebase_app_distribution(
app: ENV["FIREBASE_APP_ID"],
groups: "internal-testers",
release_notes: "Bug fixes and improvements"
)
end
desc "部署到Play商店"
lane :release do
gradle(
task: "bundle",
build_type: "Release"
)
supply(
track: "production",
aab: "./app/build/outputs/bundle/release/app-release.aab",
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true
)
end
end
Matchfile
# fastlane/Matchfile
git_url("git@github.com:organization/certificates.git")
storage_mode("git")
type("appstore")
app_identifier(["com.example.myapp", "com.example.myapp.widget"])
username("developer@example.com")
# 用于CI环境
readonly(is_ci)
# 平台
platform("ios")
Appfile
# fastlane/Appfile
# iOS
app_identifier("com.example.myapp")
apple_id("developer@example.com")
team_id("XXXXXXXXXX")
itc_team_id("XXXXXXXXXX")
# Android
json_key_file("./fastlane/play-store-key.json")
package_name("com.example.myapp")
# 环境特定
for_platform :ios do
for_lane :beta do
app_identifier("com.example.myapp.beta")
end
end
GitHub Actions工作流
# .github/workflows/ios-deploy.yml
名称: iOS部署
触发条件:
push:
分支: [main]
标签: ['v*']
任务:
部署:
运行环境: macos-14
步骤:
- 使用: actions/checkout@v4
- 名称: 设置Ruby
使用: ruby/setup-ruby@v1
参数:
ruby版本: '3.2'
bundler缓存: true
- 名称: 安装依赖项
运行: bundle install
- 名称: 设置证书
环境变量:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_AUTH }}
运行: bundle exec fastlane match appstore --readonly
- 名称: 构建和部署
环境变量:
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.ASC_KEY_ID }}
APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
APP_STORE_CONNECT_API_KEY: ${{ secrets.ASC_KEY }}
运行: |
if [[ $GITHUB_REF == refs/tags/* ]]; then
bundle exec fastlane ios release
else
bundle exec fastlane ios beta
fi
- 名称: 上传工件
使用: actions/upload-artifact@v4
参数:
名称: build-artifacts
路径: |
./build/*.ipa
./fastlane/test_output/
Android GitHub Actions
# .github/workflows/android-deploy.yml
名称: Android部署
触发条件:
push:
分支: [main]
标签: ['v*']
任务:
部署:
运行环境: ubuntu-latest
步骤:
- 使用: actions/checkout@v4
- 名称: 设置JDK
使用: actions/setup-java@v4
参数:
java版本: '17'
发行版: 'temurin'
缓存: gradle
- 名称: 设置Ruby
使用: ruby/setup-ruby@v1
参数:
ruby版本: '3.2'
bundler缓存: true
- 名称: 解码密钥库
运行: |
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > app/release.keystore
- 名称: 创建key.properties
运行: |
echo "storeFile=release.keystore" >> android/key.properties
echo "storePassword=${{ secrets.KEYSTORE_PASSWORD }}" >> android/key.properties
echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> android/key.properties
echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/key.properties
- 名称: 创建Play商店密钥
运行: echo '${{ secrets.PLAY_STORE_KEY }}' > fastlane/play-store-key.json
- 名称: 构建和部署
运行: |
if [[ $GITHUB_REF == refs/tags/* ]]; then
bundle exec fastlane android release
else
bundle exec fastlane android beta
fi
质量门控
构建验证
- 部署前所有测试通过
- 代码覆盖率满足阈值
- 无编译器警告
- 静态分析通过
发布标准
- 版本号已递增
- 更新日志已更新
- 截图最新
- 元数据完整
安全性
- 证书安全存储
- 密钥不在仓库中
- API密钥定期轮换
相关技能
app-store-connect- App Store管理google-play-console- Play商店管理mobile-testing- 测试自动化
版本历史
- 1.0.0 - 支持Fastlane 2.x的初始版本