背景
未自动化前安卓开发总是避免不了这样的工作流程:
- 1.开发一些新功能,提交代码
- 2.完成一部分功能后,打包一个测试版APK
- 3.将测试版APK上传到QQ群 / Fir.im / 蒲公英 等
- 4.在QQ群或发布平台解释当前版本所完成的功能
- 5.通知测试人员测试
实现了这套自动化发布后,工作流程被简化成:
- 1.开发新功能,提交代码
- 2.通过
git tag对代码打一个内测版的tag,在tag的描述中对写当前完成的功能
Tag 提交后 Travis CI 会自动编译代码,生成APK文件并分发到 Github 和 fir.im ,Github 和 fir.im 中会保持 Tag 的描述信息,分发完成后会有邮件通知所有参与测试的人员。而作为开发人员,只需要专注于对代码打好一个 Tag 就可以了。
什么是 Travis CI
简单来说它是用来做持续集成的工具,可以为你自动构建、测试、打包等等,极大的简化了工作流程。它对
Github的支持特别好,链接到你在Github上的项目以后,每当你把测试通过后的代码提交到master去,它会pull你的代码并按照你的要求构建执行。
安装 Ruby 和Travis CI
1.首先要安装 Ruby, 安装完成后可以用 ruby -v 检查系统是否安装 Ruby
$ ruby -v
ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
2.然后运行下面命令安装 travis
$ gem install travis
还可能遇到这个问题:[connection was forcibly closed by the remote host](Errno::ECONNRESET: An existing connection was forcibly closed by the remote host),这个就是 gem 仓库访问不到,也就是你需要翻墙,而大部分翻墙也不好使,这就需要添加国内的 gem 源,这里有两个:
$ gem sources --add https://ruby.taobao.org/ --remove https://rubygems.org/
$ gem sources -l
此处可能会遇到证书错误:关于 Windows 下证书无法验证问题 (certificate verify failed)
如果淘宝镜像不能使用了,建议换成Ruby-China镜像:
$ gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
$ gem sources -l
3.安装完毕后检查一下:
$ travis -v
1.8.8
配置 Travis CI 项目
首先进入 Travis CI 官网,官网有两个网站,travis-ci.org/ 和 travis-ci.com/ 这两个网站除了域名不一样之外,其他的操作基本一样,前者展示开源项目,后者展示私有付费项目。
We're only showing your public repositories on travis-ci.org. You can find your private projects on travis-ci.com.
进入官网之后会看到下面图标,然后用 GitHub 账号登录:
按照官网上分为三大步骤:
选择哪个项目使用 Travis CI 构建,把开关打开就可以了
在项目的根目录下新建一个文件 .travis.yml ,如下是一个 Android 项目的配置模板, 点击进入 官网Android配置模板:
language: android
android:
components:
# Uncomment the lines below if you want to
# use the latest revision of Android SDK Tools
# - tools
# - platform-tools
# The BuildTools version used by your project
- build-tools-26.0.2
# The SDK version used to compile your project
- android-26
# Additional components
- extra-google-google_play_services
- extra-google-m2repository
- extra-android-m2repository
- addon-google_apis-google-26
# Specify at least one system image,
# if you need to run emulator(s) during your tests
- sys-img-armeabi-v7a-android-26
- sys-img-armeabi-v7a-android-17
当 Travis CI 准备好我们所需要的环境后,将自动运行 yml 文件 script 部分所设置的指令,上例中运行的是 ./gradlew assembleRelease ,运行成功的话会在项目的主模块下生成 build/outputs/apk/app-release.apk ,如下:
script:
- "./gradlew assembleRelease"
Android 项目自动化构建的密码和证书安全问题
安卓项目发布需要证书文件和若干密码,但无论是开源项目还是私有项目,任何时候都不应该将原始证书或密码放入代码库(原则上来讲证书和密码也不应该交于开发人员,而应该只能通过发布服务器进行编译)。Travis CI 为此提供了2种解决方案,一种是对敏感信息、密码、证书等进行对称加密,在CI构建环境时解密,另一种是将密码等通过 Travis CI 的控制台(即网站)设置为构建时的环境变量。
由于前者会在 Travis 控制台生成一对环境变量,所以我的做法是尽量选择后者,但由于 Travis 控制台无法上传文件,因此涉及到文件加密的部分,则只能选择前者。
说了这么多,首先还是需要先对编译脚本进行改造,如果不考虑安全问题,项目的 build.gradle 文件可能会是这样:
android {
signingConfigs {
releaseConfig {
storeFile file("../cxz.jks")
storePassword "xxxxxx"
keyAlias "key_alias"
keyPassword "xxxxxx"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.releaseConfig
}
}
}
而我们最终要的效果,还是希望一份编译脚本既可以用于开发环境,也可以在CI环境下使用,在 Travis CI 中,可以通过点击 项目名称 -> Settings -> Environment Variables 中设置环境变量,比如我们可以针对上面的配置,分别设置 KEYSTORE_PASS 、 ALIAS_NAME 、 ALIAS_PASS 三个环境变量,可以通过下图所示的右下角的 Add 按钮增加环境变量:
在 Travis CI 环境下可以通过 System.getenv() 获得这些环境变量
本地开发环境中,我的做法是将这几个变量加到 gradle.properties 文件中,这样就可以在 build.gradle 内直接使用了。下面是开发环境的 gradle.properties :
KEYSTORE_PASS=xxxxxx
ALIAS_NAME=key_alias
ALIAS_PASS=xxxxxx
build.gradle修改如下:
releaseConfig {
storeFile file("../cxz.jks")
storePassword project.hasProperty("KEYSTORE_PASS") ? KEYSTORE_PASS : System.getenv("KEYSTORE_PASS")
keyAlias project.hasProperty("ALIAS_NAME") ? ALIAS_NAME : System.getenv("ALIAS_NAME")
keyPassword project.hasProperty("ALIAS_PASS") ? ALIAS_PASS : System.getenv("ALIAS_PASS")
}
接下来处理证书文件,点击 Encrypting-files进入官方文档查看,执行下面命令对文件进行加密:
travis encrypt-file xx.jks --add
如果首次运行,travis 会提示需要登录,运行 travis login --org 并输入 Github 用户名密码即可。(付费版则为 travis login --pro )
travis encrypt-file 指令会做几件事情:
- 在
Travis CI控制台自动生成一对密钥:encrypted_639db8c6f794_iv和encrypted_639db8c6f794_key; - 基于密钥通过
openssl对文件进行加密,上例中会项目根目录生成cxz.jks.enc文件 - 在
.travis.yml中自动生成Travis CI环境下解密文件的配置,上例运行后可以看到.travis.yml中多了几行:before_install: - openssl aes-256-cbc -K $encrypted_639db8c6f794_key -iv $encrypted_639db8c6f794_iv -in cxz.jks.enc -out cxz.jks -d
最后别忘了在 .gitignore 中忽略 cxz.jks 以及 gradle.properties 并在代码库中将其删除。
注意: 在生成证书文件可能会报一个错误
还请认真看官方文档,Encrypting-files里面有这样一句话:
Caveat # There is a report of this function not working on a local Windows machine. Please use the WSL (Windows Subsystem for Linux) or a Linux or OS X machine.
也就是说 windows不支持这个功能,请使用Linux或者OS X。
我也用 linux 和 OS X 实际验证了一下,加密文件的时候,生成.enc文件时,在线解密的时候的确不会报错。
Travis Ci自动发布安装apk文件到Github Release
在 Github -> settings -> Personal access tokens 生成一个只能访问当前项目并只有读取权限的 Github Access Token ,并通过 Travis CI 将 Access Token 加密。听起来有点繁琐,好在 Travis CLI 中已经可以通过一行指令做好这一切:
$ travis setup release
根据提示填写上述配置项目的信息后,Travis CLI 会自动在 .travis.yml 文件中生成好所有的配置项:
deploy:
provider: releases
api_key:
secure: xxxxx
file: app/build/outputs/apk/release/app-release.apk
on:
repo: bjchenxz/TravisDemo
tags: true
all_branches: true
provider:发布目标为Github Releaseapi_key:secure就是加密后的Access Token,Github用户名和密码,因为Travis CI要上传APK文件,因此需要有Github项目的写入权限file: 发布文件,输入文件路径即可skip_cleanup: 默认情况下Travis CI在完成编译后会清除所有生成的文件,因此需要将skip_cleanup设置为true来忽略此操作。on: 发布的时机,这里配置为tags: true,即只在有tag的情况下才发布。
注意: 如果报一下信息,那不是构建出错了,是因为没有打 tag
Skipping a deployment with the releases provider because this is not a tagged commit
自动发布到 Apk 到 fir.com
在 .travis.yml 中添加以下几行:
before_install:
- gem install fir-cli
after_deploy:
- fir p app/build/outputs/apk/release/app-release.apk -T $FIR_TOKEN -c "`git cat-file tag $TRAVIS_TAG`"
其中 FIR_TOKEN 可以在 fir.im 的用户-> API Token 中找到,然后在 Travis CI 控制台中创建环境变量 FIR_TOKEN 并粘贴即可。
自动发布到 Apk 到 蒲公英
参考地址:www.pgyer.com/doc/view/tr…
总结
所有的 yml 文件配置就那么几十行,就能省去繁琐的日常工作,何乐而不为呢。最后回顾一下自动化后的日常工作:
提交代码:
git add .
git commit -m "注释"
git push origin
打 tag :
git tag -a v0.0.1-alpha.1 -m "Tag注释,说清楚这个版本的主要改动,也可以省略-m参数直接写长文本"
git push origin --tags
如果发现打错了 tag ,可以删除本地及远程 tag
git tag -d v0.0.1-alpha.1
git push origin --delete tag v0.0.1-alpha.1
最后这是我集成 Travis CI 的项目地址,仅供参考:github.com/bjchenxz/Tr…