React native 持续集成实践
在React Native项目开发中,我们使用CircleCI + Fastlane搭建了一套持续集成的环境,来自动完成CI CD。
基本需求
- 每次push代码,CI可以自动跑测试,并在线查看测试覆盖率
- 自动打包ios app,发布到TestFlight
- 自动打包android app,发布到Crashlytics
使用到的工具
使用CircleCI搭建持续集成环境
设置基本环境
由于需要打包ios app,而ios app打包要求系统必须是macOS,所以需要选择CircleCI为macOS plan。并且在CircleCI设置的Build Enviroment里开启Build macOS project选项。
首先,在项目根目录上创建circle.yml文件(当时只有CircleCI 1的版本支持macOS plan),设置xcode版本,直接指定所需版本即可,我们项目中当时使用的xcode版本为8.3.3。
machine: enviroment: xcode: version: 8.3.3
安装依赖
我们可以先查看一下当前macOS环境中已经安装了哪些软件(macOS -
xcode 8.3.3)。可以看出当前macOS环境没有nvm,不能直接设置node的版本,所以我们需要手动安装nvm,并安装所需版本的node。由于项目中使用的包管理工具是yarn,所以也需要安装yarn。
dependencies: pre: # 安装nvm - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash # 安装所需node版本,我们项目中使用的是8.9.1 - nvm install 8.9.1 # 全局安装yarn - npm install yarn --global override: # 安装项目所需依赖 - yarn install cache_directories: # 缓存依赖节省后续build的时间 - ~/.cache/yarn - node_modules
自动运行测试
test: pre: - yarn lint override: - yarn test post: # 保存测试覆盖率文件夹,用于在线查看 - mkdir $CIRCLE_ARTIFACTS/coverage - mv coverage/* $CIRCLE_ARTIFACTS/coverage
在运行测试之前,我们要先运行lint来检查代码格式是否符合规范。yarn test用来运行测试。在测试运行完之后,要将测试覆盖率的文件夹保存在CircleCI上,用于在线查看测试报告。
在每次build之前,CircleCI会创建一个空白文件夹,并导出一个只读环境变量$CIRCLE_ARTIFACTS。在build结束之后,在这个文件夹里的内容会被保存下来,并链接到这个build。
CircleCI在每个阶段都有默认的执行命令,我们可以使用下面三个特殊键来指定何时运行哪些自定义的命令:
- pre: 在该阶段命令前运行
- override: 自定义该阶段的命令
- post: 在该阶段命令后运行
使用fastlane自动进行IOS APP beta deplopment
fastlane是为iOS和Android app自动化测试部署和发布的最简单方法。 它可以处理所有繁琐的任务,如生成屏幕截图、管理code signing以及发布app。
fastlane提供了一系列的工具来处理这些工作,每一个工具用来处理一项工作,可以根据项目来进行组合。如:gym用来打包app。
对于iOS app,会发布到TestFlight。
安装fastlane
确保已经安装最新的xcode命令行工具:
xcode-select --install
在macOS上使用brew安装fastlane
brew cast install fastlane
在系统的shell profile文件(如:~/.bash_profile)中设置环境变量:
export LC_ALL=en_US.UTF-8 export LANG=en_US.UTF-8
在本机上安装好fastlane之后,接下来我们可以set up fastlane。
Set up fastlane
在React Native项目根目录下运行下面的命令:
cd ios fastlane init
上面的命令运行完之后,会生成下图中的目录。
Appfile:该文件存储apple_id、app_identifier信息,一般不用修改
Fastfile:该文件包含所有用于发布app的信息
iOS beta deployment
打包 iOS App
fastlane使用gym acttion打包iOS App,将下面代码添加到fastfile文件中:
lane :beta do gym(scheme: "MyApp") end
运行这个lane:
fastlane ios beta
如果运行成功,会得到一个.ipa的文件。但通常我们会遇到一些问题。
配置xcode
设置bundle identifier同AppFile里的app_identifier
设置Signing - 不选中“Automatically manage signing”,使用手动的方式管理code signing。
设置Signing(Release)为release所用的code signing,我们这里没有使用fastlane的match来进行管理,而是使用手动管理的方式。
上传到TestFlight
lane :beta do # 每次build,先从TestFlight取得最新的build number, 再加1 increment_build_number( build_number: latest_testflight_build_number + 1, xcodeproj: "MyApp.xcodeproj" ) # 打包 app gym(scheme: "MyApp") # 上传至TestFlight pilot(skip_waiting_for_build_processing: true) end
至此,我们完成了fastlane iOS beta deployment在本地的配置,已经能够正常打包
fastlane进行android app beta deployment
在打包iOS app的时候,我们需要code signing,而android则需要google json key,以及签名密钥。
生成 release APK
生成签名密钥
可以使用keytool命令行工具直接生成一个私有的签名密钥:
keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
这条命令会要求你输入密钥库(keystore)和对应密钥的密码,然后设置一些与发行相关的信息。最后会生成一个叫做my-release-key.keystore的密钥库文件,密钥的有效期为10000天(特别注意:密钥的有效期一旦设定,后期无法修改)。
设置gradle变量
将my-release-key.keystore文件,放在项目的android/app目录下;
修改~/.gradle/gradle.properties 或 android/app/gradle.properties(我们项目修改的是这个)文件,添加下面几句(将*替换为自己实际设置的密码):
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore MYAPP_RELEASE_KEY_ALIAS=my-key-alias MYAPP_RELEASE_STORE_PASSWORD=***** MYAPP_RELEASE_KEY_PASSWORD=*****
添加签名到项目的gradle配置文件
修改项目中的android/app/build.gradle文件并添加签名配置:
android { ... defaultConfig { ... } signingConfigs { release { if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) { storeFile file(MYAPP_RELEASE_STORE_FILE) storePassword MYAPP_RELEASE_STORE_PASSWORD keyAlias MYAPP_RELEASE_KEY_ALIAS keyPassword MYAPP_RELEASE_KEY_PASSWORD } } } buildTypes { release { ... signingConfig signingConfigs.release } } }
生成 release APK
cd android && ./gradlew assembleRelease
只需运行上面的命令,就可以生成android release APK。生成的APK可以在
android/app/build/outputs/apk/app-release.apk路径找到。
做完上面的这些,我们就可以来配置fastlane来自动打包android apk并beta deploy到Crashlytics.
Set up fastlane
在React Native项目根目录下运行下面的命令:
cd android fastlane init
运行fastlane init时,会要求输入google service json文件,可以先不填,后续取得json文件之后更新到android/fastlane/Appfile文件里(参考:collect your google credentials)。
上面的命令运行完之后,会在android目录下生成fastlane文件夹,里面主要有下面两个文件:
Appfile:该文件存储json_key_file(该字段用来设置上面说到的google service json文件目录)、package_name信息
Fastfile:该文件包含所有用于发布app的信息
android beta deployment
由于我们选择将android app beta deploy到crashlytics,所以需要先给项目配置crashlytics。
- 首先到Fabric官网申请帐号并登录,会提示需要到android studio安装fabric插件。
- 按提示在android studio上安装好fabric插件之后,点击fabric图标,会出现如下图所示界面
- 在fabric界面登录之后,一直向下选择,直到出现如下界面,先择Crashlytics,按提示进行配置即可(初次配置可能要等好几分钟)
配置 beta lane
lane :beta do # 打包android app gradle( task: "assembleRelease", )
上传android app至crashlytics
crashlytics(api_token: "YOUR_FABRIC_CRASHLYTICS_API_TOKEN", build_secret: "YOUR_FABRIC_CRASHLYTICS_BUILD_SECRET") end
上面crashlytics的api_token以及build_secret可以在fabric origanizations里找到。
运行下面的命令,即可打包android app并发布到crashlytics。cd android && fastlane android beta
在Fabric Crashlytics上查看你的app