简短概述
在Gitlab CI中,如何在不同流水线的作业之间传递数据,例如$BUILD_VERSION
变量?
我的情况是这样的:
Pipeline 1 on push ect. Pipeline 2 after merge
`building` job ... `deploying` job
│ ▲
└─────── $BUILD_VERSION ─────────┘
背景
考虑以下示例(完整的yml
如下):
building:
stage: staging
# only on merge requests
rules:
# execute when a merge request is open
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: always
- when: never
script:
- echo "BUILD_VERSION=1.2.3" > build.env
artifacts:
reports:
dotenv: build.env
deploying:
stage: deploy
# after merge request is merged
rules:
# execute when a branch was merged to staging
- if: $CI_COMMIT_BRANCH == $STAGING_BRANCH
when: always
- when: never
dependencies:
- building
script:
- echo $BUILD_VERSION
我有两个阶段,分别是staging和deploy。在staging中,
building
工作构建应用程序并创建“Review App”(为简单起见,没有单独的构建阶段)。然后,在deploy中,deploying
工作上传新的应用程序。包含
building
工作的流水线在打开合并请求时运行。这样,应用程序就会被构建,并且开发人员可以在合并请求中点击“Review App”图标。合并请求合并后,deploying
工作立即运行。思路如下: *staging* stage (pipeline 1) *deploy* stage (pipeline 2)
<open merge request> -> `building` job (and show) ... <merge> -> `deploying` job
│ ▲
└───────────── $BUILD_VERSION ───────────────┘
对我来说问题是,staging/
building
会创建一些数据,例如$BUILD_VERSION
。我希望在deploy/deploying
中使用这个$BUILD_VERSION
,例如通过Gitlab API创建一个新的发布版本。所以我的问题是:如何将
$BUILD_VERSION
(和其他数据)从staging/building
传递到deploy/deploying
?
我迄今为止尝试过的方法
artifacts.reports.dotenv
所述案例在 Pass an environment variable to another job 中的gitlab文档中更详细地处理。此外,下面显示的 yml
文件受到这个示例的很大启发。然而,它并不起作用。
build.env
构件是在 building
中创建的,但每当执行 deploying
任务时,build.env
文件都会被删除,如第15行所示:"Removing build.env"。我试图将 build.env
添加到 .gitignore
中,但它仍然会被删除。
经过多次搜索,我在这个Gitlab issue评论和这篇stackoverflow帖子中发现artifacts.reports.dotenv
不能与dependencies
或needs
关键字一起使用。删除
dependencies
也无法解决问题。仅使用needs
也不行。同时使用两者是不允许的。有没有人知道如何使其正常工作?我觉得它应该这样工作。
将构件作为文件获取
这篇stackoverflow帖子中的回答Gitlab ci cd removes artifact for merge requests建议将
build.env
作为普通文件使用。我也尝试了这种方法。关键的yml
如下:building:
# ...
artifacts:
paths:
- build.env
deploying:
# ...
before_script:
- source build.env
结果与上面相同。
build.env
被删除。然后 source build.env
命令失败,因为 build.env
不存在。(无论是否在.gitignore
中,都经过测试)。
从API获取工件
我还发现了stackoverflow帖子Use artifacts from merge request job in GitLab CI的答案,建议使用API和$CI_JOB_TOKEN
一起使用。但由于我需要在非合并请求管道中使用工件,因此无法使用建议的CI_MERGE_REQUEST_REF_PATH
。我尝试使用
$CI_COMMIT_REF_NAME
。 然后(重要部分的)yml
如下:deploying:
# ...
script:
- url=$CI_API_V4_URL/projects/jobs/artifacts/$CI_COMMIT_REF_NAME/download?job=building
- echo "Downloading $url"
- 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --output $url'
# ...
但是这个API请求被拒绝并显示“404未找到”。由于提交SHA不受支持, 因此
$CI_COMMIT_BEFORE_SHA
或$CI_COMMIT_SHA
也无法工作。
使用needs
更新:我在GitLab文档中找到了同一项目中的管道之间的构件下载部分,这正是我想要的。但是:我无法使其工作。
在从文档中复制了更多或更少的内容后,yml
如下所示:
building:
# ...
artifacts:
paths:
- version
expire_in: never
deploying:
# ...
needs:
- project: $CI_PROJECT_PATH
job: building
ref: staging # building runs on staging branch, main doesn't work either
artifacts: true
现在,
deploying
任务立即失败,我收到以下错误提示:
我尝试设置artifacts.expire_in = never
(如图所示),但仍然遇到相同的错误。此外,在 设置 > CI/CD > Artifacts 中选择了“保留来自最近成功工作的构件”。因此,应该存在构件。我错过了什么?根据文档,这应该可以正常工作!
我希望有人能帮助我将$BUILD_VERSION
传递到deploying
任务中。如果有比我尝试过的其他方法,我非常乐意听取。提前感谢。
示例.gitlab-ci.yml
:
stages:
- staging
- deploy
building:
tags:
- docker
image: bash
stage: staging
rules:
- if: ($CI_PIPELINE_SOURCE == "merge_request_event") && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "staging"
when: always
- when: never
script:
- echo "BUILD_VERSION=1.2.3" > build.env
artifacts:
reports:
dotenv: build.env
environment:
name: Example
url: https://example.com
deploying:
tags:
- docker
image: bash
stage: deploy
rules:
- if: $CI_COMMIT_BRANCH == "staging"
when: always
- when: never
dependencies:
- building
script:
echo $BUILD_VERSION
reports: dotenv:
并改用paths:
。然后将dependencies:
保持不变,以在部署管道中恢复 build.env。 - Peteryml
并仅更改了building
的artifacts.reports
为artifacts.paths: -build.env
。 - miile7