如何统计GitLab合并请求内根流水线数 生成MR维度自增流水线ID
GitLab MR维度自增流水线ID实现方案
GitLab目前没有内置MR范围的自增流水线ID预定义变量,所有实现都需要基于MR上下文做计数,以下是两种最轻量的实现,优先推荐第一种通用方案。
方案1:单API调用实现(通用无场景限制)
你之前找到的方案冗余点主要在于做了不必要的全量流水线遍历、额外的子流水线过滤逻辑,实际上GitLab的单MR关联流水线接口默认就只返回和MR直接绑定的根流水线,自动排除下游触发的子流水线,和MR页面展示的流水线列表完全一致,一次接口调用就能拿到需要的所有数据。
最简实现只需要一个初始化job计算序号,通过dotenv artifact把变量传递给后续所有job,不需要额外依赖:
stages: - init - # 其他你的业务阶段,比如build、test、deploy calc_mr_pipeline_seq: stage: init # 仅在MR触发的根流水线执行 rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" script: # 拉取当前MR关联的根流水线列表,按创建时间倒序,只返回ID字段减少传输量 # 这里可以根据你的实际触发场景调整source过滤条件,下面覆盖了push、手动触发、MR事件、定时触发几种常见根流水线来源 - | PIPELINE_LIST=$(curl -s --header "JOB-TOKEN: $CI_JOB_TOKEN" \ "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/pipelines?source[]=push&source[]=web&source[]=schedule&source[]=merge_request_event&per_page=100" \ | jq -r '.[].id') # 遍历列表找到当前流水线的位置,索引值就是从0开始的自增序号 - | MR_PIPELINE_SEQ=0 for p_id in $PIPELINE_LIST; do if [ "$p_id" -eq "$CI_PIPELINE_ID" ]; then break fi MR_PIPELINE_SEQ=$((MR_PIPELINE_SEQ + 1)) done # 需要序号从1开始的话,打开下面这行注释即可 # MR_PIPELINE_SEQ=$((MR_PIPELINE_SEQ + 1)) - echo "MR_PIPELINE_SEQ=${MR_PIPELINE_SEQ}" >> seq.env artifacts: reports: dotenv: seq.env # 后续所有job直接使用$MR_PIPELINE_SEQ即可 your_other_job: stage: build script: - echo "当前流水线是本MR的第${MR_PIPELINE_SEQ}次执行"
这个方案的优势:
- 不需要手动创建个人访问令牌,GitLab 16.0+版本直接用内置的
CI_JOB_TOKEN即可,只要在项目CI/CD设置里打开「允许CI作业令牌访问项目API」开关 - 单MR流水线数量不超过100时仅需1次API请求,执行速度极快;如果你的单MR流水线确实超过100,加个简单的分页遍历逻辑即可,这种场景极少遇到
- 自动过滤下游子流水线,计数和MR页面展示的流水线序号完全对齐
方案2:零API调用实现(有场景限制)
如果你所有MR流水线都只由推送到源分支的动作触发,没有手动运行、定时触发、API触发的根流水线,可以直接用Git提交计数实现,完全不需要请求API:
variables: # 替换为你项目的默认目标分支,比如master MR_TARGET_BRANCH: "main" calc_seq_by_git: stage: init rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PIPELINE_SOURCE == "push" script: - git fetch origin $MR_TARGET_BRANCH --depth=0 # 统计当前分支相对目标分支的独有提交数,减1得到从0开始的序号 - COMMIT_COUNT=$(git rev-list --count HEAD ^origin/${MR_TARGET_BRANCH}) - MR_PIPELINE_SEQ=$((COMMIT_COUNT - 1)) - echo "MR_PIPELINE_SEQ=${MR_PIPELINE_SEQ}" >> seq.env artifacts: reports: dotenv: seq.env
这个方案的局限性:
- 存在非push触发的MR根流水线时,计数会错位
- MR源分支做变基、强制推送后,提交计数会变化,可能出现序号重复、跳号的问题
- 优点是完全不需要API权限,执行速度最快
避坑说明
不要直接用内置的CI_PIPELINE_IID变量,这个变量是项目全局维度的自增ID,跨MR会跳号,不符合MR范围内自增的需求。
内容的提问来源于stack exchange,提问作者cbuchart
相关产品推荐
相关产品推荐

