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

GitLab父流水线部分Job失败时,子流水线无法获取工件求助

GitLab CI子流水线获取父流水线失败任务工件的解决方案

问题核心

父流水线中smoke-tests、sanity-tests、patient-api-tests等任务已配置artifacts: when: always,但子流水线的upload-patient-report任务通过needs:pipeline依赖这些父任务时,只要任意父任务失败,子任务就会因无法获取工件报错:

This job could not start because it could not retrieve the needed artifacts.

此外,通过GitLab API在本地CLI能正常下载工件,但CI环境中返回404。需要不使用needs关键字的解决方案。

根本原因

  1. needs:pipeline的限制:GitLab跨流水线依赖时,默认要求依赖的任务必须成功才能获取工件,即使父任务配置了when: always生成工件,失败状态的任务仍会被needs判定为无法提供工件。
  2. CI环境API调用问题:本地使用个人token有权限,但CI环境的CI_JOB_TOKEN默认可能未开启API访问权限,且用分支名下载可能匹配到错误的commit(父流水线对应特定commit,而非分支最新)。

解决方案:通过GitLab API手动下载工件

步骤1:开启CI Job Token的API访问权限

进入项目设置→CI/CD→权限,勾选允许从CI作业访问API,确保CI_JOB_TOKEN能调用GitLab API获取工件。

步骤2:父流水线传递关键变量

修改父流水线的触发任务,直接传递父流水线的commit SHA,避免子流水线调用API获取:

patient-api-tests-trigger:
  stage: trigger jobs
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "push"
      when: never
    - if: $CI_PIPELINE_SOURCE == "web"
      when: always
  needs: ["patient-api-tests"]
  trigger:
    include: .trigger-ci.yml
    strategy: depend
    forward:
      yaml_variables: true
      pipeline_variables: true
  variables:
    PARENT_JOB_NAME: $CI_JOB_NAME
    PARENT_PIPELINE_ID: $CI_PIPELINE_ID
    PARENT_COMMIT_SHA: $CI_COMMIT_SHA # 新增:传递父流水线的commit SHA

步骤3:子流水线修改upload-patient-report任务

移除needs配置,添加手动下载工件的脚本逻辑:

upload-patient-report:
  extends: .upload-report
  stage: upload api report (always)
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: never
    - if: $CI_PIPELINE_SOURCE == "parent_pipeline" && $PARENT_JOB_NAME == "patient-api-tests-trigger"
      when: always
  before_script:
    - echo "Parent Pipeline ID: $PARENT_PIPELINE_ID"
    - apt-get update && apt-get install -y curl jq unzip
    # 定义通用下载函数
    - download_artifact() {
        local JOB_NAME=$1
        echo "Downloading artifacts from job: $JOB_NAME"
        # 用CI_JOB_TOKEN认证,指定父流水线的commit SHA下载对应工件
        curl --fail --location --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" \
          "https://gitlab.ru/api/v4/projects/${CI_PROJECT_ID}/jobs/artifacts/${PARENT_COMMIT_SHA}/download?job=${JOB_NAME}" \
          -o "${JOB_NAME}_artifacts.zip"
        # 解压到临时目录并移动文件到当前工作区
        unzip -q "${JOB_NAME}_artifacts.zip" -d "${JOB_NAME}_temp"
        mv "${JOB_NAME}_temp"/target* "./target_${JOB_NAME}"
        mv "${JOB_NAME}_temp"/mvn_log* ./
        rm -rf "${JOB_NAME}_temp" "${JOB_NAME}_artifacts.zip"
      }
    # 下载所有需要的工件
    - download_artifact "smoke-tests"
    - download_artifact "sanity-tests"
    - download_artifact "patient-api-tests"

关键细节说明

  • CI_JOB_TOKEN认证:CI环境自动生成的CI_JOB_TOKEN拥有当前项目的读取权限,无需手动配置个人token,避免安全风险。
  • 指定commit SHA下载:使用父流水线的PARENT_COMMIT_SHA而非分支名,确保下载的是父流水线对应版本的工件,避免分支更新导致的404。
  • 适配原有上传脚本:将每个任务的target目录重命名为target_<job-name>,匹配原upload-report脚本中mv target_*/allure-results/*的逻辑。

替代方案:上传工件到共享存储

如果API方案不符合需求,可在父流水线的测试任务中,将artifacts上传到GitLab Package Registry或外部存储(如MinIO),子流水线从该存储下载工件。示例(上传到GitLab Generic Package):

# 父流水线测试任务新增上传步骤
.run-tests:
  # ... 原有配置
  after_script:
    - curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" \
        --upload-file "${CI_PROJECT_NAME}-${CI_COMMIT_REF_SLUG}.zip" \
        "https://gitlab.ru/api/v4/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_SHA}/${JOB_NAME}_artifacts.zip"

子流水线则通过API从Package Registry下载对应文件。

内容的提问来源于stack exchange,提问作者Zel Anastasia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 16:54:21