如何在GitLab预接收钩子中识别提交的来源操作
GitLab 预接收钩子触发来源判断方案
核心结论
GitLab 实例、群组、项目三个层级的预接收钩子执行环境中,没有和 GitHub GITHUB_VIA 等价、可直接标记提交触发来源的环境变量,官方公开的预接收钩子上下文清单未提供对应字段,无法照搬GitHub的示例逻辑,直接读取变量判断操作是来自Web端MR合并按钮、API调用还是本地推送。
GitLab 预接收钩子可读取的内置环境变量
钩子执行时默认注入的上下文相关变量如下,所有变量均无法直接区分操作的触发入口:
GL_ID:触发操作的身份标识,格式为user-<用户ID>对应登录用户账号、key-<密钥ID>对应用户配置的SSH密钥GL_USERNAME:触发操作的GitLab账号用户名GL_PROJECT_PATH:当前操作所属项目的路径,格式为群组名/项目名GL_REPOSITORY:仓库的内部唯一标识GL_PROTOCOL:本次推送使用的传输协议,值为ssh或http/https,仅能区分数据传输通道,无法识别操作是来自本地git命令、Web界面还是API调用
默认分支保护的实现方案
参考GitHub示例要实现的「默认分支仅允许通过合并请求合入,禁止直接推送、界面直接编辑、API直接提交」需求,有两种成熟落地路径:
- 优先使用GitLab原生分支保护规则
不需要自定义编写钩子,直接在项目仓库设置的受保护分支配置项中,将默认分支的「允许推送」权限设为「无」,「允许合并」权限设为对应可信角色(如维护者、开发者),即可覆盖所有操作场景:自动拦截本地git直接推送、Web端文件编辑、API直接提交变更,仅允许通过合并请求流程合入代码,稳定性远高于自定义脚本。 - 自定义预接收钩子的变通判断逻辑
如果有特殊规则必须通过自定义钩子实现,可通过提交特征间接判断是否为合法MR合并操作:- 读取钩子标准输入传入的
oldrev newrev refname记录,匹配到默认分支的更新请求时,提取本次要合入的所有新提交 - 校验新提交序列是否包含GitLab MR合并生成的标准格式提交:这类提交的说明默认带
Merge branch '<源分支名>' into '<目标分支名>'标识,且关联的合并请求处于已审核通过、触发合并的合法状态 - 所有非MR合并触发的变更(直接推送、Web编辑、API直提)都不会生成带上述特征的合并提交,可直接拦截返回错误
- 读取钩子标准输入传入的
注意:不要通过判断触发用户是否为GitLab内置服务账号来识别MR合并操作,不同版本GitLab的合并执行身份逻辑存在差异,会出现大量误判。
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

