阿里正在使用一種更靈活的軟件集成發佈模式

當今典型的軟件集成發佈模式是,通過類似GitHub的Pull Request或GitLab的MergeRequest的方式管理特性分支(Feature Branch):在通過代碼評審等方法確認一條特性分支上的改動沒問題後,將其合入集成用的分支。隨後,代碼改動進入在集成分支上運行的持續交付流水線,直到發佈上線。

在阿里巴巴內部,儘管這種工作方式也得到了研發協同工具平臺(Aone)的支持,但廣大研發同學選擇的主流工作方式卻不是它,而是用一種被稱之爲變更(全稱變更請求,英文Change Request)的對象來管理特性分支,直到發佈。

初看起來,變更與Pull/MergeRequest有不少相同點,但實際它們在理念上的差別很大。

本文詳細介紹它們的相同點和不同點,並探討用戶喜歡變更這種方式的原因,當然也會介紹相應的風險和弱點。或許閱讀本文,能給你帶來一些思考。

相同點

變更與Pull/MergeRequest的相同點主要在於對特性分支本身的質量和流程的控制:

  • 一個變更,就像一個Pull/MergeRequest一樣,大體上對應一條特性分支。

  • 在Pull/Merge Request中,可以看到這條特性分支上代碼改動內容,進而進行代碼評審(Code Review)。類似的,也可以以變更爲粒度進行代碼評審。

  • 在特性分支上的代碼提交,可以自動觸發持續集成工具做構建以及各種自動檢測,其結果可以在Pull/Merge Request中展現。類似的,在變更中也可以展現。

  • 可以把Pull/MergeRequest上的最新代碼構建部署到它專屬的測試環境並運行,以進行測試和調試。在變更中也可以這樣做。

  • 在Pull/Merge Request中可以設定通過的條件,比如至少兩名評審者同意,且所有的代碼評審中發現的問題都已修復或澄清,且特性分支上的持續集成流水線運行成功。在變更中也支持類似設置。

不同點及其主要價值

變更與Pull/MergeRequest的不同之處關鍵在於,這個特性分支與其他特性分支一起集成和交付的方式。

對於Pull/MergeRequest,隨後把特性分支合併到集成用的分支,然後就沒有然後了。哦不,是然後就不再以特性分支爲粒度去管理了。這條特性分支已經合入集成用的分支,其上的代碼改動已經融入集成發佈的洪流之中,被裹挾着和其他特性分支上的代碼改動一起前進,去闖關通過集成-發佈的各個階段(Stage)。

而變更不同。即便是已與其他變更集成,它仍然具有一定的獨立性和靈活性,在確有必要時,可針對單獨變更進行操作。下面我們通過兩個例子來詳細介紹。

第一個例子

簡化起見,假定集成交付過程有三個階段:日常集成測試、在預發佈環境測試、正式發佈。

某應用的變更A到變更E共五個變更,在通過了日常集成測試這個階段後,進入了在預發佈環境測試這個階段。測試時,發現變更C有一個缺陷。這個缺陷因爲受日常測試環境所限,在日常集成測試階段沒有暴露出來。經分析,變更C與其他四個變更間沒有依賴關係,不會互相影響。因此,爲了讓其他四個變更的發佈儘量少受影響,決定把變更C從在預發佈環境測試這一階段中摘除出來。其他四個變更在一起再次測試驗證,此時該缺陷不再出現,這四個變更在一起通過了在預發佈環境測試階段,進而進入正式發佈階段,發佈上線。

在這個例子中,在摘除了變更C後,沒有將其他四個變更在一起再次經過日常集成測試階段,是出於兩方面考慮:

一是,此時的日常集成測試環境,已經被若干新添的變更所佔用。它們的測試需要時間,而且可能也會反覆調整。把新添的變更趕出去,或者把這四個變更和新添的變更混在一起,或者讓着四個變更等着,都分別有明顯的不利之處。

另一方面,A、B、D、E四個變更,它們與變更C在一起,已經通過了日常集成測試。而變更C又與它們無關,因此對它們再次進行日常集成測試,發現問題的可能性很低。測試是要講究性價比的,而不是一味追求保證產品零缺陷。

出於以上原因,在具體實戰中,開發團隊就有可能根據當時實際情況,在評估後決定,在摘除了變更C後,不再將其他四個變更在一起送回日常集成環境,而是直接在預發佈環境再次測試。

第二個例子

仍假定集成交付過程有日常集成測試、在預發佈環境測試、正式發佈三個階段。某應用的變更A到變更E共五個變更,在通過了日常集成測試這個階段後,進入了在預發佈環境測試這個階段。此時,根據市場情況變化,需要對變更C所承載的新功能做出少量調整,比如頁面說明文案上改幾個字。考慮到新的修改與變更C原有內容要麼都發布,要麼都不發佈,所以爲便於管理,新的修改就在變更C所在的特性分支上完成。這樣形成的變更C的最新內容,與其他四個變更在一起,在預發佈環境進行測試,通過後正式發佈。

以上兩個例子,是在傳統的集成-發佈方式基礎上,加入了一些靈活性:集成-發佈過程中,必要時可以中途撤下變更,可以中途修改完善變更。而有些團隊在使用變更時,採用了更進一步的方式:不再設集成工程師之類的角色,不再規劃統一的集成、發佈的計劃和時間點。而是每個開發同學負責自己的變更,不僅跟蹤它直到把變更的質量提升到可集成的程度,而且由開發同學自己把他負責的變更依次適時推入(也可能是自動進入)集成-發佈的各個階段,跟蹤它直到發佈上線。

也就是說,儘管進入了集成-發佈階段,各個變更仍是被各自的開發者分別跟蹤和推進的:它們可能有各自的推進速率和節奏,而不會相互拖累。彼此無關的變更,只是碰巧一同使用某個測試環境,一同批量測試以提高測試效率、一同上線以避免排隊而已。

據此,儘可能縮短了一個需求從開發到發佈上線的時間,並表現爲相當頻繁的發佈上線。同時也契合了DevOps的理念:“誰開發誰運行”(You build it, you run it)。

這一變化趨勢其實和軟件研發的管理實踐中發生的事情類似:瀑布模型時代就不提了。隨後迭代方法取代了瀑布模型。典型的,Scrum方法中的Sprint。而更進一步,在精益方法的看板牆上,迭代被弱化,關注的焦點從每個迭代做什麼,每個迭代進入到什麼階段,演化爲關注每個在製品流動到了哪個階段,以及每個階段包含的在製品總量。

類似的,在上述變更管理方法中,從關注某個集成版本進入到集成-發佈的哪個階段,演化爲關注每個變更進入到集成-發佈的哪個階段,以及每個階段包含了哪些變更。

另一方面的價值

上面介紹的是使用變更管理方式帶來的靈活性,以及因爲靈活務實而帶來的效率提升。變更管理方式,在信息記錄和跟蹤方面還有一些的好處:

  1. 要想方便地知道,本次測試、本次發佈,到底包含了哪些特性,只要看看包含了哪些變更就好了。變更本身有說明文字,變更還可以關聯需求、任務、缺陷等工作項,更詳細地說明變更的目的。而在變更之外,也沒有別的代碼修改可以通過直接提交到集成分支等途徑溜進來。

  2. 從變更的視角,這個變更相關的所有改動,都在該特性分支上,而不會因爲多次反饋修改而散亂到各處。因此這些修改總是可以方便地一同查看,一同操作。同時,總是能夠清晰地知道這個變更的狀態,它到了哪個階段:開發完畢了嗎?進入日常集成測試階段了嗎?已經正式發佈了嗎?等等。

  3. 變更可以關聯需求、任務、缺陷等工作項,同時變更的狀態是可以自動獲取的。因此,看板牆上跟蹤的工作項,從原理上就可能被自動移動,以反映其實際狀態。協作和進展,在看板牆上一覽無餘。

弱點和風險

以上談的都是這樣的變更管理方式能帶來的好處。那麼,它有沒有弱點和風險呢?

是的,它有。從大爆炸式集成到持續部署流水線,業界幾十年來幾乎一直在採用一個基本模式:總是一個集成版本,去順序經歷集成-發佈的各個階段。這樣可以保證,下一階段收到的內容,總是精確的經過了上一個階段的檢驗。

而本文介紹的變更管理方式所引入的靈活性,意味着顛覆了這一基本模式。靈活性從來都是雙刃劍。靈活性意味着風險增加,意味着可能被濫用。

敏捷宣言認爲“個體和互動高於流程和工具”,上述變更管理方式暗合了這樣的思想。但在實際使用該方式時,需要注意到它對團隊成員提出了更高的要求:要求他們在具體場景具體案例中,能夠對變更間的相關性及相應風險做出評估,並瞭解不同選擇對效率的影響,最終綜合做出特定場景特定案例中的決策。具體來說:

  • 變更對應的代碼改動越少,中途撤下變更帶來的風險越小。

  • 中途修改完善變更所對應的代碼改動越少,帶來的風險越小。

  • 軟件架構越好,變更中途撤下或修改完善帶來的風險越小。

  • 本次變更與其他變更的相關性越小,中途撤下或修改完善帶來的風險越小。

  • 越緊急,越考慮靈活處理。

  • 業務角度,對軟件質量的要求越高,就越不要考慮靈活處理。

延伸一下,事實上,在微服務甚至函數服務時代,即便不使用上述變更管理方式,也有類似上文的風險,也相應需要團隊成員具備類似上文的自主判斷能力。爲什麼這麼說呢?

之所以把單體應用拆分爲微服務甚至函數服務,一個重要原因就是爲了每個服務能單獨測試和發佈上線。

然而,在使用微服務甚至函數服務方式時,被測對象嚴格地講並不是一個服務,而是該服務以及測試環境中與其直接或間接打交道的所有其他服務。而當把每個服務單獨測試和發佈時,就經常會導致本階段測試時某個其他服務的版本,與下個階段測試時的版本不同,或者與將來正式發佈運行時的版本不同。於是就意味着類似上述變更管理方式中的風險。

相應的,這裏面就需要人來判斷(當然可以有智能算法的輔助),本次哪些服務上的改動務必要一起測試和上線,而另外幾個服務上的改動可以單獨運作。而下次可能又是不同情況,要根據下次的具體情況判斷。

由此看來,“總是由一個集成版本,去順序經歷集成-發佈的各個階段”這個基本模式,其實已經被悄然突破了。上述變更管理方式,只是使這個突破更加明顯了而已。

落地及工具支持

以上是介紹了一種獨特的變更管理方式,介紹了優點,也介紹了相應的風險。下面我們來看看它在阿里是如何落地的。

首先需要一套分支方案來支持它。大體上是這樣:

  1. master分支總是代表最新已發佈版本。

  2. 代碼改動總是在特性分支上完成。特性分支總是從master分支上拉出的,並在必要時從master再次同步。

  3. 沒有一條長期存在的集成發佈用的分支。而是集成發佈過程的各個階段,各對應一條短期的,被自動管理的集成發佈分支。從master分支自動拉出該分支,再把各特性分支自動合併到該分支(出現衝突時人工介入),於是它上面就有了用戶想要的各特性。

  4. 如果發現某個特性需要進一步修改完善,在特性分支上完成,並再次合併到相應的集成發佈分支。

在阿里,我們如何管理代碼分支?這篇文章對上述分支方案有更多介紹。

可以看出,這套方案,對工具平臺的要求是比較高的:從界面角度,用戶只需要管理各個集成發佈階段分別要有哪些變更。而工具平臺要將它映射爲對集成發佈分支的管理,包括創建新分支或複用已有分支、從各特性分支到集成發佈分支的合併等等。這裏面也包括了不少算法,以儘可能減少相同的合併衝突重複出現。

對工具平臺的高要求,或許是這套方法多年來一直只是在阿里巴巴內部被廣爲使用的原因,但是現在阿里巴巴也基於內部研發協同工具平臺Aone對外提供了雲效。

本文首發於公衆號“雲效”:https://mp.weixin.qq.com/s/O-9msZQW0P6lS_1u8f6L9g


作者簡介

董越(花名荷鋤),阿里巴巴研發效能部高級產品專家,江湖上的名號是流水先生。他在軟件配置管理、集成與交付管理領域工作十餘載,曾就職於西門子、摩托羅拉、雅虎、索尼愛立信、去哪兒等公司。同時在業餘時間著書立說講演,是《未雨綢繆——理解軟件配置管理》等書的作者或譯者。他目前在阿里巴巴從事阿里研發協同平臺Aone(對外產品叫雲效)的產品設計工作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章