Gitlab CI/CD 在管道之间传递人工制品/变量

问题描述

tl;博士

我如何传递数据,例如$BUILD_VERSION 变量,在 Gitlab CI 中不同管道中的作业之间?


背景

考虑以下示例(完整的 yml 下面):

building:
    # only on merge requests
    stage: staging
    script:
        - echo "BUILD_VERSION=1.2.3" > build.env
    artifacts:
        reports:
            dotenv: build.env

deploying:
    # after merge request is merged
    stage: deploy
    dependencies: 
        - building
    script:
        - echo $BUILD_VERSION

我有两个阶段,stagingdeploystaging 中的 building 作业构建应用并创建“审核应用”(为简单起见,没有单独的构建阶段)。 deploy 中的 deploying 作业然后上传新应用。

每当打开合并请求时,包含 building 作业的管道就会运行。通过这种方式构建应用程序,开发人员可以单击合并请求中的“审查应用程序”图标。 deploying 作业在合并请求合并后立即运行。思路如下:

                         *staging* stage                         *deploy* stage

<open merge request> -> `building` job (and show)   ...   <merge> -> `deploying` job
                             │                                            ▲
                             └───────────── $BUILD_VERSION ───────────────┘

我的问题是,staging/building 创建了一些数据,例如$BUILD_VERSION。我想在 deploy/$BUILD_VERSION 中使用这个 deploying,例如用于通过 Gitlab API 创建新版本。

所以我的问题是:如何将 $BUILD_VERSION(和其他数据)从 staging/building 传递到 deploy/{{ 1}}?


到目前为止我所尝试的

deploying

Pass an environment variable to another job 中的 gitlab 文档中,描述的案例较少处理。此外,下面显示artifacts.reports.dotenv 文件深受此示例的启发。还是不行。

yml 工件是在 build.env 中创建的,但是每当执行 building 作业时,deploying 文件都会被删除,如下面的第 15 行所示: .env”。我尝试将 build.env 添加build.env,但它仍然被删除

Preparing environment - Running on runner- via gitlab-runner... - Getting source from Git repository - Fetching changes with git depth set to 50... - Reinitialized existing Git repository in  - Checking out as staging... - Removing build.env - Skipping Git submodules setup - Executing "step_script" stage of the job script - Using docker image - echo $BUILD_VERSION - Job succeeded

经过数小时的搜索,我在 this gitlab issue commentthis stackoverflow post 中发现 .gitignore 不适用于 artifacts.reports.dotenvdependencies 关键字。>

删除 needs 不起作用。仅使用 dependencies 也不起作用。不允许同时使用。

有谁知道如何让它发挥作用?我觉得这就是它应该工作的方式。

将工件作为文件获取

stackoverflow 帖子 Gitlab ci cd removes artifact for merge requests 的这个答案建议将 needs 用作普通文件。我也试过这个。 (相关)build.env 如下:

yml

结果和上面一样。 building: # ... artifacts: paths: - build.env deploying: # ... before_script: - source build.env 被移除。然后 build.env 命令失败,因为 source build.env 不存在。 (build.env 是否在 build.env 中无关紧要,均已测试)

从 API 获取工件

我还找到了 stackoverflow 帖子 Use artifacts from merge request job in GitLab CI 的答案,它建议将 API 与 .gitignore 一起使用。但由于我需要非合并请求管道中的工件,因此我无法使用建议的 $CI_JOB_TOKEN

我尝试使用 CI_MERGE_REQUEST_REF_PATH。 (重要的部分)$CI_COMMIT_REF_NAME 然后是:

yml

但是这个 API 请求被“404 Not Found”拒绝了。由于 commit SHAs are not supporteddeploying: # ... 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' # ... $CI_COMMIT_BEFORE_SHA 也不起作用。

使用 $CI_COMMIT_SHA

更新:我在 gitlab 文档中找到了 Artifact downloads between pipelines in the same project 部分,这正是我想要的。但是:我无法让它工作。

从文档中复制更少的内容后,needs 如下所示:

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 作业立即失败,我收到以下错误横幅:

This job depends on other jobs with expired/erased artifacts:
Please refer to https://docs.gitlab.com/ee/ci/yaml/README.html#dependencies

我尝试设置 deploying(如图所示),但仍然出现相同的错误。同样在 Settings > CI/CD > Artifacts 中选择“保留最近成功作业的工件”。所以应该存在工件。我在这里错过了什么?这应该根据文档工作!


我希望有人能帮助我让 artifacts.expire_in = never 担任 $BUILD_VERSION 的工作。如果有其他方法而不是我尝试过的方法,我很高兴听到它们。提前致谢。


示例deploying

.gitlab-ci.yml

解决方法

这是你可以通过文件传递的东西。

在构建作业中创建新变量:

 variables:
     CONFIG: "anyname"

然后在脚本中执行导出/复制到文件,例如:

- echo $BUILD_VERSION > $CI_PROJECT_DIR/$CONFIG

在工件中添加路径:

artifacts:
   paths:
   - $CONFIG

然后在部署作业中

variables:
     CONFIG: "anyname"

和来源

- source $CI_PROJECT_DIR/$CONFIG

要使其工作,只需尝试解决传递问题,保持依赖关系并保留工件,只需使用“需求”,避免清除作业中的工件

,

您不能使用 CI/CD 在完全不相关的管道之间传递工件。 “构建”在定义合并请求的分支上运行,而“部署”在合并的结果上运行,这一事实并不意味着“部署”只是下一阶段。如果在两者之间合并另一个 MR 会怎样?如果存在合并冲突怎么办?

换句话说,你不能仅仅因为你构建了开发分支就跳过主分支上的“构建”。让“构建”一直发生,将“部署”限制在主分支。在此设置中,您可以轻松地将工件从“构建”传递到“部署”。

或者,如果您希望合并事件实际使用版本状态更新主分支,只需使用源代码控制的 VERSION 文件。这就是 git 的用途。当您合并时, main 将从分支采用 VERSION。如果不同的分支首先进入,您将必须解决冲突,这是您应该做的。