基於Travis CI搭建Android自動打包釋出工作流
最近付費購買了Travis CI,Travis CI的收費模式很有意思,不是按專案或者使用者,而是按工作程式收費,比如初級版本是$129/月,總共提供2個工作程式。在專案不多的情況下,除了用於跑單元測試外,不免想利用的更充分一些,因此抽空搭建了一套基於Travis CI的Android自動釋出工作流。
未自動化前安卓開發總是避免不了這樣的工作流程:
實現了這套自動化釋出後,工作流程被簡化成:
- 開發新功能,提交程式碼
- 通過
git tag
對程式碼打一個內測版的tag,在tag的描述中對寫當前完成的功能
Tag提交後Travis CI會自動編譯程式碼,生成APK檔案並分發到Github和fir.im,Github和fir.im中會保持Tag的描述資訊,分發完成後會有郵件通知所有參與測試的人員。而作為開發人員,只需要專注於對程式碼打好一個Tag就可以了。
整個流程看似做了不少工作,其實體現在Travis CI只有數行指令而已,以下逐一講解:
對安卓專案啟用Travis CI
Travis CI應該可以算是目前最好用的持續整合服務之一了,如果程式碼庫是基於Github的話,可以很簡單的開啟。由於本文涉及到了很多Travis CI的基礎概念,建議首先對Travis CI的自定義構建一節有所瞭解。
很早前在介紹PHP專案的持續整合時也寫過如何在PHP專案中使用Travis CI。 對於安卓專案來說步驟幾乎一致:
首先準備一個.travis.yml
檔案放在安卓專案根目錄下,.travis.yml
中記錄了Travis CI所需的基礎資訊:
language: android
sudo: false
android:
components:
- build-tools-23.0.1
- android-23
- extra-android-m2repository
- extra-android-support
script:
- "./gradlew assembleRelease"
無需讀文件就可以通過上面的配置大概知道,我們要執行的是一個安卓專案,安卓SDK版本為23,專案所用的BuildTools版本為23.0.1,為編譯這個專案我們還引入了一些必須的元件,如Support Library(extra-android-support)、Android Support Repository(extra-android-m2repository)等。
當Travis CI準備好我們所需要的環境後,將自動執行yml檔案script
部分所設定的指令,上例中執行的是./gradlew assembleRelease
,執行成功的話會在專案的主模組下生成build/outputs/apk/app-release.apk
。
最後進入Travis CI主頁,使用有專案Admin許可權的Github帳號直接登入。選擇要開啟Travis CI的專案,將右邊的開關設為On即可。
Travis CI目前有2個網站:如果是開源專案,直接進入travis-ci.org即可,如果是私有付費專案,則需要進入travis-ci.com,2個網站除了域名外所有的介面及操作幾乎一模一樣。
配置中還有一行sudo: false
,是為了開啟基於容器的Travis CI任務,讓編譯效率更高。
安卓自動化構建的密碼和證照安全
安卓專案釋出需要證照檔案和若干密碼,但無論是開源專案還是私有專案,任何時候都不應該將原始證照或密碼放入程式碼庫(原則上來講證照和密碼也不應該交於開發人員,而應該只能通過釋出伺服器進行編譯)。Travis CI為此提供了2種解決方案,一種是對敏感資訊、密碼、證照等進行對稱加密,在CI構建環境時解密,另一種是將密碼等通過Travis CI的控制檯(即網站)設定為構建時的環境變數。
由於前者會在Travis控制檯生成一對環境變數,所以我的做法是儘量選擇後者,但由於Travis控制檯無法上傳檔案,因此涉及到檔案加密的部分,則只能選擇前者。
說了這麼多,首先還是需要先對編譯指令碼進行改造,如果不考慮安全問題,專案的build.gradle
檔案可能會是這樣:
android {
signingConfigs {
releaseConfig {
storeFile file("../keys/evandroid.jks")
storePassword "123456"
keyAlias "evandroid_alias"
keyPassword "654321"
}
}
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
三個環境變數,在Travis CI環境下可以通過System.getenv()
獲得這些環境變數。
本地開發環境中,我的做法是將這幾個變數加到gradle.properties
檔案中,這樣就可以在build.gradle
內直接使用了。下面是開發環境的gradle.properties
KEYSTORE_PASS=123456
ALIAS_NAME=evandroid_alias
ALIAS_PASS=654321
這樣一來build.gradle
就變成了
releaseConfig {
storeFile file("../keys/evandroid.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")
}
接下來處理證照檔案,為了方便檔案加密等功能,Travis CI提供了一個基於ruby的CLI命令列工具,可以直接使用gem安裝
gem install travis
安裝後進入安卓專案根目錄,嘗試對證照檔案加密:
travis encrypt-file keys/evandroid.jks --add
如果首次執行,travis會提示需要登入,執行travis login --org
並輸入Github使用者名稱密碼即可。(付費版則為travis login --pro
)
travis encrypt-file
指令會做幾件事情:
- 在Travis CI控制檯自動生成一對金鑰,形如:
encrypted_e41864bb9dab_key
,encrypted_e41864bb9dab_iv
- 基於金鑰通過
openssl
對檔案進行加密,上例中會專案根目錄生成evandroid.jks.enc
檔案 在
.travis.yml
中自動生成Travis CI環境下解密檔案的配置,上例執行後可以看到.travis.yml
中多了幾行:before_install:
- openssl aes-256-cbc -K $encrypted_e41864bb9dab_key -iv $encrypted_e41864bb9dab_i -in keys/evandroid.jks.enc -out keys/evandroid.jks -d
Travis CI預設在專案根目錄下執行,因此注意根據實際需求調整enc檔案的路徑。
最後別忘了在.gitignore
中忽略keys/evandroid.jks
以及gradle.properties
並在程式碼庫中將其刪除。
Travis CI自動釋出安卓apk檔案到Github Release
Travis CI的script
部分執行成功後,可以通過配置檔案進入到釋出階段。下面是一個Travis CI釋出的示例:
deploy:
provider: releases
user: "GITHUB USERNAME"
password: "GITHUB PASSWORD"
file: app/build/outputs/apk/app-release.apk
skip_cleanup: true
on:
tags: true
這個例子中配置了這樣一些內容:
provider
:釋出目標為Github Release,除了Github外,Travis CI還支援釋出到AWS、Google App Engine等數十種provider- Github使用者名稱和密碼,因為Travis CI要上傳APK檔案,因此需要有Github專案的寫入許可權
file
: 釋出檔案,輸入檔案路徑即可skip_cleanup
: 預設情況下Travis CI在完成編譯後會清除所有生成的檔案,因此需要將skip_cleanup
設定為true來忽略此操作。on
: 釋出的時機,這裡配置為tags: true
,即只在有tag
的情況下才釋出。
雖然這樣就能完成自動釋出,但是直接暴露了Github密碼是我們更加不能接受的。更好的做法是在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: XXX
file: app/build/outputs/apk/app-release.apk
skip_cleanup: true
on:
tags: true
all_branches: true
其中api_key
下的secure
就是加密後的Access Token。
在執行travis setup release
時有可能遇到
Invalid scheme format: git@github.com for a full error report, run travis report
這樣的報錯,看起來是Travis CLI還不支援通過金鑰訪問Github,因此可以將專案的源臨時切換為http形式,執行成功後再切換回來:
git remote set-url origin https://github.com/AlloVince/evandroid.git
git remote set-url origin git@github.com:AlloVince/evandroid.git
在實際部署過程中,發現釋出到Github Release比較坑的點是
git push
git push --tags
往往會同時生成2個Travis CI任務,但是在Travis網頁中預設介面只能看到最後跑的一個任務,而未打Tag的任務又會報
Skipping a deployment with the releases provider because this is not a tagged commit
這曾讓我一度以為自己的指令碼哪裡寫錯了,但是又找不到錯誤原因……
自動釋出APK到fir.im
自動釋出到Github對於開發人員已經足夠,但是考慮到專案實際需要以及國情,還是有必要選擇一個國內的App分發服務,fir.im、蒲公英都是不錯的選擇,不但允許遊客下載,還提供了二維碼等更適合對接手機的功能,國內下載速度也很快。由於fir.im提供了比較方便的CLI工具,因此本文以fir.im為例,在.travis.yml
中新增以下幾行:
before_install:
- gem install fir-cli
after_deploy:
- fir p app/build/outputs/apk/app-release.apk -T $FIR_TOKEN -c "`git cat-file tag $TRAVIS_TAG`"
即在環境構建階段安裝fir-cli,在釋出成功後通過fir命令列工具將apk上傳到fir。
其中$FIR_TOKEN
可以在fir.im的使用者->API Token中找到,然後在Travis CI控制檯中建立環境變數FIR_TOKEN
並貼上即可。
這裡有個小技巧,如果我們僅僅上傳APK檔案到fir.im,看到連結的測試人員其實並不知道這次釋出所包含的變動,因此通過git cat-file tag $TRAVIS_TAG
將當前釋出tag所包含的附加資訊一同上傳了。其中$TRAVIS_TAG
變數是Travis CI每次執行自動附帶的環境變數,還有很多其他的Travis環境變數供我們玩出更多花樣。
釋出完畢後自動發郵件通知
雖然Travis CI也有通知功能,但不能定製模板,通知內容也僅僅為提示CI執行的結果,顯然更適合開發人員。我們還是希望最終能以更友好的方式通知團隊成員,同時考慮到郵件送達率,可以優先選擇如Submail、SendCloud等國內郵件傳送服務。
這裡以Submail為例,首先需要在Submail內建立郵件模板,比如我們可以建立這樣一封觸發式郵件模板:
Hi 親
@var(TRAVIS_REPO_SLUG)新版本@var(TRAVIS_TAG)已經發布了,功能更新:
@var(TAG_DESCRIPTION)
去下載:
http://fir.im/w13s
建立後可以得到郵件模板id,根據Submail手冊,將模板中所需要的變數置入,最終可以使用一行Curl指令傳送一封郵件:
after_deploy:- curl -d "appid=10948&to=allo.vince@gmail.com&subject=[自動通知] 安卓新版本$TRAVIS_TAG釋出&project=u2c0r2&signature=$SUBMAIL_SIGN&vars={\"TRAVIS_REPO_SLUG\":\"$TRAVIS_REPO_SLUG\",\"TRAVIS_TAG\":\"$TRAVIS_TAG\",\"TAG_DESCRIPTION\":\"$(git cat-file tag $TRAVIS_TAG | awk 1 ORS='<br>')\"}" https://api.submail.cn/mail/xsend.json
其中Submail用到的認證憑據signature同樣是通過Travis CI控制檯配置的。
總結
最終完成的示例專案在此。其實所有的yml檔案配置不到30行,就能省去繁瑣的日常工作,何樂而不為呢。最後回顧一下自動化後的日常工作:
提交程式碼:
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
大部分Tag標籤雖然僅用於內測,但是仍然建議允許版本語義化原則。
References
相關文章
- [譯] 使用 Travis CI 自動釋出 npmNPM
- 基於DotNetty實現自動釋出 - 實現一鍵打包釋出Netty
- 解放雙手,基於github travis-ci docker自動化部署java專案GithubDockerJava
- 基於GitLab CI搭建Golang自動構建環境GitlabGolang
- 基於 GitLab CI 搭建前端自動構建環境Gitlab前端
- iOS自動整合打包釋出iOS
- [小團隊自動化] 基於 Gitea+Drone CI+Vault 打造屬於自己的CI/CD工作流Git
- windows右鍵選單自動打包釋出nuget,沒有CI/CD一樣方便!Windows
- Hexo遇上Travis-CI:可能是最通俗易懂的自動釋出部落格圖文教程Hexo
- 使用travis-ci自動部署Hexo到github和codingHexoGithub
- 用 Travis CI 打造大前端持續整合和自動化部署前端
- iOS自動構建打包釋出指令碼iOS指令碼
- ReactNative專案自動化打包釋出React
- .NET 微服務——CI/CD(2):自動打包映象微服務
- 基於 Gitea+Drone CI+Vault 打造屬於自己的CI/CD工作流Git
- 【Hexo】使用Hexo+github pages+travis ci 實現自動化部署HexoGithub
- 基於Travis CI實現 Gitbook在 Github 和 Coding 的同步部署Github
- React Native專案自動化打包釋出React Native
- HBuilder Android APP打包釋出UIAndroidAPP
- 拯救懶癌文件君 - VuePress + Travis CI + Github Pages 自動線上生成文件VueGithub
- Linux_基於Tomcat自動釋出指令碼LinuxTomcat指令碼
- 用 GitHub Actions 自動打包釋出 Python 專案GithubPython
- [小團隊自動化] (一) Drone CI For Github —— 打造自己的CI/CD工作流Github
- 釋出nuget包的正確姿勢---cicd自動打包釋出nuget包
- 基於DotNetty實現自動釋出 - 自動檢測程式碼變化Netty
- Travis-CI自動化測試並部署至自己的CentOS伺服器CentOS伺服器
- Android程式自動化打包Android
- 安卓自動化打包環境搭建安卓
- jenkins實踐篇(1)——基於分支的自動釋出Jenkins
- Bitbucket Pipes釋出,帶來30+自動化CI/CD管道的方法
- [小團隊自動化] (三) 輕量化自建 Drone CI For Gitea —— 打造自己的CI/CD工作流Git
- objc系列譯文(6.5):為iOS專案搭建Travis CI伺服器OBJiOS伺服器
- 搭建基於C#和 Appium 的 Android自動測試環境C#APPAndroid
- Azure 基礎:用 PowerShell 自動釋出 CloudServicesCloud
- 基於Jenkins實現php專案的自動化測試、自動打包和自動部署JenkinsPHP
- 持續整合服務 Travis CI 教程
- Knativa 基於流量的灰度釋出和自動彈性實踐
- 基於 flow.ci 實現 PHP 專案自動化持續整合PHP