CI
CI (Continuous Integration,持續(xù)集成),CI 是 XP(Extreme Programming,極限編程)的實(shí)踐之一。近年來
人們普遍使用 Jenkins 等軟件來實(shí)現(xiàn)這一目的柬批。
讓 CI 軟件監(jiān)視倉庫,可以在開發(fā)者發(fā)送提交后立刻執(zhí)行自動測試或構(gòu)建味混。通過持續(xù)執(zhí)行這樣一個(gè)操作,可以檢測出開發(fā)者意外發(fā)送的提交或無意的邏輯偏差,讓代碼保持在一定質(zhì)量以上窃植。
在現(xiàn)代的軟件開發(fā)中持續(xù)集成已經(jīng)不可或缺,甚至逐漸成為開發(fā)中的常識箩祥。在開源世界中也是同樣志电。
常見的CI有: Travis CI 骇笔、 Jenkins 、Circle CI
基于Travis CI的Android自動發(fā)布流程
Travis CI對Github上的開源Repo是免費(fèi)的竿拆,私有Repo收費(fèi)宙拉。
可以將表示Travis CI的執(zhí)行結(jié)果的圖片嵌入到markdown中
,這個(gè)圖片在很多GitHub上的項(xiàng)目中都有見到丙笋。Travis CI使用YAML文件作為構(gòu)建腳本惫企。
這里我們利用Travis CI來自動根據(jù)我們打的Git Tag來構(gòu)建APK并Push到自己的Github Release上(也可設(shè)置分發(fā)到fir.im)晃虫。
使GitHub帳號登錄Travis CI;點(diǎn)擊右上將腳的頭像在岂,點(diǎn)擊"Sync account"按鈕豫缨,然后打開對自己項(xiàng)目的Hook開關(guān)缩举;最后在對應(yīng)的項(xiàng)目中添加.travis.yml
文件來配置 Travis CI即可洁奈。
使用Travis CI時(shí)串慰,剛開始一直無法發(fā)現(xiàn)倉庫里面的其它分支;后來再倉庫頁面 setting -> Integrations & services -> ... -> Test serviece 笙各;對其進(jìn)行測試后钉答,Travis CI才有反映。
Android項(xiàng)目對應(yīng)的 .travis.yml 文件
下面是一個(gè)簡單的Android項(xiàng)目下的 .travis.yml 文件
# .travis.yml 文件
# 聲明構(gòu)建語言環(huán)境
language: android
android: # 配置信息
components:
# 你可能需要修改下面兩項(xiàng)的版本
- build-tools-25.0.0
- android-25
# Android Support Repository
- extra-android-m2repository
# Support Library
- extra-android-support
script:
# 生成 APK
- ./gradlew assembleRelease
# 部署
deploy:
# 部署到GitHub Release酪惭。
# 除此之外希痴,Travis CI還支持發(fā)布到fir.im者甲、AWS春感、Google App Engine等
provider: releases
# Github oauth token
api_key: "GITHUB OAUTH TOKEN"
# 部署文件路徑;對于Android就部署生成的 apk 文件
file: "FILE TO UPLOAD"
# 避免 Travis CI在部署之前清空生成的APK文件
skip_cleanup: true
# 發(fā)布時(shí)機(jī)
on:
# tags設(shè)置為true表示只有在有tag的情況下才部署
tags: true
先來測試上面的文件。 創(chuàng)建一個(gè)簡單的Android工程進(jìn)行測試鲫懒;在工程的根目錄添加 上述 .travis.yml 文件嫩实。
根據(jù)實(shí)際情況修改文件中相關(guān)內(nèi)容,這里修改file: app-release-unsigned.apk
窥岩;還有api_key就參考下文 "方法一:將GitHub的token設(shè)置為環(huán)境變量"
然后測試 Travis CI服務(wù):
GitHub對應(yīng)倉庫頁面 setting -> Integrations & services -> ... -> Test serviece
這里生成的 app-release-unsigned.apk
并沒有進(jìn)行過簽名甲献。
一份示例文件: android_Travis_CI_Test/travis.yml.1.bak
Travis CI中有這樣一句提示: Please note that deploying GitHub Releases works only for tags, not for branches.
在這里可以檢測你的.travis.yml
有沒有基本的語法錯(cuò)誤: Validate your .travis.yml file
遇到的問題
錯(cuò)誤1:
Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain
原因:推送到GitHub中的Android項(xiàng)目中沒有: gradle/wrapper/gradle-wrapper.jar
文件(被.gitignore_global忽略了)。
錯(cuò)誤2:
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':app'.
> You have not accepted the license agreements of the following SDK components:
[ConstraintLayout for Android 1.0.2, Solver for ConstraintLayout 1.0.2].
Before building your project, you need to accept the license agreements and complete the installation of the missing components using the Android Studio SDK Manager.
如果使用了ConstraintLayout則會出現(xiàn)錯(cuò)誤2颂翼。
上面的意思是:您尚未接受以下SDK組件的許可協(xié)議:[ConstraintLayout for Android 1.0.2晃洒,Solver for ConstraintLayout 1.0.2]。在構(gòu)建項(xiàng)目之前朦乏,您需要接受許可協(xié)議球及,并使用Android Studio SDK Manager完成缺少組件的安裝。
解決辦法在文件中添加如下內(nèi)容:
before_install:
- mkdir "$ANDROID_HOME/licenses" || true
- echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "$ANDROID_HOME/licenses/android-sdk-license"
- echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_HOME/licenses/android-sdk-preview-license"
Accept ConstraintLayout licenses · Issue #6617 · travis-ci/travis-ci
android - Travis CI failed because cannot accept license Constrain Layout - Stack Overflow
錯(cuò)誤3:
Dpl does not have permission to upload assets. Make sure your token contains the repo or public_repo scope.
dpl.2
Preparing deploy
failed to deploy
之前誤以為 public access
就是public_repo
呻疹;回到 GitHub頁面修改token的訪問權(quán)限吃引,添加 public_repo
scope 然后更新。
錯(cuò)誤4:
/home/travis/.rvm/gems/ruby-2.2.7/gems/octokit-4.6.2/lib/octokit/client/releases.rb:86:in `initialize': No such file or directory @ rb_sysopen - app/build/outputs/apk/app-release.apk (Errno::ENOENT)
/home/travis/.rvm/gems/ruby-2.2.7/gems/octokit-4.6.2/lib/octokit/client/releases.rb:86:in `initialize': No such file or directory @ rb_sysopen - app/build/outputs/apk/app-debug.apk (Errno::ENOENT)
在部署前使用ls命令查看app/build/outputs/apk/
路徑下的文件刽锤。添加如下語句:
before_deploy:
- ls app/build/outputs/apk/
Log輸出:
$ ls app/build/outputs/apk/
app-release-unsigned.apk
解決方法:
為構(gòu)建添加緩存
構(gòu)建速度好慢镊尺,嘗試添加緩存:
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
手動清楚緩存:
加密自動化構(gòu)建中使用到的密碼和token
自動化構(gòu)建中需要用到密碼和證書并思,我們必須保證的安全性庐氮。為此Travis CI為此提供了2種解決方案:
- 一種是對敏感信息、密碼纺荧、證書旭愧、token等進(jìn)行對稱加密,在CI構(gòu)建環(huán)境時(shí)解密
- 另一種是將密碼等通過Travis CI的控制臺(即網(wǎng)站)設(shè)置為構(gòu)建時(shí)的環(huán)境變量宙暇。
獲取GitHub的認(rèn)證
將apk部署到GitHub Release需要向Github傳送文件输枯,就需要獲得GitHub的相關(guān)認(rèn)證。
獲取認(rèn)證的方法:
- 可以是在配置文件
.travis.yml
中使用明文密碼占贫。極不安全桃熄。 - 或使用 Github Personal Access Token 進(jìn)行驗(yàn)證。下面介紹型奥。
創(chuàng)建 Github Personal Access Token
在Github -> settings -> Personal access token 生成一個(gè)勾選了public_repo scope
的Github Personal Access Token瞳收。
生成 token: Github auth token on TravisCI
Creating a personal access token for the command line - User Documentation
生成了Github Personal Access Token后我們就將其應(yīng)用到 .travis.yml
中。
應(yīng)用Github Personal Access Token的兩種方法
方法一:將GitHub的token設(shè)置為環(huán)境變量
- 在Travis CI網(wǎng)站中對應(yīng)的項(xiàng)目頁面厢汹,點(diǎn)擊"More options"然后選擇上圖中的 setting 螟深。
- 在“Environment Variables”下添加環(huán)境變量:這里我添加 "GH_TOKEN"變量名稱,值就復(fù)制你之前生成的token烫葬,并確保"Display value in build log" 為"OFF"狀態(tài)界弧。
然后在.travis.yml
文件中這樣使用該環(huán)境變量:
api_key:
secure: ${GH_TOKEN}
Github Personal Access Token在第一次復(fù)制后就會自動隱藏凡蜻,無法再次查看;如果忘記了token就只有重新生成 token垢箕。
方法二:在本地安裝travis并使用travis的相關(guān)命令對token進(jìn)行加密
token可以重復(fù)使用划栓,但是對于特定的倉庫必須重新運(yùn)行上面的命令進(jìn)行加密并指定倉庫。
- 安裝ruby条获≈臆瘢可參考:Ubuntu安裝ruby到opt下的rbenv目錄
- 查詢最新的Travis CI的版本:
gem search travis
。我這里是 travis (1.8.8) - 安裝該版本的travis:
gem install travis -v 1.8.8 --no-rdoc --no-ri
- 查看是否安裝完成:
travis --version
帅掘,然后會提示你“shellcompletion not installed ...” shell補(bǔ)全沒有安裝是否需要安裝委煤,輸入 y。重新打開終端即可對該命令使用tab補(bǔ)全修档。 - 如果首次運(yùn)行素标,travis會提示需要登錄,可以通過運(yùn)行
travis login
并輸入Github用戶名密碼即可萍悴⊥吩猓或者如果你不想輸入密碼,使用travis login --github-token <之前生成的github-token>
也可進(jìn)行登錄癣诱。 - 更簡單一點(diǎn)的是直接使用
travis encrypt <之前生成的token> -r <owner>/<repo>
其中-r
用于指定倉庫计维。然后有根據(jù)命令輸出添加相關(guān)信息到.travis.yml
文件。示例:deploy: api_key: secure: "XR0ZYSp+eWOhHwO0az80nEZoOOyaOIeV7brTekEdl7APUfPziQHrV4G/xPxPZB2Fcn13efyiwpPbmXpSVkIqJJZg2Ok/efBviUIwgl5pqGrddgXEskW8+lebHJA/17JjmXoo2ZT9BcmMlVrT0Dj5WCJXH2QOSAXzVy/9DO7e3pEijAImCHgh0oH/hQzlO86IMBn3Fzlb520bplEI4fnuJNU/nKZrl05dTRCso2ZB2/MXt1X5vfYm4zrwjTgZXOpfSVur6kv/EMNQFDiGLa3F22m1FDQULDfHY7evT79hYlcRKVGx7hoQRrOxXr0Ag6wcb+4buvwaxutNPjaEXkH3FfocrIGxZtox1kE19ebqjc6fT/CH85Lf+AqT2rR86Wr5aaEQcKAxNZxUJtir5MAIo0j7vkx1PUi0MCb9K6JHca9lkFsoYP1L0pjDztD8w4J15rv5TCV/JjMxhCGQkGwDH+M3Z7dQOgikoRaO11o6C5/fC8qfCeGKT3GzL9966dy0UY9ZDQbB7y3donlWgoTZHn6xahGNlP4CYiP6Ax94egDmbSmyiJud5Y0NmwXMY0IEuJPWEFkmBdGEbZuqqsL3mxqxebox7q7gz613ToZSsfbNhKw3ouETftjXoMnlfRFIl7LSAOwAtL5Wig5zlwCMafGTFaGpLH0zl02Udjy3UbU="
- 或者使用命令
travis encrypt GITHUB_TOKEN=<之前生成的token> -r <owner>/<repo>
,加密環(huán)境變量GITHUB_TOKEN撕予。其中-r
用于指定倉庫鲫惶。這里解密之后得到GITHUB_TOKEN=<之前生成的token>
而并非<之前生成的token>
。
對于加密環(huán)境變量GITHUB_TOKEN
的形式实抡,需這樣使用:
env:
global:
secure: "XR0ZYSp+eWOhHwO0az80nEZoOOyaOIeV7brTekEdl7APUfPziQHrV4G/xPxPZB2Fcn13efyiwpPbmXpSVkIqJJZg2Ok/efBviUIwgl5pqGrddgXEskW8+lebHJA/17JjmXoo2ZT9BcmMlVrT0Dj5WCJXH2QOSAXzVy/9DO7e3pEijAImCHgh0oH/hQzlO86IMBn3Fzlb520bplEI4fnuJNU/nKZrl05dTRCso2ZB2/MXt1X5vfYm4zrwjTgZXOpfSVur6kv/EMNQFDiGLa3F22m1FDQULDfHY7evT79hYlcRKVGx7hoQRrOxXr0Ag6wcb+4buvwaxutNPjaEXkH3FfocrIGxZtox1kE19ebqjc6fT/CH85Lf+AqT2rR86Wr5aaEQcKAxNZxUJtir5MAIo0j7vkx1PUi0MCb9K6JHca9lkFsoYP1L0pjDztD8w4J15rv5TCV/JjMxhCGQkGwDH+M3Z7dQOgikoRaO11o6C5/fC8qfCeGKT3GzL9966dy0UY9ZDQbB7y3donlWgoTZHn6xahGNlP4CYiP6Ax94egDmbSmyiJud5Y0NmwXMY0IEuJPWEFkmBdGEbZuqqsL3mxqxebox7q7gz613ToZSsfbNhKw3ouETftjXoMnlfRFIl7LSAOwAtL5Wig5zlwCMafGTFaGpLH0zl02Udjy3UbU="
deploy:
api_key:
secure: ${GITHUB_TOKEN}
這里可以對
secure: 字串
的作用做一個(gè)猜測: Travis讀取到 secure 時(shí)便會解密該字串欠母,并將解密后得到的值替換 secure 這行內(nèi)容。比如如果加密的是變量=值
吆寨,那么當(dāng)其出現(xiàn)在上文的global:
時(shí)赏淌,就是定義了一個(gè)全局的環(huán)境變量,然后就可在后面使用該變量啄清。
- 另外還可以直接使用
travis setup releases
命令:
GitHub Releases Uploading - Travis CI六水。
可以使用
travis help encrypt
查看命令幫助;
使用travis repos
列出所有倉庫辣卒;參考:travis-ci/travis.rb: Travis CI Client (CLI and Ruby library)
加密簽名apk時(shí)使用到的密碼和keystore文件(方式一)
事先創(chuàng)建好key和keystore文件掷贾。 這里我把keystore文件的后綴名變?yōu)榱?keystore,大家使用的都是 .jks
1荣茫、 加密keystore文件my.keystore
: travis encrypt-file my.keystore -r FanDean/android_Travis_CI_Test
想帅。根據(jù)命令輸出的提示,將加密后的keystore文件 my.keystore.enc 放入Android工程的根目錄啡莉;并在 .travis.yml
文件中添加如下內(nèi)容:
before_install:
- openssl aes-256-cbc -K $encrypted_f6c9a5f058a8_key -iv $encrypted_f6c6a5f053a8_iv -in my.keystore.enc -out my.keystore -d
2港准、 加密keystore password 憎乙、 key password 和 keyAlias。方法和加密 GitHub Token 一樣叉趣;也可使用添加環(huán)境變量的方式。
這里我們準(zhǔn)備下面三個(gè)環(huán)境變量该押,并通過在travis網(wǎng)站添加環(huán)境變量的形式進(jìn)行添加:
- KEYSTORE_PWD
- KEY_PWD
- KEY_ALIAS
具體添加方式略(后面我們使用另外一種方法)疗杉。
.travis.yml
文件中添加如下內(nèi)容對apk進(jìn)行簽名:
before_deploy:
- cp $TRAVIS_BUILD_DIR/.keystore $HOME
# 記住這里已經(jīng)將當(dāng)前工作目錄切換到 apk 下
- cd app/build/outputs/apk/
# Signing 簽名
- jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore $HOME/my.keystore -storepass $KEYSTORE_PWD -keypass $KEY_PWD app/build/outputs/apk/app-release-unsigned.apk $KEY_ALIAS
# Verification 驗(yàn)證您的 APK 是否已簽署
- jarsigner -verify app-release-unsigned.apk
- "${ANDROID_HOME}/build-tools/24.0.2/zipalign -v 4 app-release-unsigned.apk app-release.apk"
jarsigner
- JAR Signing and Verification Tool;也可以用來對apk進(jìn)行簽名蚕礼。
看起來比較麻煩烟具。
加密簽名apk時(shí)使用到的密碼和keystore文件(方式二)
參考下面的文章,我們可以使用一種新的方式:
- 保護(hù)您的密鑰 - 簽署您的應(yīng)用
- 構(gòu)建未簽署 APK 并手動簽署它 - 簽署您的應(yīng)用
- 基于Travis CI搭建Android自動打包發(fā)布工作流(支持Github Release及fir.im)
- android - Sign APK without putting keystore info in build.gradle - Stack Overflow
創(chuàng)建并加密 keystore.properties 文件
在Android項(xiàng)目根目錄創(chuàng)建 keystore.properties
文件保存keyPwd等變量奠蹬。
storePwd=***
keyPwd=***
keyAlias=test_key
storeFileLocal=/home/fan/.android/my_keystore/my.keystore
storeFileCI=../my.keystore
同樣加密 keystore.properties
文件: travis encrypt-file keystore.properties -r FanDean/android_Travis_CI_Test
同樣添加 "openssl aes-256-cbc -K $encrypted_ad23ea9b533c_key -iv $encrypted_ad23ca6e583c_iv -in keystore.properties.enc -out keystore.properties -d" 到 before_install 下面朝聋。
修改app/build.gradle 文件
然后在 app/build.gradle 文件中添加如下內(nèi)容,用于保護(hù)您的密鑰和判斷當(dāng)前是在本地還是在 CI服務(wù)器:
// Create a variable called keystorePropertiesFile, and initialize it to your
// keystore.properties file, in the rootProject folder.
def keystorePropertiesFile = rootProject.file("keystore.properties")
// Initialize a new Properties() object called keystoreProperties.
def keystoreProperties = new Properties()
// Load your keystore.properties file into the keystoreProperties object.
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
def keyStoreFile = file(keystoreProperties['storeFileLocal'])
// 判斷是位于本地還是CI服務(wù)器
if (!keyStoreFile.exists()){
keyStoreFile = file(keystoreProperties['storeFileCI'])
}
android {
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPwd']
storeFile keyStoreFile
storePassword keystoreProperties['storePwd']
}
}
...
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
...
忽略 keystore.properties文件
在 .gitignore_global 文件中添加:
keystore.properties
一些配置
script: ./gradlew testRelease assembleRelease
script:
- "./gradlew clean build connectedCheck -PdisablePreDex --stacktrace"
Travis Config · kawa89/Testing Wiki
script:
- ./travis/test.sh
./gradlew clean testDebugUnitTest
./gradlew connectedAndroidTest --info
./gradlew clean assembleDebug
GoIV/.travis.yml at master · farkam135/GoIV
script:
- ./gradlew assembleDebug testOnlineDebugUnitTest testOfflineDebugUnitTest checkstyle
查找
android .travis.yml
的相關(guān)配置囤躁,可嘗試在GitHub中搜索 "android travis"然后選擇查看 issues 和 wiki 冀痕。
參考:
- Building an Android Project - Travis CI
- GitHub-Android持續(xù)集成 - skyJC
- 用Travis CI給Android項(xiàng)目部署Github Release · Kesco Lin
- 基于Travis CI搭建Android自動打包發(fā)布工作流(支持Github Release及fir.im)
- Travis CI Android example – Matti – Medium 完整示例,并且提供了對應(yīng)的 GitHub 示例狸演。推薦言蛇。
-
Adding GitHub token to Travis CI configuration
Github auth token on TravisCI — Cees-Jan Kiewiet's blog - Environment Variables - Travis CI
Jenkins學(xué)習(xí)資料 Jenkins Overview