GitLab CI跨子流水线下载工件:Job ID传递及数据库复用问题
解决GitLab CI父子流水线间传递Job ID及跨流水线下载Artifacts的问题
一、父子流水线传递Job ID的两种实用方案
1. 子流水线输出Job ID为Artifacts,父流水线读取
在生成数据库资源的子流水线中,将当前Job ID写入文件并作为Artifacts上传,父流水线下载该Artifacts即可获取目标Job ID。
子流水线(如Product-Tables项目)CI配置示例:
generate-dump: stage: build script: - mysqldump -u root -p$DB_PASSWORD product_db > dump.sql - echo "$CI_JOB_ID" > job_id.txt # 将当前Job ID写入文件 artifacts: paths: - dump.sql - job_id.txt expire_in: 1h # 设置过期时间,减少存储占用
父流水线获取Job ID的脚本:
fetch-product-job-id: stage: prepare script: # 触发子流水线后,通过GitLab API获取其最新成功Job的ID(或直接下载子流水线的artifacts) - 'curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/123/jobs?scope=success&ref=main" | jq -r ".[0].id" > product_job_id.txt' artifacts: paths: - product_job_id.txt
2. 跨项目needs关联(推荐,GitLab 13.10+支持)
直接通过needs关联其他项目的成功Job,自动下载其Artifacts,无需手动传递Job ID。
父流水线配置示例:
test-microservice: stage: test needs: - project: your-group/Product-Tables job: generate-dump ref: main artifacts: true - project: your-group/Database-Users job: export-grants ref: main artifacts: true services: - mysql:8.0 script: # 直接使用自动下载的文件导入数据库 - mysql -h mysql -u root -p$MYSQL_ROOT_PASSWORD test_db < dump.sql - mysql -h mysql -u root -p$MYSQL_ROOT_PASSWORD < users-grants.sql variables: MYSQL_ROOT_PASSWORD: test123 MYSQL_DATABASE: test_db
二、手动通过Job ID下载Artifacts的正确命令
如果必须手动下载,使用GitLab API的标准命令:
# 下载指定Job的所有Artifacts curl --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.example.com/api/v4/projects/<项目ID>/jobs/<Job ID>/artifacts" -o artifacts.zip unzip artifacts.zip # 直接下载单个文件 curl --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.example.com/api/v4/projects/<项目ID>/jobs/<Job ID>/artifacts/dump.sql" -o dump.sql
关键注意事项:
$GITLAB_API_TOKEN可使用$CI_JOB_TOKEN(仅限同组项目,需确保权限足够),或创建项目级访问令牌并赋予read_api、read_repository权限。- 确保Runner能访问GitLab API地址。
三、完整端到端示例
1. 数据库资源生成项目(Product-Tables)的.gitlab-ci.yml
stages: - generate generate-dump: stage: generate image: mysql:8.0 script: # 模拟生成测试表和权限文件 - echo "CREATE TABLE products (id INT PRIMARY KEY);" > dump.sql - echo "GRANT ALL ON test_db.* TO 'test_user'@'%' IDENTIFIED BY 'test_pass';" > users-grants.sql - echo "$CI_JOB_ID" > job_id.txt artifacts: paths: - dump.sql - users-grants.sql - job_id.txt expire_in: 1h
2. 微服务测试项目的父流水线.gitlab-ci.yml
stages: - fetch-resources - test fetch-db-resources: stage: fetch-resources image: curlimages/curl:latest script: # 转义项目路径为URL兼容格式 - PROJECT_PATH=$(echo "your-group/Product-Tables" | sed s/\\//%2F/g) # 获取最新成功的generate-dump Job ID - 'curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$PROJECT_PATH/jobs?scope=success&ref=main" | jq -r ".[0].id" > product_job_id.txt' # 下载所需文件 - curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$PROJECT_PATH/jobs/$(cat product_job_id.txt)/artifacts/dump.sql" -o dump.sql - curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$PROJECT_PATH/jobs/$(cat product_job_id.txt)/artifacts/users-grants.sql" -o users-grants.sql artifacts: paths: - dump.sql - users-grants.sql expire_in: 30m test-microservice: stage: test needs: ["fetch-resources"] image: python:3.10 services: - name: mysql:8.0 alias: mysql script: # 安装MySQL客户端 - apt-get update && apt-get install -y mysql-client # 等待MySQL启动就绪 - until mysqladmin ping -h mysql -u root -p$MYSQL_ROOT_PASSWORD --silent; do sleep 1; done # 创建测试库并导入数据 - mysql -h mysql -u root -p$MYSQL_ROOT_PASSWORD -e "CREATE DATABASE test_db;" - mysql -h mysql -u root -p$MYSQL_ROOT_PASSWORD test_db < dump.sql - mysql -h mysql -u root -p$MYSQL_ROOT_PASSWORD < users-grants.sql # 运行微服务测试 - python -m pytest tests/ -v variables: MYSQL_ROOT_PASSWORD: test123
额外提醒
- 使用
$CI_JOB_TOKEN时,确保父、子项目在同一GitLab组,或子项目已配置允许外部项目访问其Artifacts。 - 跨项目
needs需在GitLab设置中开启"Pipeline subscriptions",并授予父项目访问子项目流水线的权限。 - 合理设置Artifacts过期时间,避免不必要的存储消耗。
内容的提问来源于stack exchange,提问作者St. Jan
相关产品推荐
相关产品推荐

