如何在GitLab CI中查询上一次流水线执行状态以决定是否运行?
GitLab CI流水线状态检查与重试调度方案
针对你遇到的定时流水线拉取镜像失败、需要30分钟后重试的问题,你可以通过GitLab API查询上一次流水线状态,结合调度变量来控制当前流水线是否执行,具体实现如下:
1. 核心逻辑
- 用GitLab CI自带的
CI_JOB_TOKEN调用API,获取项目上一次流水线的状态 - 给两个调度任务分别设置标识变量:常规4小时调度不设特殊变量,30分钟重试调度设置
IS_RETRY_PIPELINE=true - 根据变量和上次流水线状态,决定当前流水线是否继续执行
2. 具体配置
第一步:添加状态检查前置作业
在你的gitlab-ci.yml里加一个前置作业,专门做状态校验,校验不通过就终止流水线:
stages: - check_status - pull_build # 其他阶段... check_pipeline_status: stage: check_status image: alpine:latest before_script: - apk add --no-cache curl jq # 安装必要工具 script: # 获取上一次非当前运行的流水线状态(取列表第2条,因为第1条是当前流水线) - LAST_STATUS=$(curl -s --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/pipelines?per_page=2" | jq -r '.[1].status') # 分情况判断 if [ "$IS_RETRY_PIPELINE" = "true" ]; then # 重试调度:只有上次流水线失败才继续 if [ "$LAST_STATUS" = "failed" ]; then echo "上次流水线失败,开始重试" exit 0 else echo "上次流水线状态是$LAST_STATUS,不需要重试" exit 1 fi else # 常规调度:只有上次成功或无历史流水线才执行 if [ -z "$LAST_STATUS" ] || [ "$LAST_STATUS" = "success" ]; then echo "上次流水线正常,执行常规调度" exit 0 else echo "上次流水线失败,跳过本次常规调度,等重试触发" exit 1 fi fi rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' # 只对调度触发的流水线做检查 allow_failure: false # 检查不通过直接停掉流水线 # 你的拉取镜像作业示例 pull_and_build_image: stage: pull_build image: docker:latest services: - docker:dind script: - docker pull your-registry/your-image:latest # 后续构建/测试步骤... rules: - if: '$CI_PIPELINE_SOURCE == "schedule"'
第二步:配置两个调度任务
- 常规调度:在GitLab项目的「CI/CD > 调度」里新建,设置每4小时触发,不需要添加额外变量(或者手动设置
IS_RETRY_PIPELINE=false) - 重试调度:新建另一个调度,设置在常规调度执行后30分钟触发(比如常规是0点、4点触发,重试就设0:30、4:30),添加变量
IS_RETRY_PIPELINE=true
3. 额外优化(可选)
如果需要确保重试调度确实是在失败后的30分钟内触发,可以加上时间差校验:
在check_pipeline_status的脚本里添加:
# 获取上次流水线的结束时间并转成时间戳 LAST_FINISHED=$(curl -s --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/pipelines?per_page=2" | jq -r '.[1].finished_at') LAST_TIMESTAMP=$(date -d "$LAST_FINISHED" +%s) CURRENT_TIMESTAMP=$(date +%s) DIFF_MINUTES=$(( (CURRENT_TIMESTAMP - LAST_TIMESTAMP) / 60 )) # 在重试调度的判断里加时间校验 if [ "$IS_RETRY_PIPELINE" = "true" ]; then if [ "$LAST_STATUS" = "failed" ] && [ "$DIFF_MINUTES" -le 35 ]; then # 留5分钟误差 echo "上次失败且在30分钟内,开始重试" exit 0 else echo "不符合重试条件,终止" exit 1 fi fi
注意事项
CI_JOB_TOKEN默认有读取流水线信息的权限,不用额外配置,除非项目权限做了严格限制- 确保使用的镜像能安装
curl和jq,或者直接用预装了这些工具的镜像(比如alpine/curl+jq)
内容的提问来源于stack exchange,提问作者sliders_alpha
相关产品推荐
相关产品推荐

