且听疯吟如此生活三十年
使用 Travis CI 自动部署 React Native 项目 (iOS 篇)

编译、测试、打包、部署这一系列的操作实在是太麻烦而且容易出错漏,能自动化的东西我们就没必要手动去点。端着咖啡悠哉地等着叮的一声,安装包出现在面前,这才是我们想要的
花了点时间,把正在进行的 React Native 项目的自动部署完善了一下,实现了通过 Travis CI 自动编译测试,并打包成 ipa 发布到 FTP 的整个流程
现在只要 Push 到 Github 上,等到 Travis CI 运行完成,就直接可以拿到 ipa 包安装测试了

准备工作:
首先你需要一个 Github 账户
Travis CI 连接 Gtihub 后,会自动检查根目录下带有 .travis.yml 的项目
关于 Travis CI 的功能和文档,请参考 https://docs.travis-ci.com/

这里给出一个 React Native 项目的 yml 文件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
language: objective-c
osx_image: xcode7.1
xcode_project: ios/MyApp.xcodeproj
xcode_scheme: MyApp
env:
matrix:
- SPEC=spec1

before_install:
- ./scripts/decrypt_key.sh
- ./scripts/add_key.sh
- brew update

install:
- brew reinstall node flow watchman xctool
- npm install -g react-native-cli

branches:
only:
- master

script:
- ./scripts/release.sh

首先设置项目编译环境:

包括 language 和 要使用的编译镜像 osx_image,并指定项目文件和编译的 scheme

证书加密:

由于 iOS 打包过程需要一些证书密钥,这些是无法公开 Push 到 Github 的
虽然 Travis CI 没有提供 security file 的功能,但是提供了一个 security 的环境变量的功能
因此,我们可以通过在本地加密证书然后上传,线上编译时再解开来实现这一目的

比如:

  • Encrypt
1
2
3
4
# encrypt_key.sh
openssl aes-256-cbc -k ${ENCRYPT_PASS} -in scripts/MyAppdev.mobileprovision -out scripts/MyAppdev.mobileprovision.enc -a
openssl aes-256-cbc -k ${ENCRYPT_PASS} -in scripts/dist.cer -out scripts/dist.cer.enc -a
openssl aes-256-cbc -k ${ENCRYPT_PASS} -in scripts/dist.p12 -out scripts/dist.p12.enc -a
  • Decrypt
1
2
3
4
# decrypt_key.sh
openssl aes-256-cbc -k ${ENCRYPT_PASS} -in scripts/MyAppdev.mobileprovision.enc -out scripts/MyAppdev.mobileprovision -d -a
openssl aes-256-cbc -k ${ENCRYPT_PASS} -in scripts/dist.cer.enc -out scripts/dist.cer -d -a
openssl aes-256-cbc -k ${ENCRYPT_PASS} -in scripts/dist.p12.enc -out scripts/dist.p12 -d -a

注意: 请不要直接上传你的证书和密钥!也不要把密码上传到公开的地方!

导入证书到 Travis 编译环境:

参考下面的步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# add_key.sh

# Create a custom keychain
security create-keychain -p travis ios-build.keychain

# Make the custom keychain default, so xcodebuild will use it for signing
security default-keychain -s ios-build.keychain

# Unlock the keychain
security unlock-keychain -p travis ios-build.keychain

# Set keychain timeout to 1 hour for long builds
# see http://www.egeek.me/2013/02/23/jenkins-and-xcode-user-interaction-is-not-allowed/
security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain

# Add certificates to keychain and allow codesign to access them
security import ./scripts/apple.cer -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
security import ./scripts/dist.cer -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
security import ./scripts/dist.p12 -k ~/Library/Keychains/ios-build.keychain -P $KEY_PASS -T /usr/bin/codesign


# Put the provisioning profile in place
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp "./scripts/MyAppdev.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/

安装环境

安装编译所需要的环境,比如 xctool、node、npm、react-native 等等

编译和打包

举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# release.sh

npm install

react-native bundle --dev false --platform ios \
--bundle-output "/tmp/main.jsbundle" --entry-file index.ios.js

xctool -project ios/MyApp.xcodeproj -scheme MyApp build -sdk iphoneos \
configuration Release OBJROOT=$PWD/build SYMROOT=$PWD/build

if [[ $? != 0 ]];then
echo ">> build failed"
exit 1;
fi

PROVISIONING_PROFILE="$HOME/Library/MobileDevice/Provisioning Profiles/MyAppdev.mobileprovision"
OUTPUTDIR="$PWD/build/Release-iphoneos"
NAME=Esports_${TRAVIS_COMMIT:0:6}.ipa

xcrun -log -sdk iphoneos PackageApplication "$OUTPUTDIR/MyApp.app" \
-o "$OUTPUTDIR/$NAME"

if [[ $? != 0 ]];then
echo ">> package application failed"
exit 1;
fi

cd $OUTPUTDIR
curl --ftp-create-dirs -T "$NAME" -u $FTP_USER:$FTP_PASSWORD \
ftp://$FTP_SERVER/esports/$NAME

echo ">> {$NAME} uploaded!"
echo ">> all done!"

基本上和本地编译运行 React Native 项目类似,不同之处在于使用了 xctool 命令行来编译

  • 首先安装依赖 package
  • 然后 react-native bundle (如果使用 online 的模式,可以忽略这一步)
  • 使用 xctool 编译和测试项目
  • 打包 App 为 ipa 文件
  • FTP 发布(Travis CI 支持多种发布方式,可以参考文档实现)
  • 完成,邮件或 IM 通知(如果你需要)

ref: https://www.objc.io/issues/6-build-tools/travis-ci/