You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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"'

第二步:配置两个调度任务

  1. 常规调度:在GitLab项目的「CI/CD > 调度」里新建,设置每4小时触发,不需要添加额外变量(或者手动设置IS_RETRY_PIPELINE=false)
  2. 重试调度:新建另一个调度,设置在常规调度执行后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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 10:40:32