0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

前端大仓monorepo权限设计思路和实现方案

OSC开源社区 来源:网络整理 2024-01-12 09:52 次阅读

背景

前端 monorepo 在试行大仓研发流程过程中,已经包含了多个业务域的应用、共享组件库、工具函数等多种静态资源,在实现包括代码共享、依赖管理的便捷性以及更好的团队协作的时候,也面临大仓代码文件权限的问题。如何让不同业务域的研发能够顺畅的在大仓模式下开发,离不开有效的权限管理方法。好的权限管理方法能够确保研发同学轻松找到和理解项目的不同部分,而不受混乱或不必要的复杂性的影响,并且也应该允许研发同学合作并同时工作,同时也要确保代码合并的更改经过代码审查,以维护代码的质量和稳定性。本文通过实践过程中遇到的一些问题以及逐步沉淀下来的最佳实践,来阐述下前端大仓 monorepo 在权限这块是如何思考以及设计的。

前期调研

在做大仓权限设计的时候,前期做了很多的调研,也参考了国内和国外的一些威廉希尔官方网站 文章,总结起来主要是基于以下三点的设计思路去实现:

文件系统的自研,能够做到文件读写权限的完全控制:对于文件系统的自研,国外的最佳实践不外乎是 Google 和 Meta,他们都是大仓实践的典范。对于文件系统的权限控制,有一套自研的文件系统,能够对核心代码和配置文件做到读写权限控制。在 Google 发表的一篇论文《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 内部自研了 Piper,能够支持基于文件级别的访问控制列表,大多数仓库对所有 Piper 用户可见,但是重要的配置文件或包含业务关键算法的文件可以进行更严格的控制,并且对 Piper 中的文件的读写访问都会被记录。

基于Git提供的钩子函数,能做到文件写权限的控制:Git 本身是一个分布式文件系统,其提供了代码研发流程中的各种钩子函数,在不同的钩子函数里面对文件的修改做校验,可以做到代码文件写权限的控制,但是做不到代码文件的读权限控制;

基于Gitlab的能力,对文件目录权限做控制:Gitlab 开始引入了“Protected Environments”的概念,即允许为具体的文件或目录设置权限,并指定哪些用户或用户组拥有文件的“Maintainer”权限,以便管理文件的更改和合并请求,可以用于更细粒度的文件级别权限控制。当然此种方法也只能做到代码文件写权限的控制,做不到代码文件的读权限控制。

从上面的三种调研实现来看,如果要完全做到文件系统的读写权限控制,势必需要自研一套适合研发流程及业务体系的文件系统,这种实现成本会很大,且基于实际的应用场景去考虑,也不是很有必要。所以本文主要围绕基于Git提供的钩子函数和基于Gitlab的能力来阐述过程中是如何实践的

设计实现

在前端 monorepo 实践过程中,对于权限模块的设计如果考虑不好的话,会带来很不好的研发体验,同时权限的实现不仅仅是代码逻辑层面,需要考虑很多方面。在实践过程中,具体考虑了分支模型的定义、角色权限的分配、文件目录权限以及研发流程的权限控制四个方面。

分支模型的定义

分支模型的定义即不同业务域在大仓下文件目录的定义,清晰的目录结构和文件命名规范是非常重要的,研发可以很快速的检索到所需的文件。前端大仓的分支模型定义如下:

bec6d3b0-b073-11ee-8b88-92fbcf53809c.png

Apps:各业务域的目录结

_Share:业务域下通用依赖目录

Abroad-Crm-Micro:具体应用名

...:后续新增的应用都在业务域目录下

Components:业务域下通用组件目录(初始化固定目录)

...:可以自定义扩展目录

Global:国际业务域应用目录

...:后续新增的业务域目录都在 App目录下

Packages:前端平台通用组件、工具函数、配置文件、Hooks 依赖

Components:平台通用组件目录(初始化固定目录)

Hooks:平台通用 Hooks 目录(初始化固定目录)

...:可以自定义扩展目录

通过使用语义化的文件和目录命名,减少了混淆和错误,使得分支模型的定义更加的清晰,研发成员也可以很清楚的知道自己所关注的业务应用在哪个目录下,同时如果需要看其他业务域的代码,也很容易检索到。

上面只是大仓 B 端应用的分支模型定义,目前融合了 C 端 H5 应用以及 Node 服务应用之后,大仓目录的划分会相对比较复杂的多,这里不再具体赘述。

角色权限的分配

在大仓模式下,角色权限没有另辟蹊径,还是沿用 Gitlab 已有的权限配置:Owner、Maintainer 和 Developer。

bed77cc4-b073-11ee-8b88-92fbcf53809c.png

Owner:即代码仓库的所有者,所有者是拥有最高权限的角色,可以对项目进行完全控制。他们可以添加和删除项目成员,修改项目设置,包括访问级别、分支保护规则和集成设置等。只有项目的所有者才能转让或删除项目;权限配置角色为TL

Maintainer:即代码仓库的维护者,可以管理项目的代码、问题、合并请求等。可以创建和管理分支,添加和删除文件,创建和关闭问题,合并和推送分支等。维护者不能更改项目的访问级别或添加新的维护者;权限配置角色为TL/PM

Developer:即代码仓库的开发者,是项目的一般成员,具有对代码进行修改和提交的权限。他们可以创建和分配问题、合并请求,查看代码、提交变更以及推送和拉取分支等。权限配置角色为研发人员。

这里需要考虑的是只要开发者具备 Developer 权限,那么他就可以修改大仓任何目录下的代码,并且本地可以提交,这样会导致本地源码依赖出现很大的风险:会出现本地代码构建和生产环境构建不一致的情况,在研发流程意识不强的情况下很容易引发线上问题。本着对代码共享的原则,对于代码文件读权限不做控制,也允许研发修改代码,但是对修改的代码的发布会做流程上的强管控。这里就会涉及到 Gitlab 的分支保护机制以及文件 Owner 权限配置。

文件目录权限配置

在 GitLab 未支持文件目录权限设置之前,对于文件目录权限的控制主要依赖 Git 的钩子函数,在代码提交的时候,对暂存区的变更文件进行识别并做文件权限校验,流程设计也不怎么复杂,只需要额外再开发文件目录和研发的权限映射配置平台即可。在 GitLab 开始支持文件目录权限设置,可以用于更细粒度的文件级别的权限控制,内部就支持文件目录和研发的权限映射关系,其配置页面如下:

bee499fe-b073-11ee-8b88-92fbcf53809c.png

当有对应的文件或者目录路径下的文件变更的时候,在CodeReview过程中必须由对应的 Owner 成员确认无误之后,才可以MR代码。比如:

.husky/ 表示 .husky 目录下的文件变更,必须由具体的文件 Owner 评审通过才可以 MR;

Apps/XXX/crm/ 表示 Apps/XXX/crm 目录下的文件变更,必须由对应的文件 Owner其中之一审批通过才可以 MR。

通过 GitLab 提供的文件目录权限配置,即使研发可以修改任意目录下的文件代码,但是最终在CodeReview的流程中,需要对应的文件 Owner 进行确认评审,这样就避免了研发在不注意的情况下,提交了原本不该变更的文件的代码,同时也避免了线上问题的发生。

研发流程的权限控制

前面提到的分支模型的定义、角色权限的分配以及文件目录权限的配置都是需要约定俗成的,但是在真实的研发过程中,需要考虑的场景会复杂的多。比如研发可以绕开 MR 的流程,直接本地合并代码到发布分支。对于这类场景,对大仓下的分支做了规范约束以及 MR&CodeReview 流程中的强管控。

保护分支

在大仓研发模式下,主要有四类分支,其命名规范如下:

Dev 分支命名规范:feature-[应用标识]-版本号-自定义

测试分支命名规范:test-[应用标识]-版本号

发布分支命名规范:release-[应用标识]-版本号

热修复分支命名规范:hotfix-[应用标识]-版本号

其中 Feature 分支为开发分支,由 Developer 创建和维护;Release 和 Hotfix分支为保护分支,Developer 和 Maintainer 都可以创建,但是 Developer 角色没有权限直接将 Feature 分支合入 Release 或者 Hotfix 分支,只能由 Maintainer 角色来维护。基于目前不同业务域会经常创建 test 分支用于不同测试环境的部署,这里 test 分支并未设置为保护分支。当然 Matser 分支也是保护分支,只有 Owner 角色才有权限直接将分支代码合并到主干分支。

通过对不同类型的分支的定义,基于 GitLab 提供的保护分支能力,避免了研发本地合并代码的情况,使得 Feature 分支的代码必须走研发流程的 MR&CodeReview 流程,才能最终合入代码。

钩子函数

通过保护分支的约束,避免了本地直接合发布分支带来的风险,但是在本地代码提交的过程中,如果不做权限的校验,就会CodeReview流程中出现文件 Owner 权限不足的情况,为了在代码提交阶段就能识别到非变更文件的提交,这里基于 Git 的钩子函数,做了权限校验,其流程如下:

bef84ee0-b073-11ee-8b88-92fbcf53809c.png

通过 Git Hooks 提供的 Pre-Commit 和 Pre-Push 两个节点做权限校验,防止出错。Pre-Commit 不是必须的,如果影响代码提交的效率,可以跳过这个步骤,Pre-Push 是必须的,不允许非 Owner 做本地发布。

当然这里也会带来一个问题:当迭代的 Release 分支落后于 Master 分支,此时基于 Master 分支创建的 Feature 分支就会和 Release 分支代码不一致,导致出现很多非必要的变更文件,此时研发会很疑惑为什么会出现没有修改过的变更文件。这个问题在大仓研发模式下是无法避免的,通过分析之后,在本地提交阶段,过滤了 Apps 目录的校验,只保留了大仓顶层部分核心文件的权限校验,因为大部分的变更都在业务域下的应用里面,顶层的文件很少会去修改。

MR&CodeReview

通过保护分支的约束以及钩子函数对部分核心文件的校验,减少了很多在 MR&CodeReview 中本该遇到的问题。基于文件 Owner 权限的 MR 和 CodeReview 流程:Commit 阶段 -> Push 阶段 -> 创建 MR -> CodeReview -> 执行 MR,每个阶段的流程如下:

bf06e45a-b073-11ee-8b88-92fbcf53809c.png

Commit 阶段通过对核心文件的 Owner 校验,避免核心文件被乱改的情况;

CodeReview 阶段通过文件 Owner 权限的校验,确保非本身业务域被修改之后被其他业务域的 Owner 知悉。

bf1d4ede-b073-11ee-8b88-92fbcf53809c.png

bf377728-b073-11ee-8b88-92fbcf53809c.png

这里会带来一个问题:当 Release 分支回合 Master 代码的时候,会创建临时 MR,这个过程也会有文件 Owner 权限的校验(比如客服同学同步代码的时候,也会将商家和供应链的代码一起同步过来),就需要其他业务域的文件 Owner CR 通过才行,但 Master 的代码实际已经是 CR 过的,没有必要重复 CR,并且同步频繁的时候,会经常 CR 确认,导致回合代码的效率非常低。这里给效率威廉希尔官方网站 那边提了需求,在 Release 分支回合 Master 代码的时候,不做文件 Owner 的校验。

通过上面对研发流程中的权限控制,避免了出现本地代码构建和生产环境构建不一致的情况,确保了提交代码的质量和稳定性。

扩展思路

通过以上的设计实现,基本上大仓下的权限设计能满足现有的研发模式了。为了弥补文件读权限控制的缺陷,过程中,也考虑了访问控制列表以及文件访问日志的实现,但是最终觉得不是很有必要,就没有在大仓里面应用起来。这里可以分享下访问控制列表以及文件访问日志实现的几种思路。

访问控制列表

访问控制列表即大仓下对文件目录的访问控制,以便更精确地控制对敏感信息或关键代码的访问。之前有提到 Google 和 Meta 都是通过自研的文件系统实现,但是如果不是自研,是不是就一定实现不了了呢,其实未必见得。

VSCode设置文件隐藏

通过在大仓目录下的 .vscode/settings.json 文件配置 files.exclude 属性可以实现文件的显隐,如下:

{
  "files.exclude": {
    "**/scripts": true
  }
}
上面的配置表示大仓目录下的scripts目录是不可见的。

存在的问题: 如果懂 .vscode/settings.json 配置的研发,可以直接本地将 True 改为 False,这里配置就失效了。还有并不是所有研发都是用的 VSCode IDE,还有不少研发用其他的 IDE,每个人的研发习惯不一样,很难做到强约束。

MAC下隐藏文件

MAC 下可以通过 shell 命令设置文件的显隐,如下:


chflags hidden **/scripts

上面的 shell 命令表示隐藏大仓下的 scripts 目录。结合大仓研发模式下提供的代码按需拉取能力,可以在代码拉取的最后环节执行如上的命令,就可以隐藏对应的文件。

存在的问题:如果懂 MAC 下文件显隐的设置,可以在 shell 终端上执行 chflags nohidden **/scripts ,这样 scripts 就会变为可见了,达不到最终的效果。

对于访问权限列表的控制,实际上是可以通过一些其他的方式实现,但其实现思路基本都是治根不治本,起不了多大的作用,所以最后都没有在大仓的研发流程里面体现。

文件访问日志

文件访问日志即当研发打开文件的时候,发送一条日志到服务端并保存下来,这样可以对包含敏感信息的配置文件进行监听, 设置审计日志和监控,以便跟踪谁做了什么操作,并在出现异常情况时能够快速识别和应对问题。通过 VSCode 插件是可以实现的,VSCode 启动之后,提供了对应文件目录路径的打开事件 onDidOpenTextDocument,当研发打开任何文件的时候,都可以触发监听事件,那么我们就能在监听事件里面去做日志发送相关的逻辑,实现文件访问日志记录的功能,大致的实现如下:


export function monitorPermissionOfTargetFile(targetFilePath: string, repoRootPath: string) {
  const targetFileFullPath = repoRootPath + targetFilePath;
  // 打开项目目录下任意文件的回调函数
  vscode.workspace.onDidOpenTextDocument(textDocument => {
    // 获取被打开的文件路径
    const filePath = textDocument.uri.fsPath;
    if (filePath === targetFileFullPath) {
      // 添加日志发送逻辑
    }
  });
}

存在的问题:该功能强依赖 VSCode IDE,只有在 VSCode 里面才能实现,并非所有的研发都在用 VSCode,并且实时监听文件的点击事件也会带来一定的系统开销成本。现在本来打开多个 VSCode IDE,电脑运行就比较慢了,再加上该功能,性能损耗估计会更多。

上面只是提供了大仓权限实践过程中未落地的两个扩展思路,如果还有其他更好的思路能实现文件的读权限控制,欢迎随时沟通交流。

总结

前端 monorepo 大仓的权限设计在实现的过程中,遇到了很多的问题,有些时候想的很好,但是实际在研发流程中会因不同的业务域场景存在不一样的问题。比如基于 Master 新建 Feature 分支还是基于 Release 新建 Feature 分支这个问题就尤其突出,起初基于 Master 新建的 Feature 分支,带来的问题是研发在合 Release 分支的时候,有很多非变更文件,导致 CR 都不清楚具体要看哪些文件;然后改成基于 Release 新建的 Feature 分支,带来的问题是会遗漏部分已发版的 Release 分支代码;最后综合考虑还是基于 Master 新建的 Feature 分支。大仓的权限设计也离不开参与研发流程改造的小伙伴以及效能威廉希尔官方网站 的小伙伴,过程中为了适配大仓的权限,做了很多研发流程的改造以及GitLab能力的扩展,希望本文能给读者带来一定的帮助。

审核编辑:黄飞

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Google
    +关注

    关注

    5

    文章

    1762

    浏览量

    57507
  • 文件系统
    +关注

    关注

    0

    文章

    284

    浏览量

    19904
  • 代码
    +关注

    关注

    30

    文章

    4780

    浏览量

    68529
  • vscode
    +关注

    关注

    1

    文章

    155

    浏览量

    7698

原文标题:前端monorepo大仓权限设计的思考与实现

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    RF360全新移动射频前端解决方案剖析

    前段时间,微波射频网报道了高通新推出的RF360射频前端解决方案(查看详情),新产品首次实现了单个移动终端支持全球所有4G LTE制式和频段的设计。接下来让我们一起深度解析RF360全新移动射频
    发表于 06-27 06:19

    嵌入式linux前端权限控制的相关资料分享

    全局变量,该变量在浏览器关闭之前都有效,这样我们就可以通过设置不同的该变量值,来满足我们前端权限的管理了。源码登陆页面JS验证及sessionStorage()变量赋值&l...
    发表于 11-05 09:28

    基于Web2.0的用户权限管理研究与实现

    研究基于Web2.0的用户权限管理的特征及解决方案,结合RBAC 授权模型,提出一种融合了用户个性化页面组织和多级复杂用户管理的扩展型RBAC权限模型。该方案能够更好地满足Web2.0
    发表于 04-18 09:48 19次下载

    一种新的基于B/S模式的权限管理方案

    本文分析了RBAC 模型存在的局限性,结合高校教务系统权限管理的特点,在给出了 WEB 页面权限指纹概念的基础上提出了一种基于用户功能、分组式授权的新的权限管理方案
    发表于 06-15 09:42 40次下载

    基于RBAC的限制约束在权限控制中的实现

    本文针对当前权限控制框架在权限控制和数据保护方面存在的问题,提出一种新的权限控制解决方案——基于RBAC 的限制约束扩展。文章重点描述了限制约束功能的原理与
    发表于 01-15 16:08 6次下载

    基于ThinkPHP的权限控制模块的设计与实现许宏云

    基于ThinkPHP的权限控制模块的设计与实现_许宏云
    发表于 03-17 08:00 0次下载

    基于DRFM的数据采集前端的设计思路和方法

    本文以DRFM设计为核心,着重介绍了DRFM的数据采集前端的设计思路和方法。在超高速数据采集领域,数百兆乃至1 GHz的采样速度非但在国内,即就在国外也是电路设计的难点。使用基于SRAM的CPLD
    发表于 12-11 12:45 1294次阅读
    基于DRFM的数据采集<b class='flag-5'>前端</b>的设计<b class='flag-5'>思路</b>和方法

    具有撤销用户访问权限的外包数据加密方案

    of network and computer applications,2012,35(4):1367 -1373)进行分析,指出了该方案无法实现对用户访问权限进行撤销的问题。针对该方案
    发表于 12-26 15:20 0次下载
    具有撤销用户访问<b class='flag-5'>权限</b>的外包数据加密<b class='flag-5'>方案</b>

    射频前端幕后英雄走到台前 高通射频前端方案被采纳

    射频前端隐藏在手机内部,设计复杂但是作用关键,近日高通射频前端方案被采纳高通射频前端方案被采纳,高通表示做一个集成化的射频前端解决方案
    发表于 01-15 15:46 3693次阅读

    嵌入式linux简单的前端权限控制

    全局变量,该变量在浏览器关闭之前都有效,这样我们就可以通过设置不同的该变量值,来满足我们前端权限的管理了。源码登陆页面JS验证及sessionStorage()变量赋值 &l...
    发表于 11-02 10:06 1次下载
    嵌入式linux简单的<b class='flag-5'>前端</b><b class='flag-5'>权限</b>控制

    Web前端性能优化思路

    本文旨在整理常见Web前端性能优化的思路,可供前端开发参考。因为力求精简,限于篇幅,所以并未详述具体实施方案。 基于现代Web前端框架的应用
    的头像 发表于 10-18 14:21 972次阅读
    Web<b class='flag-5'>前端</b>性能优化<b class='flag-5'>思路</b>

    基于vite3的monorepo前端工程搭建步骤

    代码库管理方式 - Monorepo: 将多个项目存放在同一个代码库中
    的头像 发表于 06-09 10:21 792次阅读
    基于vite3的<b class='flag-5'>monorepo</b><b class='flag-5'>前端</b>工程搭建步骤

    基于Mybatis拦截器实现数据范围权限

    前端的菜单和按钮权限都可以通过配置来实现,但很多时候,后台查询数据库数据的权限需要通过手动添加SQL来实现
    的头像 发表于 06-20 09:57 1327次阅读
    基于Mybatis拦截器<b class='flag-5'>实现</b>数据范围<b class='flag-5'>权限</b>

    如何实现基于Mybatis拦截器实现数据范围权限呢?

    前端的菜单和按钮权限都可以通过配置来实现,但很多时候,后台查询数据库数据的权限需要通过手动添加SQL来实现
    的头像 发表于 06-20 09:59 1235次阅读
    如何<b class='flag-5'>实现</b>基于Mybatis拦截器<b class='flag-5'>实现</b>数据范围<b class='flag-5'>权限</b>呢?

    oracle系统权限和对象权限的区别

    Oracle系统权限和对象权限是Oracle数据库中的两种不同类型的权限控制机制。虽然它们都是用于限制用户对数据库进行操作的权限,但它们的作用范围和控制粒度有所不同。本文将详细介绍Or
    的头像 发表于 12-05 16:21 1094次阅读