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

时间:2021-06-29 13:22:19

标签: gitlab devops gitlab-ci pass-data

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

2 个答案:

答案 0 :(得分:1)

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

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

 variables:
     CONFIG: "anyname"

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

- echo $BUILD_VERSION > $CI_PROJECT_DIR/$CONFIG

在工件中添加路径:

artifacts:
   paths:
   - $CONFIG

然后在部署作业中

variables:
     CONFIG: "anyname"

和来源

- source $CI_PROJECT_DIR/$CONFIG

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

答案 1 :(得分:1)

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

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

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