全自動化的 Android 編譯管線

【編者按】Nicolas Frankel 是 hybris 的高級顧問, 在Java / J2EE 領域擁有超過10年的管理經驗,本文闡述了他在使用自動化工序去構建 Android 應用程序遇到的一些難題,你們不妨讀讀,但願能有所收穫。html

如下系譯文:android

在我目前的工做中,我必須使用一些自動化工序去構建 Android 應用程序。這篇文章的目的就是描述我所遇到的難題,避免讀者在這個過程浪費更多時間。目的就是分享我在這一過程當中所遇到的困難,爲讀者提供前車可鑑,從而節省寶貴的時間。正則表達式

環境搭建以下:

  • 使用 Puppet 搭建基礎設施
  • 使用 Jenkins 搭建 CI 服務器
  • 工程文件
  • 來構建主體
  • 做爲主要測試工具

Puppet and Jenkins

全自動化的 Android 編譯管線

事實上,個人準備工做已經至關完備。同事們已經使 Jenkins 服務器能夠自動安裝,以及準備好了所需的軟件包——包括 Java 和已提供的可複用的 Puppet 類。Jenkins 的工做徹底依賴於一個單一 config.xm 文件,即不一樣部分的封裝。每部分都由一個專門的模板處理。所以,在我看來,建立一個簡單的 Gradle 任務就如同在公園裏散步通常輕鬆,最多幾天時間即可以完成。shell

第一步很是容易:只需一個最新版 Puppet 清單,能幫助你添加 Gradle 插件到 Jenkins 服務器。後端

The Gradle wrapper

若是你是我博客的忠實讀者,那你大概知道我對 Gradle 的見解。不過,我必須得認可,Maven 的確缺少這種兼容性,即不論安裝哪一個版本的工具都確保編譯成功——雖然它應該具有該功能。爲了實現這一目標,Gradle 經過提供一個 JAR、一個 shell 腳本和一個屬性文件,屬性文件還包含了從 URL 到 Gradle ZIP 的分發,組裝成所謂的包裝機制。這三個需求都被存儲在 SCM 中。安全

然而這正是麻煩的開始。在一個企業環境中進行下載,意味着要經過和驗證代理。最簡單的選擇莫過於在工做配置下設置好一切,包括代理憑證。然而,從安全的角度來看,這樣的作法並不理想,由於任何人訪問 Jenkins 接口或文件系統,都可以讀取這些憑據。顯然,咱們須要一個更好的方式。服務器

用戶已經擁有了配置代理完備的 Nexus 庫。上傳所需的 Gradle 分佈,並更新指向它的 gradle.properties,簡直易如反掌。併發

The Android SDK

全自動化的 Android 編譯管線
Android SDK 只是一個 ZIP 文件。我用一樣的方法:先下載文件而後將其上傳到 Nexus。這一步以後,一個 Puppet 腳本會負責下載、提取,併爲它設置正確的權限。app

然而,事情並無想象的那麼簡單。Android 開發者都知道,Android SDK 須要手動操做:開發者必須手動檢查所需平臺和工具,並將其下載在本地文件系統。這看上去很簡單不是嗎,但若是轉爲自動操做則會讓不少開發者頭疼,儘管有一個命令行至關於能夠經過 SDK「帶有 --no-ui 參數」來安裝/更新包。若是你想了解更多,請點擊這裏工具

谷歌工程師未能提供的兩個重要參數:

  • Proxy credentials – login/password
  • Accepting license agreements

爲了解決這一問題,網上有不少蹩腳的方案,最誘人的應該要數配置文件了,但我卻發現它們沒多大用。然而,經過 expect 命令的使用,我反而發現了一種創造性的解決辦法。Expect 是一個漂亮的命令,用來讀取標準輸出,並用標準輸入進行相應的填寫。值得一提的是,它居然還能夠接受正則表達式。因此,在請求代理登陸時,你鍵入登陸名、填寫密碼,當它要求許可證接受時,你鍵入「贊成」就能輕鬆搞定。雖然我反覆屢次試驗,歷經不少錯誤,才達到預期結果。但這個方法很是簡單、直接。

我最初的設計是,使全部可能用到的裝有 Puppet 的 Android 包,成爲服務器配置的一部分。在標準化操做中「如文件建立或系統包安裝」,Puppet 能夠肯定這項配置是否必要。例如:若是某文件已經存在,那就沒有必要再重複建立了。在最後的 Log 中,Puppet 會報告它執行的每個操做。起初,我試圖經過在配置過程當中,人爲地告訴 Puppet 哪一個包是已配置的,由於 Android SDK 爲每一個包都建立一個文件夾。但要命的是,Puppet 只接受單一文件夾來驗證。對於某些包來講,並無任何版本信息「例如 Google 遊戲服務」。

所以,一個同事提出將 Puppet 配置的更新,移動到每一個任務的預先步驟中。這樣能修復非冪等問題,同時,還能在每一個任務中更新所需配置。

Robolectric

全自動化的 Android 編譯管線
說到這裏,我本覺得一切都搞定了。但很是不幸,並非這麼回事,就由於這個庫—— Robolectric。

此前,我對 Robolectric 沒什麼瞭解,只知道這是一個測試庫,可以在 Android 上運行測試,而無需任何物理設備的鏈接。在 Jenkins 上試圖編譯時,我偶然發現了一個「有意思」的問題:儘管 Roboletric 提供了一個具備完整依賴性的 POM, 但 MavenDependencyResolver 類硬編碼庫應該從哪裏下載?

惟一的解決辦法是經過擴展上面的類來實現。我用的就是上面提到的企業 Nexus 庫。

上傳併發布任務

爲了實現前面的任務,我只需添加一個自定義 Gradle 任務,從 settings.xml 獲得 Nexus 設置「由 Puppet 調配」。基於此,我成功地上傳了任務。最後,對於每一個任務執行的型號,我添加到所上傳的工件集的輸出文件中。所以,無論編譯文件是哪一種型號配置,下面的命令都將只上傳 XXX 和 YYY:

./gradlew assembleXXX assembleYYY upload

上面的任務都搞定了,那發佈豈不是更簡單:惟一須要的就是設置 Gradle 插件,它添加了一個發佈任務,相似於 Maven 的 deploy。

結束語

做爲後端開發人員,我已經習慣於持續集成設置,毫無疑問,我能夠在幾天內搞定 Android CI 的進程。對於 Android 系統在 CI 上的欠缺,我以爲難以想象。每一步都苦不堪言,糟糕的記錄「若是有的話」和解決方案彷佛更像黑客般具備破壞性。若是你想沿着這條路走下去。吶,別說我沒告訴你……Good Luck!

原文連接: Fully Automated Android Build

本文系 OneAPM 工程師編譯整理。
想閱讀更多技術文章,請訪問 OneAPM 官方博客

相關文章
相關標籤/搜索