一
背景
前端 monorepo 在試行大倉研發(fā)流程過程中,已經(jīng)包含了多個(gè)業(yè)務(wù)域的應(yīng)用、共享組件庫、工具函數(shù)等多種靜態(tài)資源,在實(shí)現(xiàn)包括代碼共享、依賴管理的便捷性以及更好的團(tuán)隊(duì)協(xié)作的時(shí)候,也面臨大倉代碼文件權(quán)限的問題。如何讓不同業(yè)務(wù)域的研發(fā)能夠順暢的在大倉模式下開發(fā),離不開有效的權(quán)限管理方法。好的權(quán)限管理方法能夠確保研發(fā)同學(xué)輕松找到和理解項(xiàng)目的不同部分,而不受混亂或不必要的復(fù)雜性的影響,并且也應(yīng)該允許研發(fā)同學(xué)合作并同時(shí)工作,同時(shí)也要確保代碼合并的更改經(jīng)過代碼審查,以維護(hù)代碼的質(zhì)量和穩(wěn)定性。本文通過實(shí)踐過程中遇到的一些問題以及逐步沉淀下來的最佳實(shí)踐,來闡述下前端大倉 monorepo 在權(quán)限這塊是如何思考以及設(shè)計(jì)的。
二
前期調(diào)研
在做大倉權(quán)限設(shè)計(jì)的時(shí)候,前期做了很多的調(diào)研,也參考了國內(nèi)和國外的一些技術(shù)文章,總結(jié)起來主要是基于以下三點(diǎn)的設(shè)計(jì)思路去實(shí)現(xiàn):
文件系統(tǒng)的自研,能夠做到文件讀寫權(quán)限的完全控制:對(duì)于文件系統(tǒng)的自研,國外的最佳實(shí)踐不外乎是 Google 和 Meta,他們都是大倉實(shí)踐的典范。對(duì)于文件系統(tǒng)的權(quán)限控制,有一套自研的文件系統(tǒng),能夠?qū)诵拇a和配置文件做到讀寫權(quán)限控制。在 Google 發(fā)表的一篇論文《Why Google stores billions of lines of code in a single repository》中也有提到:
Since Google’s source code is one of the company’s most important assets, security features are a key consideration in Piper’s design. Piper supports file-level access control lists. Most of the repository is visible to all Piper users;d however, important configuration files or files including businesscritical algorithms can be more tightly controlled. In addition, read and write access to files in Piper is logged. If sensitive data is accidentally committed to Piper, the file in question can be purged. The read logs allow administrators to determine if anyone accessed the problematic file before it was removed.
大致的意思是 Google 內(nèi)部自研了 Piper,能夠支持基于文件級(jí)別的訪問控制列表,大多數(shù)倉庫對(duì)所有 Piper 用戶可見,但是重要的配置文件或包含業(yè)務(wù)關(guān)鍵算法的文件可以進(jìn)行更嚴(yán)格的控制,并且對(duì) Piper 中的文件的讀寫訪問都會(huì)被記錄。
基于Git提供的鉤子函數(shù),能做到文件寫權(quán)限的控制:Git 本身是一個(gè)分布式文件系統(tǒng),其提供了代碼研發(fā)流程中的各種鉤子函數(shù),在不同的鉤子函數(shù)里面對(duì)文件的修改做校驗(yàn),可以做到代碼文件寫權(quán)限的控制,但是做不到代碼文件的讀權(quán)限控制;
基于Gitlab的能力,對(duì)文件目錄權(quán)限做控制:Gitlab 開始引入了“Protected Environments”的概念,即允許為具體的文件或目錄設(shè)置權(quán)限,并指定哪些用戶或用戶組擁有文件的“Maintainer”權(quán)限,以便管理文件的更改和合并請(qǐng)求,可以用于更細(xì)粒度的文件級(jí)別權(quán)限控制。當(dāng)然此種方法也只能做到代碼文件寫權(quán)限的控制,做不到代碼文件的讀權(quán)限控制。
從上面的三種調(diào)研實(shí)現(xiàn)來看,如果要完全做到文件系統(tǒng)的讀寫權(quán)限控制,勢(shì)必需要自研一套適合研發(fā)流程及業(yè)務(wù)體系的文件系統(tǒng),這種實(shí)現(xiàn)成本會(huì)很大,且基于實(shí)際的應(yīng)用場景去考慮,也不是很有必要。所以本文主要圍繞基于Git提供的鉤子函數(shù)和基于Gitlab的能力來闡述過程中是如何實(shí)踐的。
三
設(shè)計(jì)實(shí)現(xiàn)
在前端 monorepo 實(shí)踐過程中,對(duì)于權(quán)限模塊的設(shè)計(jì)如果考慮不好的話,會(huì)帶來很不好的研發(fā)體驗(yàn),同時(shí)權(quán)限的實(shí)現(xiàn)不僅僅是代碼邏輯層面,需要考慮很多方面。在實(shí)踐過程中,具體考慮了分支模型的定義、角色權(quán)限的分配、文件目錄權(quán)限以及研發(fā)流程的權(quán)限控制四個(gè)方面。
分支模型的定義
分支模型的定義即不同業(yè)務(wù)域在大倉下文件目錄的定義,清晰的目錄結(jié)構(gòu)和文件命名規(guī)范是非常重要的,研發(fā)可以很快速的檢索到所需的文件。前端大倉的分支模型定義如下:
Apps:各業(yè)務(wù)域的目錄結(jié)
_Share:業(yè)務(wù)域下通用依賴目錄
Abroad-Crm-Micro:具體應(yīng)用名
...:后續(xù)新增的應(yīng)用都在業(yè)務(wù)域目錄下
Components:業(yè)務(wù)域下通用組件目錄(初始化固定目錄)
...:可以自定義擴(kuò)展目錄
Global:國際業(yè)務(wù)域應(yīng)用目錄
...:后續(xù)新增的業(yè)務(wù)域目錄都在 App目錄下
Packages:前端平臺(tái)通用組件、工具函數(shù)、配置文件、Hooks 依賴
Components:平臺(tái)通用組件目錄(初始化固定目錄)
Hooks:平臺(tái)通用 Hooks 目錄(初始化固定目錄)
...:可以自定義擴(kuò)展目錄
通過使用語義化的文件和目錄命名,減少了混淆和錯(cuò)誤,使得分支模型的定義更加的清晰,研發(fā)成員也可以很清楚的知道自己所關(guān)注的業(yè)務(wù)應(yīng)用在哪個(gè)目錄下,同時(shí)如果需要看其他業(yè)務(wù)域的代碼,也很容易檢索到。
上面只是大倉 B 端應(yīng)用的分支模型定義,目前融合了 C 端 H5 應(yīng)用以及 Node 服務(wù)應(yīng)用之后,大倉目錄的劃分會(huì)相對(duì)比較復(fù)雜的多,這里不再具體贅述。
角色權(quán)限的分配
在大倉模式下,角色權(quán)限沒有另辟蹊徑,還是沿用 Gitlab 已有的權(quán)限配置:Owner、Maintainer 和 Developer。
Owner:即代碼倉庫的所有者,所有者是擁有最高權(quán)限的角色,可以對(duì)項(xiàng)目進(jìn)行完全控制。他們可以添加和刪除項(xiàng)目成員,修改項(xiàng)目設(shè)置,包括訪問級(jí)別、分支保護(hù)規(guī)則和集成設(shè)置等。只有項(xiàng)目的所有者才能轉(zhuǎn)讓或刪除項(xiàng)目;權(quán)限配置角色為TL。
Maintainer:即代碼倉庫的維護(hù)者,可以管理項(xiàng)目的代碼、問題、合并請(qǐng)求等。可以創(chuàng)建和管理分支,添加和刪除文件,創(chuàng)建和關(guān)閉問題,合并和推送分支等。維護(hù)者不能更改項(xiàng)目的訪問級(jí)別或添加新的維護(hù)者;權(quán)限配置角色為TL/PM。
Developer:即代碼倉庫的開發(fā)者,是項(xiàng)目的一般成員,具有對(duì)代碼進(jìn)行修改和提交的權(quán)限。他們可以創(chuàng)建和分配問題、合并請(qǐng)求,查看代碼、提交變更以及推送和拉取分支等。權(quán)限配置角色為研發(fā)人員。
這里需要考慮的是只要開發(fā)者具備 Developer 權(quán)限,那么他就可以修改大倉任何目錄下的代碼,并且本地可以提交,這樣會(huì)導(dǎo)致本地源碼依賴出現(xiàn)很大的風(fēng)險(xiǎn):會(huì)出現(xiàn)本地代碼構(gòu)建和生產(chǎn)環(huán)境構(gòu)建不一致的情況,在研發(fā)流程意識(shí)不強(qiáng)的情況下很容易引發(fā)線上問題。本著對(duì)代碼共享的原則,對(duì)于代碼文件讀權(quán)限不做控制,也允許研發(fā)修改代碼,但是對(duì)修改的代碼的發(fā)布會(huì)做流程上的強(qiáng)管控。這里就會(huì)涉及到 Gitlab 的分支保護(hù)機(jī)制以及文件 Owner 權(quán)限配置。
文件目錄權(quán)限配置
在 GitLab 未支持文件目錄權(quán)限設(shè)置之前,對(duì)于文件目錄權(quán)限的控制主要依賴 Git 的鉤子函數(shù),在代碼提交的時(shí)候,對(duì)暫存區(qū)的變更文件進(jìn)行識(shí)別并做文件權(quán)限校驗(yàn),流程設(shè)計(jì)也不怎么復(fù)雜,只需要額外再開發(fā)文件目錄和研發(fā)的權(quán)限映射配置平臺(tái)即可。在 GitLab 開始支持文件目錄權(quán)限設(shè)置,可以用于更細(xì)粒度的文件級(jí)別的權(quán)限控制,內(nèi)部就支持文件目錄和研發(fā)的權(quán)限映射關(guān)系,其配置頁面如下:
當(dāng)有對(duì)應(yīng)的文件或者目錄路徑下的文件變更的時(shí)候,在CodeReview過程中必須由對(duì)應(yīng)的 Owner 成員確認(rèn)無誤之后,才可以MR代碼。比如:
.husky/ 表示 .husky 目錄下的文件變更,必須由具體的文件 Owner 評(píng)審?fù)ㄟ^才可以 MR;
Apps/XXX/crm/ 表示 Apps/XXX/crm 目錄下的文件變更,必須由對(duì)應(yīng)的文件 Owner其中之一審批通過才可以 MR。
通過 GitLab 提供的文件目錄權(quán)限配置,即使研發(fā)可以修改任意目錄下的文件代碼,但是最終在CodeReview的流程中,需要對(duì)應(yīng)的文件 Owner 進(jìn)行確認(rèn)評(píng)審,這樣就避免了研發(fā)在不注意的情況下,提交了原本不該變更的文件的代碼,同時(shí)也避免了線上問題的發(fā)生。
研發(fā)流程的權(quán)限控制
前面提到的分支模型的定義、角色權(quán)限的分配以及文件目錄權(quán)限的配置都是需要約定俗成的,但是在真實(shí)的研發(fā)過程中,需要考慮的場景會(huì)復(fù)雜的多。比如研發(fā)可以繞開 MR 的流程,直接本地合并代碼到發(fā)布分支。對(duì)于這類場景,對(duì)大倉下的分支做了規(guī)范約束以及 MR&CodeReview 流程中的強(qiáng)管控。
保護(hù)分支
在大倉研發(fā)模式下,主要有四類分支,其命名規(guī)范如下:
Dev 分支命名規(guī)范:feature-[應(yīng)用標(biāo)識(shí)]-版本號(hào)-自定義
測(cè)試分支命名規(guī)范:test-[應(yīng)用標(biāo)識(shí)]-版本號(hào)
發(fā)布分支命名規(guī)范:release-[應(yīng)用標(biāo)識(shí)]-版本號(hào)
熱修復(fù)分支命名規(guī)范:hotfix-[應(yīng)用標(biāo)識(shí)]-版本號(hào)
其中 Feature 分支為開發(fā)分支,由 Developer 創(chuàng)建和維護(hù);Release 和 Hotfix分支為保護(hù)分支,Developer 和 Maintainer 都可以創(chuàng)建,但是 Developer 角色沒有權(quán)限直接將 Feature 分支合入 Release 或者 Hotfix 分支,只能由 Maintainer 角色來維護(hù)。基于目前不同業(yè)務(wù)域會(huì)經(jīng)常創(chuàng)建 test 分支用于不同測(cè)試環(huán)境的部署,這里 test 分支并未設(shè)置為保護(hù)分支。當(dāng)然 Matser 分支也是保護(hù)分支,只有 Owner 角色才有權(quán)限直接將分支代碼合并到主干分支。
通過對(duì)不同類型的分支的定義,基于 GitLab 提供的保護(hù)分支能力,避免了研發(fā)本地合并代碼的情況,使得 Feature 分支的代碼必須走研發(fā)流程的 MR&CodeReview 流程,才能最終合入代碼。
鉤子函數(shù)
通過保護(hù)分支的約束,避免了本地直接合發(fā)布分支帶來的風(fēng)險(xiǎn),但是在本地代碼提交的過程中,如果不做權(quán)限的校驗(yàn),就會(huì)在CodeReview流程中出現(xiàn)文件 Owner 權(quán)限不足的情況,為了在代碼提交階段就能識(shí)別到非變更文件的提交,這里基于 Git 的鉤子函數(shù),做了權(quán)限校驗(yàn),其流程如下:
通過 Git Hooks 提供的 Pre-Commit 和 Pre-Push 兩個(gè)節(jié)點(diǎn)做權(quán)限校驗(yàn),防止出錯(cuò)。Pre-Commit 不是必須的,如果影響代碼提交的效率,可以跳過這個(gè)步驟,Pre-Push 是必須的,不允許非 Owner 做本地發(fā)布。
當(dāng)然這里也會(huì)帶來一個(gè)問題:當(dāng)?shù)?Release 分支落后于 Master 分支,此時(shí)基于 Master 分支創(chuàng)建的 Feature 分支就會(huì)和 Release 分支代碼不一致,導(dǎo)致出現(xiàn)很多非必要的變更文件,此時(shí)研發(fā)會(huì)很疑惑為什么會(huì)出現(xiàn)沒有修改過的變更文件。這個(gè)問題在大倉研發(fā)模式下是無法避免的,通過分析之后,在本地提交階段,過濾了 Apps 目錄的校驗(yàn),只保留了大倉頂層部分核心文件的權(quán)限校驗(yàn),因?yàn)榇蟛糠值淖兏荚跇I(yè)務(wù)域下的應(yīng)用里面,頂層的文件很少會(huì)去修改。
MR&CodeReview
通過保護(hù)分支的約束以及鉤子函數(shù)對(duì)部分核心文件的校驗(yàn),減少了很多在 MR&CodeReview 中本該遇到的問題。基于文件 Owner 權(quán)限的 MR 和 CodeReview 流程:Commit 階段 -> Push 階段 -> 創(chuàng)建 MR -> CodeReview -> 執(zhí)行 MR,每個(gè)階段的流程如下:
Commit 階段通過對(duì)核心文件的 Owner 校驗(yàn),避免核心文件被亂改的情況;
CodeReview 階段通過文件 Owner 權(quán)限的校驗(yàn),確保非本身業(yè)務(wù)域被修改之后被其他業(yè)務(wù)域的 Owner 知悉。
這里會(huì)帶來一個(gè)問題:當(dāng) Release 分支回合 Master 代碼的時(shí)候,會(huì)創(chuàng)建臨時(shí) MR,這個(gè)過程也會(huì)有文件 Owner 權(quán)限的校驗(yàn)(比如客服同學(xué)同步代碼的時(shí)候,也會(huì)將商家和供應(yīng)鏈的代碼一起同步過來),就需要其他業(yè)務(wù)域的文件 Owner CR 通過才行,但 Master 的代碼實(shí)際已經(jīng)是 CR 過的,沒有必要重復(fù) CR,并且同步頻繁的時(shí)候,會(huì)經(jīng)常 CR 確認(rèn),導(dǎo)致回合代碼的效率非常低。這里給效率技術(shù)那邊提了需求,在 Release 分支回合 Master 代碼的時(shí)候,不做文件 Owner 的校驗(yàn)。
通過上面對(duì)研發(fā)流程中的權(quán)限控制,避免了出現(xiàn)本地代碼構(gòu)建和生產(chǎn)環(huán)境構(gòu)建不一致的情況,確保了提交代碼的質(zhì)量和穩(wěn)定性。
四
擴(kuò)展思路
通過以上的設(shè)計(jì)實(shí)現(xiàn),基本上大倉下的權(quán)限設(shè)計(jì)能滿足現(xiàn)有的研發(fā)模式了。為了彌補(bǔ)文件讀權(quán)限控制的缺陷,過程中,也考慮了訪問控制列表以及文件訪問日志的實(shí)現(xiàn),但是最終覺得不是很有必要,就沒有在大倉里面應(yīng)用起來。這里可以分享下訪問控制列表以及文件訪問日志實(shí)現(xiàn)的幾種思路。
訪問控制列表
訪問控制列表即大倉下對(duì)文件目錄的訪問控制,以便更精確地控制對(duì)敏感信息或關(guān)鍵代碼的訪問。之前有提到 Google 和 Meta 都是通過自研的文件系統(tǒng)實(shí)現(xiàn),但是如果不是自研,是不是就一定實(shí)現(xiàn)不了了呢,其實(shí)未必見得。
VSCode設(shè)置文件隱藏
通過在大倉目錄下的 .vscode/settings.json 文件配置 files.exclude 屬性可以實(shí)現(xiàn)文件的顯隱,如下:
{ "files.exclude": { "**/scripts": true } }
上面的配置表示大倉目錄下的scripts目錄是不可見的。
存在的問題: 如果懂 .vscode/settings.json 配置的研發(fā),可以直接本地將 True 改為 False,這里配置就失效了。還有并不是所有研發(fā)都是用的 VSCode IDE,還有不少研發(fā)用其他的 IDE,每個(gè)人的研發(fā)習(xí)慣不一樣,很難做到強(qiáng)約束。
MAC下隱藏文件
MAC 下可以通過 shell 命令設(shè)置文件的顯隱,如下:
chflags hidden **/scripts
上面的 shell 命令表示隱藏大倉下的 scripts 目錄。結(jié)合大倉研發(fā)模式下提供的代碼按需拉取能力,可以在代碼拉取的最后環(huán)節(jié)執(zhí)行如上的命令,就可以隱藏對(duì)應(yīng)的文件。
存在的問題:如果懂 MAC 下文件顯隱的設(shè)置,可以在 shell 終端上執(zhí)行 chflags nohidden **/scripts ,這樣 scripts 就會(huì)變?yōu)榭梢娏耍_(dá)不到最終的效果。
對(duì)于訪問權(quán)限列表的控制,實(shí)際上是可以通過一些其他的方式實(shí)現(xiàn),但其實(shí)現(xiàn)思路基本都是治根不治本,起不了多大的作用,所以最后都沒有在大倉的研發(fā)流程里面體現(xiàn)。
文件訪問日志
文件訪問日志即當(dāng)研發(fā)打開文件的時(shí)候,發(fā)送一條日志到服務(wù)端并保存下來,這樣可以對(duì)包含敏感信息的配置文件進(jìn)行監(jiān)聽, 設(shè)置審計(jì)日志和監(jiān)控,以便跟蹤誰做了什么操作,并在出現(xiàn)異常情況時(shí)能夠快速識(shí)別和應(yīng)對(duì)問題。通過 VSCode 插件是可以實(shí)現(xiàn)的,VSCode 啟動(dòng)之后,提供了對(duì)應(yīng)文件目錄路徑的打開事件 onDidOpenTextDocument,當(dāng)研發(fā)打開任何文件的時(shí)候,都可以觸發(fā)監(jiān)聽事件,那么我們就能在監(jiān)聽事件里面去做日志發(fā)送相關(guān)的邏輯,實(shí)現(xiàn)文件訪問日志記錄的功能,大致的實(shí)現(xiàn)如下:
export function monitorPermissionOfTargetFile(targetFilePath: string, repoRootPath: string) { const targetFileFullPath = repoRootPath + targetFilePath; // 打開項(xiàng)目目錄下任意文件的回調(diào)函數(shù) vscode.workspace.onDidOpenTextDocument(textDocument => { // 獲取被打開的文件路徑 const filePath = textDocument.uri.fsPath; if (filePath === targetFileFullPath) { // 添加日志發(fā)送邏輯 } }); }
存在的問題:該功能強(qiáng)依賴 VSCode IDE,只有在 VSCode 里面才能實(shí)現(xiàn),并非所有的研發(fā)都在用 VSCode,并且實(shí)時(shí)監(jiān)聽文件的點(diǎn)擊事件也會(huì)帶來一定的系統(tǒng)開銷成本。現(xiàn)在本來打開多個(gè) VSCode IDE,電腦運(yùn)行就比較慢了,再加上該功能,性能損耗估計(jì)會(huì)更多。
上面只是提供了大倉權(quán)限實(shí)踐過程中未落地的兩個(gè)擴(kuò)展思路,如果還有其他更好的思路能實(shí)現(xiàn)文件的讀權(quán)限控制,歡迎隨時(shí)溝通交流。
五
總結(jié)
前端 monorepo 大倉的權(quán)限設(shè)計(jì)在實(shí)現(xiàn)的過程中,遇到了很多的問題,有些時(shí)候想的很好,但是實(shí)際在研發(fā)流程中會(huì)因不同的業(yè)務(wù)域場景存在不一樣的問題。比如基于 Master 新建 Feature 分支還是基于 Release 新建 Feature 分支這個(gè)問題就尤其突出,起初基于 Master 新建的 Feature 分支,帶來的問題是研發(fā)在合 Release 分支的時(shí)候,有很多非變更文件,導(dǎo)致 CR 都不清楚具體要看哪些文件;然后改成基于 Release 新建的 Feature 分支,帶來的問題是會(huì)遺漏部分已發(fā)版的 Release 分支代碼;最后綜合考慮還是基于 Master 新建的 Feature 分支。大倉的權(quán)限設(shè)計(jì)也離不開參與研發(fā)流程改造的小伙伴以及效能技術(shù)的小伙伴,過程中為了適配大倉的權(quán)限,做了很多研發(fā)流程的改造以及GitLab能力的擴(kuò)展,希望本文能給讀者帶來一定的幫助。
審核編輯:黃飛
-
Google
+關(guān)注
關(guān)注
5文章
1787瀏覽量
58671 -
文件系統(tǒng)
+關(guān)注
關(guān)注
0文章
293瀏覽量
20288 -
代碼
+關(guān)注
關(guān)注
30文章
4886瀏覽量
70253 -
vscode
+關(guān)注
關(guān)注
1文章
167瀏覽量
8364
原文標(biāo)題:前端monorepo大倉權(quán)限設(shè)計(jì)的思考與實(shí)現(xiàn)
文章出處:【微信號(hào):OSC開源社區(qū),微信公眾號(hào):OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
RF360全新移動(dòng)射頻前端解決方案剖析
嵌入式linux前端權(quán)限控制的相關(guān)資料分享
基于Web2.0的用戶權(quán)限管理研究與實(shí)現(xiàn)
一種新的基于B/S模式的權(quán)限管理方案
基于RBAC的限制約束在權(quán)限控制中的實(shí)現(xiàn)
基于ThinkPHP的權(quán)限控制模塊的設(shè)計(jì)與實(shí)現(xiàn)許宏云
基于DRFM的數(shù)據(jù)采集前端的設(shè)計(jì)思路和方法

具有撤銷用戶訪問權(quán)限的外包數(shù)據(jù)加密方案

射頻前端幕后英雄走到臺(tái)前 高通射頻前端方案被采納
嵌入式linux簡單的前端權(quán)限控制

Web前端性能優(yōu)化思路

基于Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)范圍權(quán)限

如何實(shí)現(xiàn)基于Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)范圍權(quán)限呢?

評(píng)論