1. 程式人生 > >如何簡單快速搭建 Android 大倉

如何簡單快速搭建 Android 大倉

書接上文,上回提到 B 站Android團隊為了解決元件化後協作上的問題,已經採用了大倉(monorepo)的方案來組織程式碼。

國內實踐大倉的團隊少之又少,更別提 Android 的大倉了,幾乎沒有來自其它團隊的可借鑑經驗。在這條路上,我們可以算作先行者。本文粗陋,文中所列思路不可能適用所有團隊,僅給同樣想實踐Android 大倉的人些許啟發。

一個標準的 Gradle 專案

首先回顧一下 Android 專案的組織方式。自從13年開始官方逐漸遷移到 Android Studio 做為 IDE 後,Android 專案的開發和編譯就綁在 Gradle 上了。

一個標準的 Gradle 專案結構如下所示:

MyApp/
├── build.gradle 
├── settings.gradle 
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar  
│       └── gradle-wrapper.properties  
├── gradlew  
├── gradle.properties 
└── app
     ├── build.gradle
     └── src
          └── main
              ├── java
              ├── res
              └── AndroidManifest.xml

通常,會有多個Gradle Module存在:

MyApp/
├── build.gradle 
├── settings.gradle 
├── app
│     ├── build.gradle
│     └── src
├── lib1
│     ├── build.gradle
│     └── src
└── lib2
      ├── build.gradle
      └── src

其中 settings.gradle 會註冊所有的 Module

include ':app', ':lib1', ':lib2'

多倉庫

隨業務的擴張,Module 數量會越來越多。遵循多數人實踐過的元件化的思路,按業務分倉庫存放便理所當然:

android group/
  ├── MyApp/ 
  │     ├── build.gradle
  │     └── settings.gradle
  ├── app1/
  │     ├── build.gradle
  │     └── settings.gradle
  ├── app2/
  │     ├── build.gradle
  │     └── settings.gradle
  └── libs/
        ├── build.gradle
        └── settings.gradle

每個倉庫都是一個標準 Gradle 專案,通過 publishing 外掛將module 都上傳 aar(或者jar)到 maven私服(如nexus)上,再在 MyApp/build.gradle 中以 maven 元件的形式依賴它們,最終打包成apk:

repositories {
    maven {
        name = "myRepo"
        url = "http://myrepo.example.com/android"
    }
}
dependencies {
    implementation 'com.example.android:app-a:1.0.0'
    implementation 'com.example.android:app-b:1.0.0'
    implementation 'com.example.android:lib-a:1.1.0'
}

[圖片上傳失敗...(image-7a44b2-1546505515555)]

此時的程式碼組織方式便是上文中所述的多倉庫形態(可能許多團隊正處於當前階段)。

多倉到大倉

那麼,如何既能快速搭建出適用於 Android 的大倉,又能不影響當前的團隊協作流程,還要儘量避免遷移帶來的開發效率降低?

經過一段時間的深入研究 Gradle API,終於找到一個簡單快速的可行方案——composite builds

上面說過,其實每個倉庫都是按業務分離的標準的 Gradle 專案,那麼就可以通過Gradle 官方提供的一個直接引入其它專案的API——includeBuild——快速將所有倉庫組織起來。

在 MyApp/settings.gradle 中直接引入其它 Gradle 專案:

includeBuild '../app1'
includeBuild '../app2'
includeBuild '../libs'

另外比較令人驚喜的是,如Gradle 官方所說,includeBuild會自動替換依賴com.example.android:app-a為有對應宣告的module,如 project(:app1:app-a)。這樣仍然可以用原有的依賴寫法,什麼都不用改,基本沒有遷移工作量。

具體示例可以見官方示例專案:https://github.com/gradle/gradle/tree/master/subprojects/docs/src/samples/compositeBuilds/hierarchical-multirepo

而且,使用 includeBuild 能保留當前的開發流程不變,每個模組仍釋出到 maven 上,不破壞既有協作流程。各個業務的開發,通過Android Studio 開啟自己專案的目錄即可,可以說幾乎沒有開發效率的影響。

解決了各個專案合併問題,另外一個就是要保證大倉的可維護性。

上文講過,依然沿用之前分層的方式,按約定的資料夾組織:

<root dir>
    ├── build.gradle
    ├── settings.gradle 
    ├── app/
    │    ├── app-a
    │    │    ├── src 
    │    │    └── build.gradle
    │    ├── app-b
    │    │    ├── src
    │    │    └── build.gradle   
    │    ├── build.gradle
    │    └── settings.gradle
    │
    ├── common/
    │    ├── common-a
    │    │    ├── src
    │    │    └── build.gradle
    │    ├── build.gradle
    │    └── settings.gradle
    │
    ├── framework/
    │    ├── lib-a
    │    │    ├── src
    │    │    └── build.gradle
    │    ├── build.gradle
    │    └── settings.gradle
    │
    └── MyApp
         ├── src
         └── build.gradle

各個業務方的程式碼只需要按層級對號入座即可。

對號入座的方式有很多種,最簡單的便是直接拷貝專案到對應目錄,而如果要保留原倉庫的提交記錄,則可以使用 git filter-branch 和 git update-index 等命令(略過不表╮( ̄▽ ̄)╭)。

收斂合併許可權

人總是會犯錯的,為了不讓近百名開發成員在一個倉庫裡打架,我們需要在 gitlab 許可權分配的基礎上,通過API實現自動化的方式來合併程式碼。

每個資料夾(或者模組)可以新增一個配置檔案,如OWNERS,業務團隊自己分配 owner和reviewer。

<root dir>
    ├── app
    │    ├── OWNERS
    │    └── app-a
    │          └── OWNERS
    ├── common
    │    ├── OWNERS
    │    └── common-a
    │          └── OWNERS
    ├── framework
    │    ├── OWNERS
    │    └── lib-a
    │          └── OWNERS
    └── MyApp
         └── OWNERS

通過gitlab webhook及note api來實現一個自動化工具:

當開發人員提交一個新的 Merge Reqeust 時,工具找到有變更資料夾的對應 owner 及 reviewer,提醒他來review 和操作合併;當他在MR中提交merge指令時,由自動化工具執行合併操作。

綜述

  1. 通過 Gradle 的includeBuild將所有分開的倉庫合併到一起,並按一定的目錄層級組織各個子專案。
  2. 通過 gitlab 的 api 實現一個自動化工具來合併程式碼。

通過上述兩個步驟,便打造了一個大倉雛形。然而這只是大倉的第一步,未來還有很多工作呢…

關於大倉,本文只簡單描述了一下方案大致思路,行文粗糙,希望對想實踐大倉的你有所幫助,如有疑問歡迎評論留言。

歡迎加入Android進階交流群;701740775。進群可免費領取一份最新技術大綱和Android進階資料。請備註csdn