如何高效參與開源項目?
本文重新發(fā)布了如何高效利用有限的時間參與開源社區(qū)的兩篇文章,修復(fù)了大量影響閱讀的措辭。
大部分人參與開源社區(qū)會面臨的一個巨大挑戰(zhàn),那就是缺乏時間。本文試圖提供一種方式,幫助想要參與開源社區(qū)的同學(xué)高效利用有限的時間。
在一個開源社區(qū)里,maintainers 需要關(guān)注的范圍比 contributors 要大得多。本文分別討論這兩類人群適用的參與開源社區(qū)的技巧,以減少過程中的摩擦,提高時間的利用率。
Contributors
Join the community and lurk first
參與開源社區(qū)的第一步就是加入社區(qū)。加入社區(qū)的方式有很多,可以訂閱郵件列表,關(guān)注開發(fā)活動,參與技術(shù)或非技術(shù)討論,等等。很多希望參與開源社區(qū)的人遲遲邁不出第一步就是忽略了自己首先要加入社區(qū),跟社區(qū)建立起聯(lián)系。
一個典型的錯誤做法是完全不顧開源社區(qū)是開發(fā)開源項目的主體,一頭鉆進技術(shù)細節(jié)里,暗搓搓地做一個“大功能”,然后希望社區(qū)盡快合并這個補丁,讓自己得到榮譽。
Linux Foundation 有一篇博文?Participating in Open Source Communities[1]?明確反對了這種做法。
Some organizations make the mistake of developing big chunks of code in house and then dumping them into the open source project, which is almost never seen as a positive way to engage with the community. The reality is that open source projects can be complex, and what seems like an obvious change might have far reaching side effects in other parts of the project. Any significant change is likely to require some community discussion before it moves to implementation to make sure that there are no side effects and that the solution is aligned with the broader goals for the project. While you discuss it with the community, it can help to focus on the problem, rather than a specific solution, before you invest too much time in the creation of a body of code.
一個現(xiàn)實的例子,前幾天有人問我,自己做了一個 Flink StateBackend 的實現(xiàn),提交給社區(qū)是不是就能當(dāng) PMC 了。這個問題屬實把我整不會了。從來沒有在社區(qū)當(dāng)中亮相的人,突然出現(xiàn)并提出自己實現(xiàn)了一個“大功能”,在其他成員眼里跟民科沒什么不同。絕大部分情況下,這種實現(xiàn)跟上游社區(qū)的開發(fā)節(jié)奏是脫節(jié)的,很難合回去。也就是說,閉門造車的形式自我感動地開發(fā)項目,即使花費了時間,大概率還是白忙一場。
剛開始接觸 Flink 社區(qū)的時候,我就按照項目文檔的提示訂閱了 users 和 dev 兩個郵件列表。實話說,最初的三個月,我基本看不懂他們在說什么。當(dāng)時的我盡可能地讀每一封郵件,從郵件里面引用的鏈接一個個點進去了解背景,混沌當(dāng)中建立起對項目的初步印象。直到四個月后第一次提交代碼,這個祛魅的過程才算完成。從此以后,我逐漸能夠輕松地參與到技術(shù)討論,也掌握了 review 的溝通習(xí)慣。
最近,我在跟人介紹 Engula 項目的時候,也是先發(fā)討論區(qū)[2]和聊天室[3]的鏈接。新成員可以閱讀過往的討論,掛在聊天室里,觀察社區(qū)討論問題和推進工作的方式,了解已有的設(shè)計實現(xiàn)和結(jié)論。參與閑聊或者回復(fù)感興趣的話題,找到自己愿意投入的工作。只有這樣,才能進一步深入?yún)⑴c開源社區(qū),而不是接觸了好幾年,卻始終邁不出第一步。
Figure out what you care about
要想利用有限的時間創(chuàng)造更多價值,最好的方法是找到一個感興趣的問題,然后持續(xù)投入進去直到解決。
一個典型的錯誤做法是強迫自己做著不感興趣的工作。這種情況下,由于內(nèi)心是抗拒的,即使投入再多的時間,也幾乎不會有產(chǎn)出。
可能有人會不理解,開源社區(qū)的 contributor 都是自愿參與,如果不想做某個工作,不是不做就可以了嗎。其實不然,社區(qū)成員身處其中很容易感受到無形的社交壓力。
一種情況是不懂得拒絕。知乎上有個問題,如何優(yōu)雅地拒絕開源項目的 PR 邀請[4],講的就是這種情況。我在回答里分享了一個自己拒絕 Flink 社區(qū)成員里的 PR 邀請的案例。另一種情況是錯誤估計難度,即自以為能搞定這個工作,做的過程里發(fā)現(xiàn)不對,又不好意思改口說自己搞不定。應(yīng)對這些情況的方法非常簡單,直截了當(dāng)?shù)卣f明情況即可,解放自己避免浪費時間。
另外一個難題是自己往往對比較有挑戰(zhàn)性的工作感興趣,但是從一個剛接觸項目的 contributor 到能夠完成一個復(fù)雜任務(wù)之間有一道坎。
要跨過這道坎,同樣需要積極采取行動,而不要獨自糾結(jié)。首先可以考慮從簡單的工作入手,比如閱讀項目文檔時發(fā)現(xiàn)的拼寫錯誤。一個簡單的貢獻能帶你走完整個 contribution 流程。一回生二回熟,做其他有挑戰(zhàn)性的工作也就不會在流程上踩坑。其次可以保持和 maintainers 的交流,以了解現(xiàn)有邏輯的設(shè)計背景和演進過程。只有對工作涉及的邏輯有充分的了解,才能寫出高質(zhì)量的代碼。高質(zhì)量的代碼也意味著更少的返工和不必要的爭論,也就避免了時間的浪費。
Build relationships
隨著參與的深入,總有你一個人無法完成的工作。開源協(xié)同的價值就在于跨越所屬組織的邊界合作開發(fā)項目。合作的基礎(chǔ)是成員之間的信任,也就是良好的關(guān)系。
開源社區(qū)是圍繞開源軟件建立起來的。但是并不只有軟件本身帶來技術(shù)價值,人與人的連結(jié)帶來認同感和歸屬感,這些也能滿足社區(qū)成員的需要。此外,相互信任的基礎(chǔ)能很大程度提升價值創(chuàng)造的效率,例如減少浪費在同步和對齊上的時間。因此,建立并保持與其他項目成員的關(guān)系至關(guān)重要。
做到這一點的方式就是充分的溝通。同樣,這需要以開放的心態(tài)對待平時的交流。不要把所有事情都憋在心里。不要糾結(jié)于想清楚所有細節(jié)再開始溝通,其他成員一時間內(nèi)往往沒辦法追上你所想的所有細節(jié)。我的建議是,當(dāng)你有一個初步的想法,也做了力所能及的調(diào)研,就可以整理一下,發(fā)布到社區(qū)當(dāng)中征求意見。
我給 Engula 項目做了一個社區(qū)計劃[5]。老實說,內(nèi)容并不成熟,但是我一個人干想也得不出結(jié)論,所以在經(jīng)過幾輪自我 Review 以后,就先拋出來征求意見。另一個例子是 Engula 的 maintainer @huachaohuang 想為 contributor 提供開發(fā)文檔,于是就發(fā)起了一個關(guān)于 Dev Guide 的討論[6]。正好我對這個話題也早有想法,當(dāng)我看到發(fā)出來的討論以后,發(fā)現(xiàn)他也在關(guān)注這個話題。于是我花了一個小時把自己的想法寫下來,經(jīng)過討論以后提 PR 推進主分支。
溝通協(xié)作的過程里沖突在所難免。我在好幾個項目里都別人討論甚至爭論過很多次技術(shù)問題,給別人的行為提過意見,也夸贊過好的做法。開源社區(qū)解決沖突的方式比較樸素,一般是有話直說,盡量客觀地達成共識,按照流程約定做出決策。不用整那么多彎彎繞浪費時間。
舉一個現(xiàn)實的例子,曾經(jīng)有人跟我抱怨提上去的 PR 被 maintainer 挑戰(zhàn)了,問我應(yīng)該怎么回復(fù)。懷疑 maintainer 是不是有偏見,抱怨很難跟 maintainer 溝通,大量的時間精力浪費在糾結(jié)這些臆想出來的問題,自然是筋疲力竭,感覺在開源社區(qū)里寸步難行。
Talk to your boss, and choose your job
最后,關(guān)注到相當(dāng)一部分 contributors 的公司員工的身份。這顯然會影響到他們參與社區(qū)的動力和能力。
主要的挑戰(zhàn)是,如果工作期間不允許參與開源社區(qū),同時工作本身已經(jīng)消耗了太多的時間精力,那么 contributors 對參與開源社區(qū)也只能是有心無力。這其實是很長一段時間里開源社區(qū)的參與在國內(nèi)發(fā)展緩慢的原因。大量的開發(fā)者都在過度工作,下班只想躺平休息,沒有動力再談什么開源貢獻。
不過,隨著時間的發(fā)展,情況也在發(fā)生著變化。越來越多的公司采用更加靈活合理的工作時間,尤其是以研發(fā)為核心競爭力的公司。如果你所在的公司仍然要求超負荷工作,燃燒生命賺血汗錢,那么是時候找份新工作了。時代已經(jīng)變了,就讓這些公司被無情的淘汰吧。
另一個方向是考慮在工作期間參與開源社區(qū)。如果你確實喜歡某個開源項目,那么最佳策略就是找一份允許你全職投入這個項目的工作。這樣的工作崗位如今并不少見。尤其是隨著企業(yè)級解決方案越來越傾向于采用開源組件,企業(yè)對熟悉開源軟件的人才的需求只會日益增加。如果找不到全職投入開源項目的工作,與之相關(guān)的工作也是備選方案。
不過,即使這份工作允許你全職投入開源項目,也并不意味著你能夠參與開源社區(qū)。特別是當(dāng)你的老板認為參與開源社區(qū)不能為公司創(chuàng)造價值的時候。面對這個問題,首先你可以問問你的老板,說不定他不這么覺得,那就省事兒了。如果你的老板確實難以理解,那你就得像兜售一個技術(shù)方案一樣向他宣傳參與開源社區(qū)的價值了。我在其他的文章里對這一點已經(jīng)有不少討論,你可以看看。
普適的時間管理手段這里就不展開介紹了,各種相關(guān)書籍和 GTD 方法論都很值得一看。
Maintainers
Nominate new maintainers selectively
Maintainers 比起 contributors 需要關(guān)注的更多的事情。隨著開源項目日漸復(fù)雜,開源社區(qū)逐漸成長,單靠一個人的力量很難處理好所有的事務(wù)。這個時候,就需要 maintainer 適時地發(fā)展項目維護的隊伍。
首先需要理清 maintainer 頭銜的定位。實際上,大部分項目的維護是個苦力活,而 maintainers 就是一群承擔(dān)這些工作的社區(qū)成員。Maintainers 可能會擁有合并 PR 的權(quán)限,在社區(qū)治理中能投票做決策,確定項目發(fā)展的方向。但是,這種權(quán)限并非特權(quán)。在一個健康的社區(qū)里,任何社區(qū)成員都可以做技術(shù)討論,也可以就社區(qū)發(fā)展話題提出自己的觀點。對于技術(shù)觀點,客觀上更加合理的方案理應(yīng)被采納。對于社區(qū)發(fā)展話題,maintainers 也一定會考慮建設(shè)性的提議。
可能有不少人把成為 maintainer 當(dāng)成參與開源社區(qū)的目標(biāo),這是很好的。如果你理解了 maintainer 的職責(zé),通過 contribution 積累了足夠的信譽,成為 maintainer 為開源社區(qū)服務(wù),這個頭銜是一個顯式的認可。不過,大可不必過分糾結(jié)于 maintainer 頭銜。這只是對 contribution 認可形式的其中一種,而不是唯一一種。
Maintainers 的職責(zé)并不輕松,所以 Python 社區(qū)和 Apache 軟件基金會下的項目社區(qū)都會有一個詢問 contributor 是否愿意成為 maintainer 的流程。也存在 contributor 拒絕邀請的情況,因為就像前面提到的,健康的開源社區(qū)里,只要提議是合理的,就能憑借其客觀的優(yōu)勢勝出。成為 maintainer 并不意味著在方案選擇上有特權(quán)。
對于 contributor 的感謝,也可以通過宣傳渠道發(fā)布。比起一個模糊的 maintainer 頭銜,作為技術(shù)人員,我會更在意這個人實際在開源社區(qū)里實際完成的事情。
基于上面的認識,我們引出下一個觀點。Maintainers 發(fā)展新成員,必須是有選擇性的。
這種選擇性的主要依據(jù)是維護項目的需要,而不是追求數(shù)量或者過分在意 diversity 等等。這可以類比到開發(fā)軟件的目的是提供技術(shù)價值,而不是代碼行數(shù)或者所采用的編程語言的數(shù)量。
一個典型的錯誤案例是出于自己同時是公司員工的身份,被命令將 maintainers 的人數(shù)發(fā)展到某個數(shù)字。這種指標(biāo)只關(guān)注數(shù)字而不關(guān)注具體的人,而且往往定得脫離實際。公司員工迫于指標(biāo)壓力很容易降低 maintainers 的標(biāo)準(zhǔn),逮到一個算一個的湊人頭,或者為了 diversity 對不同背景的 contributor 采取不同的標(biāo)準(zhǔn)。這樣發(fā)展出來的 maintainers 不僅不能分擔(dān)項目維護的職責(zé),還很有可能因為不勝任而產(chǎn)生新的問題。
另一個典型的錯誤經(jīng)常出現(xiàn)在個人項目上,當(dāng)個人項目發(fā)展壯大,唯一的 maintainer 想要發(fā)展新成員時,很容易陷入到要找一個自己的分身的誤區(qū)。也就是說,新的 maintainer 必須和自己一樣能夠關(guān)注到項目的方方面面。這是不對的。沒有兩個人完全相同。只要一個 contributor 有足夠的信譽,并且能在項目或社區(qū)的維護的某個方面上承擔(dān)職責(zé),他就是一個好的 maintainer 人選。
不過,這里講到的信譽是一個非常主觀的概念,提名 maintainer 的傾向每個項目也各有不同。
?Perl 社區(qū)最初由 Larry Wall 獨裁。近年來,隨著他逐漸淡出核心成員圈子,Perl 社區(qū)的治理實際上已經(jīng)變成由 28 人組成的 core team 負責(zé)。?PostgreSQL 社區(qū)由 7 人組成的 core team 和 28 位 committers 處理所有工作。?ASF 治下的項目有一套比較固定的治理模型[7]。具體到每個項目,例如?Apache Pulsar[8]?和?Apache Flink[9]?會有自己具體的要求和傾向。?Spring Project 社區(qū)的 committers 都是 Pivotal 公司或 VMWare 公司的員工。但是它顯然也是誕生于開源協(xié)同的作品。?Linux Kernel 基本上還是由 Linus 獨裁。同時,海量的驅(qū)動和架構(gòu)支持有各自的 maintainer 進行維護。參考?Linux Kernel Maintainers 頁面[10]。?Netty 社區(qū)沒有明確的規(guī)則。Trustin Lee 發(fā)起項目并獨自維護了三年。隨后,Norman Maurer 和 Scott Mitchell 等少數(shù)幾個人持續(xù)參與,成為 maintainer 并共同維護 Netty 項目至今。
如果讓我對 maintainer 提一個基礎(chǔ)要求,我會希望他在項目或社區(qū)中做出了卓越的貢獻,并且當(dāng)前的 maintainers 團隊樂于和他一起工作。
Structure processes
除了增加項目維護的人員,另一個基本的減少時間浪費的手段就是結(jié)構(gòu)化流程。我們分點介紹其內(nèi)涵。
第一點是直覺大于文檔。對于托管在 GitHub 上的項目來說,help wanted 和 good first issue 標(biāo)簽是一個眾所周知的約定。合理標(biāo)記 issue 能讓 contributor 按照過往的經(jīng)驗快速找到切入點。我在修訂 TiDB 社區(qū)的治理方案[11]的時候,也是以跟 GitHub 開箱即用的功能親和為主要目標(biāo)之一。如果參與一個開源項目有太多新東西要學(xué),那么 maintainers 就有的是要解釋的東西了。大部分人效率最高的路徑是完全憑直覺做事,并取得好的結(jié)果。所以如無必要,請勿設(shè)立復(fù)雜的規(guī)則。
第二點是文檔大于口述。直覺畢竟只能解決部分問題,對于特殊的或者需要強調(diào)的內(nèi)容,明確記錄下來作為文檔絕對是個好主意。
不過文檔首要的還不是記錄流程,而是項目的目標(biāo)或者叫定位。這是每個對項目感興趣的人都會問的問題,高水平的 contributor 尤甚。他們不僅僅是想在開源社區(qū)里做簡單的工作,更想成為一個偉大的或富有價值的項目的締造者。如果你想為你的項目吸引到高水平的開發(fā)者,那么最好是確定一個清晰且令人振奮的目標(biāo),并將它展示在最顯眼的地方。例如,Apache Flink 的定位是數(shù)據(jù)流上的有狀態(tài)計算,其中有狀態(tài)這點是開源世界里開創(chuàng)性的工作。例如,PostgreSQL 的定位是世界最先進的開源關(guān)系型數(shù)據(jù)庫。例如,Elixir 語言的目標(biāo)是構(gòu)建可擴展和可維護的應(yīng)用。
其次是約定俗成的文檔,包括 README 和 CONTRIBUTING 等等。其中一般包含項目的簡介,開始使用的方法,參與貢獻的基本流程,和指向更多文檔的鏈接。大部分 contributor 會嘗試尋找和閱讀這些文檔。如果他們能從其中解決自己的問題,就不需要 maintainer 花時間說明了。至少,在有人提問的時候,直接發(fā)一個文檔的鏈接,也能省不少事兒。
另一個值得強調(diào)的是 Code of Conduct 即行為準(zhǔn)則。提名新的 maintainer 之前最好確保被提名人知悉和理解社區(qū)行為準(zhǔn)則。行為準(zhǔn)則通常是一些涉及平等、尊重和避免冒犯的原則。雖然大多數(shù)開源社區(qū)很少遇到嚴重違反行為準(zhǔn)則的情況,但是 maintainers 應(yīng)該對此保持敏感。這類問題一旦處理不當(dāng),很容易演變成政治斗爭,甚至導(dǎo)致社區(qū)分裂或項目停擺。
最后是設(shè)計文檔。Contributors 要深度參與技術(shù)貢獻需要了解相關(guān)代碼的設(shè)計背景和演進過程,設(shè)計文檔就是最好的參考材料。良好的代碼質(zhì)量有助于避免 contributor 閱讀源碼時受挫,但是項目固有的復(fù)雜度還是需要設(shè)計文檔來輔助解釋。如果代碼質(zhì)量和設(shè)計文檔都缺位,想要深度參與技術(shù)貢獻的 contributor 就不得不指望 maintainer 花費大量的時間解釋和指導(dǎo)了。這點對于 maintainer 自己也是一樣的。當(dāng)你想要做一個新的功能,如果沒有好的技術(shù)文檔,你也得懵圈,也得拉人反復(fù)對齊。
第三點是避免私下討論。有關(guān)項目和社區(qū)的討論,唯一的信源應(yīng)該是一個公開的渠道。例如,ASF 治下的項目要求所有有效的討論都應(yīng)該發(fā)生在郵件列表上。例如,大部分托管在 GitHub 上的項目隱含了討論應(yīng)該發(fā)生在 GitHub 平臺上。社區(qū)成員可能還會通過其他的溝通渠道輔助交流,例如即時通信軟件。但是這些輔助渠道的討論需要被抄送到唯一信源上才實際生效。這樣,contributor 才能在無需了解諸多渠道的前提下有能力獲取所有有價值的信息。
這些公開討論的內(nèi)容以及表現(xiàn)出來的做事方式,就是社區(qū)當(dāng)中的“活文檔”。模仿是人類的天性,如果你希望別人遵循某種做事方式以減少沖突,那么最好以身作則,再帶動更多的人跟隨。前面討論 contributor 的參與技巧時候說過,加入社區(qū)并首先觀察別人是怎么做的,是一種避免浪費時間的好方法。那么與之相對的,maintainer 也要在項目維護和日常交流方面為此提供方便。
Open Communications: as a virtual organization, the ASF requires all communications related to code and decision-making to be publicly accessible to ensure asynchronous collaboration, as necessitated by a globally-distributed community.?The Apache Way[12]
第四點是考慮自動化。結(jié)構(gòu)化的流程更容易自動化。當(dāng)你的流程越來越結(jié)構(gòu)化,那么是時候考慮自動化它了。顯然,無需 maintainer 親自動手的自動化流程能夠減輕項目維護的壓力。
同樣,最好的自動化是符合直覺的。GitHub 平臺提供了一系列自動化的支持。尤其是?GitHub Actions[13]?發(fā)布以后,自動化的靈活性得到了進一步的提升。利用項目代碼托管的平臺提供的開箱即用的能力做自動化,能夠最大程度的避免各種沖突。
自動化還應(yīng)該建立在現(xiàn)有的成熟流程上,而不應(yīng)該憑空生造一個流程。好的案例包括提交文檔變更后自動部署文檔頁面,利用 merge bot 提高 pull requests review 和 merge 的效率等等。
其中,后者的采用是有兩面性的。許多代碼提交極其活躍的開源社區(qū)也仍然不需要引入自動化流程。當(dāng)然,測試基本是自動化的,至少有腳本。不過 review 和 merge 還是可以人工完成的。我比較認同 merge bot 的地方是有些實現(xiàn)了排隊合并功能以及 roll up 打包測試功能。這兩個功能在保證合入主分支的代碼是基于最新的主分支測試過的前提下,減少了需要進行測試的次數(shù)和人為協(xié)調(diào)的負擔(dān)。但是,有些 merge bot 強制要求 review 和 merge 走非常嚴格的審批流程,把這個過程變得復(fù)雜不堪,這是我非常反對的。所以在引入 merge bot 之前,請確保你清楚地知道它如何改善協(xié)作效率,并保留回滾的能力。
另一個典型的錯誤案例是 stale bot 的自動關(guān)閉功能。真的,沒人喜歡這個功能。開發(fā)者來到社區(qū)是為了和人建立聯(lián)系,共同開發(fā)好的軟件,而不是為了被機器人支配。應(yīng)對 issue 或 PR 的積壓問題,首先應(yīng)該盡可能的及時處理。其次,大部分積壓的 issue 是無效的內(nèi)容,例如愿望清單和模糊的想法,這些只需要快速關(guān)閉即可。對于低優(yōu)先級的 bug issue 的積壓,既然問題是實際存在的,也不是 wontfix 的情形,憑什么關(guān)掉呢?如果當(dāng)前的 maintainers 積極主動地處理 issue 和 PR 還是處理不過來,那么是時候?qū)ふ乙粋€新的 maintainer 了。
Users SHALL NOT log feature requests, ideas, suggestions, or any solutions to problems that are not explicitly documented and provable.?The ZeroMQ Community[14]
流程自動化的標(biāo)桿案例包括?Kubernetes 社區(qū)[15]和?Rust 社區(qū)[16]。在學(xué)習(xí)這兩個社區(qū)的做法的時候,需要強調(diào)的是
1.請關(guān)注這兩個社區(qū)為流程自動化投入了多少人力。2.請關(guān)注這兩個社區(qū)是在什么時候引入了何種自動化邏輯。3.請關(guān)注這兩個社區(qū)的成員如何利用自動化流程。4.請關(guān)注這兩個社區(qū)在流程自動化上的異同。5.請關(guān)注這兩個社區(qū)推行流程自動化時的討論,尤其是爭議。6.請勿貨物崇拜,直接照抄它們的方案。否則你會死得很慘。
既然 Rust 社區(qū)都不抄 Kubernetes 社區(qū)的方案,你為啥貿(mào)貿(mào)然就要抄?
Manage day-to-day events
前面講的是一些整體的做法,回到每個 maintainer 身上,實際的項目維護工作其實是日常事務(wù)。
最常見的問題是開發(fā)的風(fēng)險控制。開源項目通常會有自己的版本發(fā)布周期。有時候你希望下個版本能交付某幾個關(guān)鍵功能或改進,而這些工作并不都是由你一個人完成。尤其是,你之所以想交付這些變更,是因為公司的要求,而開發(fā)團隊包括并非公司員工的成員。這個時候就需要你做好項目的風(fēng)險控制。
從公司員工的角度,我介紹過開源項目和商業(yè)公司獨立運營的協(xié)同模型。運用這個模型,可以把商業(yè)上緊急的需求實現(xiàn)在 fork 倉庫上,交付 hotfix 應(yīng)對緊急情況。稍后,把改動 contribute back 到開源項目當(dāng)中。這樣就可以把商業(yè)要求和軟件開發(fā)的工程要求隔離開來,避免向開源社區(qū)傾倒粗糙的補丁。Stream Native[17]?就在公司組織下有 Apache Pulsar 的 fork 倉庫。我沒有仔細研究過他們的具體做法,但是顯然他們把一些公司關(guān)心的內(nèi)容都放在 fork 倉庫上記錄。讓上帝的歸上帝,凱撒的歸凱撒。這是好文明。
如果評估出來更合適的做法是把改動直接做在上游,那么我會建議在需要嚴格控制風(fēng)險的情況下,直接由公司員工組成開發(fā)團隊。當(dāng)然,這些員工得靠自己的努力在開源社區(qū)當(dāng)中贏得信譽,而不是只根據(jù)職位就被允許直接提交代碼。如果同樣的需求已經(jīng)有其他團隊在做,那么溝通就是必要的。如果信得過這個團隊,保持關(guān)注并提供幫助即可。否則,可以嘗試接管項目開發(fā)。Flink 社區(qū)的?FLIP-85[18]?提案是我和 Uber 的工程師分別獨立提出的。經(jīng)過幾輪郵件列表上的討論,最終由阿里的工程師主導(dǎo)實現(xiàn)。我參與了 review 和提供了部分參考實現(xiàn)。
上面講的是一個好的案例。其實對于一個活躍的開源社區(qū)來說,PR 沖突的情況不會太少,種類也很多。
TiDB 社區(qū)發(fā)生過一起有名的?Xuanwo 事件[19]。完全相同的兩個補丁,后提交的反而先被合入,導(dǎo)致先提交的被迫關(guān)閉。尤其是這個事件發(fā)生在并不繁忙的倉庫上,并且兩個補丁提交的時間相差一個月。這是一種非常典型的情況,需要 maintainers 保持對項目范圍內(nèi)發(fā)生的活動的關(guān)注。
Flink 社區(qū)有不少經(jīng)典的樂子。FLINK-10052[20]?作為我從 2019 年就和 @lamberken 配合修復(fù)完成并經(jīng)過生產(chǎn)環(huán)境驗證的高嚴重性問題,在過去的三年里提交的三個補丁都因為缺乏響應(yīng)最終沒有合并。這也導(dǎo)致不少用戶被迫手動打補丁。FLINK-11937[21]?是另一個例子。兩家員工提供了不同的方案,其中一方缺少社區(qū)話語權(quán),無力單獨推進合并,另一方有能力但是無意推進,也不允許其他人推進。同樣的案例還有?FLIP-44[22]?和?Queryable State[23]?等等。
Flink 的例子其實證明了商業(yè)公司需要通過 fork 倉庫的來應(yīng)對商業(yè)需求。另外也可以看到這些討論的發(fā)起人是如何被 stale bot 二次傷害的。
從開源協(xié)同的角度,contributor 不是程序,而是真實的人。上面提到的溝通手段,去掉公司員工的背景也同樣適用。商業(yè)公司要做風(fēng)險控制,開源社區(qū)也是一個組織,也可以做風(fēng)險控制。只不過,開源社區(qū)是一個開放式組織。在這個環(huán)境下控制風(fēng)險的手段不是管控,而是協(xié)同。前面講到的文檔和結(jié)構(gòu)化的流程在這里同樣可以起作用。信息在 contributor 之間自由流通,就不會有 FUD 產(chǎn)生的傷害。平時保持和其他 contributor 的聯(lián)系,就能知道當(dāng)前的工作最應(yīng)該找誰一起做。
大部分情況下,contributor 是能夠自我驅(qū)動和自我激勵的。他們爆發(fā)出的創(chuàng)造力不可小覷。單就時間上的風(fēng)險而言,如果你在開發(fā)文檔里明確寫下開發(fā)周期和發(fā)布模型,contributor 是樂于見到自己參與或主導(dǎo)開發(fā)的工作隨新版本一起發(fā)布的。越是自我驅(qū)動參與開源社區(qū)的 contributor 越重視積累信譽。這個過程中,如果你作為 shepherd 指導(dǎo)或參與進去,只需要切實地關(guān)注和解決開發(fā)團隊成員遇到的困難,并在需要時幫助他們管理好進度。
其他的溝通技巧和 maintainer 的最佳實踐這里不再展開。Open Source Guides 提供了這個話題非常有益的補充,推薦延伸閱讀。
?Best Practices for Maintainers[24]?Leadership and Governance[25]?Building Welcoming Communities[26]
Have fun and take care of yourself
不論是 contributor 還是 maintainer 你都已經(jīng)通過參與開源社區(qū)為社會創(chuàng)造出了價值。時不時想想你為什么要參與或維護這個項目,回顧這個項目已經(jīng)取得的成就。你已經(jīng)做得很好了。
軟件都有自己的生命周期,開源軟件也不例外。開源社區(qū)的工作也不是你生活的全部。如果你找到了新的樂趣,完全可以把項目交給其他 maintainers 維護,或者直接歸檔。如果開源項目的維護已經(jīng)超出你的能力范圍或者消耗了太多的時間精力,也可以休息一段時間甚至放棄對項目的維護。作為開源社區(qū)成員的你沒有義務(wù)非得維護這個項目或者響應(yīng)別人的請求。你把自己的工作自由的提供給其他人利用,已經(jīng)創(chuàng)造了非??陀^的價值。
References
[1]?Participating in Open Source Communities:?https://www.linuxfoundation.org/tools/participating-in-open-source-communities/[2]?討論區(qū):?https://github.com/engula/engula/discussions[3]?聊天室:?https://discord.gg/AN6vgVXaHC[4]?如何優(yōu)雅地拒絕開源項目的 PR 邀請:?https://www.zhihu.com/question/475269038/answer/2045981148[5]?社區(qū)計劃:?https://github.com/engula/engula.github.io/pull/15[6]?關(guān)于 Dev Guide 的討論:?https://github.com/engula/engula/discussions/84[7]?治理模型:?http://www.apache.org/foundation/how-it-works.html#roles[8]?Apache Pulsar:?https://pulsar.apache.org/en/contributing/#becoming-a-committer[9]?Apache Flink:?https://flink.apache.org/contributing/how-to-contribute.html[10]?Linux Kernel Maintainers 頁面:?https://www.kernel.org/doc/html/latest/process/maintainers.html[11]?修訂 TiDB 社區(qū)的治理方案:?https://github.com/pingcap/community/issues/516[12]?The Apache Way:?https://www.apache.org/theapacheway/index.html[13]?GitHub Actions:?https://github.com/features/actions[14]?The ZeroMQ Community:?https://zguide.zeromq.org/docs/chapter6/[15]?Kubernetes 社區(qū):?https://github.com/kubernetes/test-infra/tree/master/prow[16]?Rust 社區(qū):?https://github.com/rust-lang/homu[17]?Stream Native:?https://github.com/streamnative/pulsar[18]?FLIP-85:?https://issues.apache.org/jira/browse/FLINK-16654[19]?Xuanwo 事件:?https://github.com/pingcap/tipb/pull/208[20]?FLINK-10052:?https://issues.apache.org/jira/browse/FLINK-10052[21]?FLINK-11937:?https://issues.apache.org/jira/browse/FLINK-11937[22]?FLIP-44:?https://cwiki.apache.org/confluence/display/FLINK/FLIP-44%3A+Support+Local+Aggregation+in+Flink[23]?Queryable State:?https://lists.apache.org/thread/snlsb5z9lcogdo7359dcwr4hn5qpymlo[24]?Best Practices for Maintainers:?https://opensource.guide/best-practices[25]?Leadership and Governance:?https://opensource.guide/leadership-and-governance[26]?Building Welcoming Communities:?https://opensource.guide/building-community/#growing-your-community
-關(guān)注我
