将脚本移动到 gitlab-ci.yml 中的单独文件中以避免代码重复并将其包含在多个文件中

Posted

技术标签:

【中文标题】将脚本移动到 gitlab-ci.yml 中的单独文件中以避免代码重复并将其包含在多个文件中【英文标题】:Moving scripts into a separate file in gitlab-ci.yml to avoid code duplication and including it from several files 【发布时间】:2021-02-19 14:47:37 【问题描述】:

我正在尝试使用 .gitlab-ci.yml 设置代码重复最少的 CI。

这样,我将配置分离到单独的文件中,并重用其中常见的部分。

我有一个带有 Gitlab CI 设置的单独存储库:gitlab-ci 和几个使用它来形成自己的 CI 管道的项目。

gitlab-ci 仓库的内容

template_jobs.yml:

.sample:
  rules:
    -  if: '$CI_PIPELINE_SOURCE == "push"'
       when: on_success
    -  when: never

jobs_architectureA.yml:

include:
  - local: '/template_jobs.yml'

.script_core: &script_core
  -  echo "Running stage"

test_archA:
  extends:
    - .sample
  stage: test
  tags:
    - architectureA
  script:
    - *script_core

jobs_architectureB.yml:

include:
  - local: '/template_jobs.yml'

.script_core: &script_core
  -  echo "Running stage"

test_archB:
  extends:
    - .sample
  stage: test
  tags:
    - architectureB
  script:
    - *script_core

项目代码内容:

在实际项目中(每个项目有单独的存储库,我有很多),我有以下内容:

.gitlab-ci.yml:

stages:
  - test

include:
  - project: 'gitlab-ci'
    file: '/jobs_architectureA.yml'
  - project: 'gitlab-ci'
    file: '/jobs_architectureB.yml'

此配置工作正常,允许仅包含某些模块的某些架构,同时在作业模板之间共享规则。

但是,很容易注意到一个代码重复:jobs_architectureA.ymljobs_architectureB.yml 都包含一个公共部分:

.script_core: &script_core
  -  echo "Running stage"

最好将其移动到单独的文件中:template_scripts.yml 并同时包含 jobs_architectureA.yml* 和 jobs_architectureB.yml。但是,这会导致 YAML 无效(至少从 Gitlab 的角度来看)。

有了这个,我得出一个结论,我可以分享这些规则,因为它们的使用机制是通过extends关键字;但是,我无法使用脚本来执行此操作:因为它在 YAML 级别使用 &/* anchoring 机制。

理想情况下,我想要以下内容:

理想(概念上)gitlab-ci 存储库的内容

template_jobs.yml:

.sample:
  rules:
    -  if: '$CI_PIPELINE_SOURCE == "push"'
       when: on_success
    -  when: never

template_scripts.yml:

.script_core: &script_core
  -  echo "Running stage"

jobs_architectureA.yml:

include:
  - local: '/template_jobs.yml'
  - local: '/template_scripts.yml'

test_archA:
  extends:
    - .sample
  stage: test
  tags:
    - architectureA
  script:
    - *script_core  # this becomes invalid, as script_core is in the other file, even though it is included at the top

jobs_architectureB.yml:

include:
  - local: '/template_jobs.yml'
  - local: '/template_scripts.yml'

test_archB:
  extends:
    - .sample
  stage: test
  tags:
    - architectureB
  script:
    - *script_core # this becomes invalid, as script_core is in the other file, even though it is included at the top

我做错了吗? 我是否遇到了 Gitlab 机制的限制?是不是在这个特定的 YML 类型中实现了 include 指令,这限制了我? 我是否可以选择实现接近所需行为的东西?

请注意,虽然这可能看起来没什么大不了的,但实际上,我的脚本还有很多,实际的脚本要大得多。因此,目前是到处都是重复代码,很容易出错。

【问题讨论】:

【参考方案1】:

我的解决方案是不直接在jobs_architectureA.yml 中包含template_jobs.ymltemplate_scripts.yml,而只在“最终”.gitlab-ci.yml 中包含

以你为例,/template_jobs.yml//template_scripts.yml 不变。

jobs_architectureA.yml 失去了include

test_archA:
  extends:
    - .sample
  stage: test
  tags:
    - architectureB
  script:
    - *script_core # this becomes invalid, as script_core is in the other file, even though it is included at the top

.gitlab-ci.yml 变为:

stages:
  - test

include:
  - local: '/template_jobs.yml'
  - local: '/template_scripts.yml'
  - project: 'gitlab-ci'
    file: '/jobs_architectureA.yml'
  - project: 'gitlab-ci'
    file: '/jobs_architectureB.yml'

【讨论】:

有趣。我必须尝试是否可行(实际上,为什么有什么不同?)。但是,如果想在此处使用模板定义自定义阶段和作业,这会显着限制在 .gitlab-ci.yml 级别上进行自定义的能力。【参考方案2】:

实际上,我的脚本还有很多,实际的脚本要大得多

添加到Cyril 的solution、GitLab 13.12(2021 年 5 月)可以帮助扩展这些包括:

在包含 YAML CI/CD 配置文件时支持通配符

CI/CD 管道的 includes: 关键字可让您将一个较长的 .gitlab-ci.yml 文件拆分为多个较小的文件,以提高可读性。 它还可以更轻松地在多个地方重用配置。

单个管道中经常包含多个文件,并且它们可能都存储在同一个位置。

在此版本中,我们添加了对使用 * 通配符和本地 includes: 关键字的支持。您现在可以让您的 includes: 部分更动态、更简洁、更易于阅读,在 GitLab 中查看我们的 dogfooding 它。

参见Documentation 和Issue。

【讨论】:

以上是关于将脚本移动到 gitlab-ci.yml 中的单独文件中以避免代码重复并将其包含在多个文件中的主要内容,如果未能解决你的问题,请参考以下文章

如何将存储库中的文件复制到用于作业的 Docker 容器中,在 gitlab-ci.yml

使用“:”的脚本命令导致 .gitlab-ci.yml 执行错误

多个分支中的.gitlab-ci.yml的多个版本

Gitlab-ci.yml 创建合并请求

使用 gitlab-ci.yml 文件的代码覆盖率报告

.gitlab-ci.yml 配置文件详解