如何设置动态 gitlab-ci 文件

Posted

技术标签:

【中文标题】如何设置动态 gitlab-ci 文件【英文标题】:How to setup a dynamic gitlab-ci file 【发布时间】:2019-11-13 02:35:45 【问题描述】:

我正在尝试设置一个动态 gitlab-ci 文件,其中包含基于项目变量所需的 gitlab-ci 文件。

不幸的是,我似乎无法让它工作,我已经阅读了文档并搜索了论坛,但不幸的是我找不到任何解决方案。

如何实现动态的gitlab-ci文件?

基本上我想做类似下面的 sn-p 的事情,但我注意到我不能在文件方法中使用变量(返回“无效配置:文件不存在”。)。

include:
  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-$GITLABFILE.yml'
    only:
      - $GITLABFILE
include:
  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci.yml'
    only:
      - $GITLABFILE == null

由于我无法在文件方法中使用变量,我尝试了以下配置,但不幸的是它总是加载最后一个文件并忽略唯一的关键字。

include:
  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci.yml'
    except:
      variables:
        - $GITLABFILE

  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-legacy.yml'
    only:
      variables:
        - $GITLABFILE == 'legacy'

  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-legacy-nobuild.yml'
    only:
      variables:
        - $GITLABFILE == 'legacy-nobuild'

我希望单个 gitlab-ci 文件可以根据变量检索其他 gitlab-ci 文件。

希望有人可以帮助我或为我指明正确的方向。

【问题讨论】:

【参考方案1】:

一种可能的解决方案:参见GitLab 14.3(2021 年 9 月)

根据条件包含 GitLab CI/CD 配置

include 是编写完整 CI/CD 管道时最常用的关键字之一。 如果您正在构建更大的管道,您可能会使用 include 关键字将外部 YAML 配置引入您的管道。

在此版本中,我们正在扩展关键字的功能,以便您可以将includerules 条件结合使用。

现在,您可以决定何时应该或不应该包含外部 CI/CD 配置。这将帮助您编写一个能够根据您选择的条件动态修改自身的标准化管道。

请参阅 Documentation 和 Issue。

例子:

您只能在include 中使用if 规则,并且只能与certain variables 一起使用。不支持changesexistsrules 关键字。

include:
  - local: builds.yml
    rules:
      - if: '$INCLUDE_BUILDS == "true"'

test:
  stage: test
  script: exit 0

见GitLab 14.5(2021 年 11 月)

带有exists关键字的条件包含

include 关键字是编写完整 CI/CD 管道时最常用的关键字之一。如果您正在构建更大的管道,您 可能正在使用 include 关键字将外部 YAML 配置引入您的管道。

在此版本中,我们正在扩展关键字的功能,以便您可以在规则条件中使用 include 和 exists。轮到你了 可以根据存储库中何时存在某些文件来决定何时应该或不应该包含外部 CI/CD 配置。

参见Documentation 和Issue。

【讨论】:

【参考方案2】:

感谢 Ivan,我找到了完美的解决方案,我所做的是创建 1 个 gitlab-ci,其中包括所有其他文件,并且在每个特定文件中,我使用 Ivan 建议的唯一关键字。

现在我的文件如下所示:

项目级别(在每个项目中)存在的 gitlab-ci:

include:
  - project: 'tools/gitlab-ci'
    file: '/selector.yml'

那么我的 selector.yml 文件如下所示:

include:
  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-global.yml'

  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-nobuild.yml'

  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-legacy.yml'

  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-multitheme.yml'

  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-default.yml'

由于正在读取所有文件,我不得不将 before_script 任务移动到每个单独的阶段,否则 gitlab 只会读取最后一个 before_script 声明,因此我为此创建了一个模板/锚点:

.before_script_template: &before-script-legacy
  before_script:
    - apt-get update -y && apt-get install -yqqf openssh-client git unzip sshpass rsync --fix-missing

    # Is probably already present but just to be sure.
    - npm install -g gulp
    - npm install -g bower

    - echo "You've set the GITLABFILE var to legacy and therefore get this file"

compile_legacy:
  stage: build
  <<: *before-script-legacy
  script:
    - #Some stuff here....
  only:
    variables:
      - $GITLABFILE == "legacy" && $SKIP_COMPILE == null

另请注意,每个阶段都必须有一个唯一的标识符/作业名称!

【讨论】:

【参考方案3】:

为什么不将条件逻辑放在这些单独的 gitlab-ci 文件中,然后将它们全部包含在内。

这样的东西 - 在你的主文件中:

variables:
  GITLABFILE: legacy

include:
  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci.yml'

  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-legacy.yml'

  - project: 'tools/gitlab-ci'
    file: '/gitlab-ci-legacy-nobuild.yml'

然后在每个子文件中 - 例如在gitlab-ci-legacy.yml:

job:
  script:
    - echo Do something
  only:
    variables:
      - $GITLABFILE == "legacy"

查看更多:https://docs.gitlab.com/ee/ci/yaml/#onlyvariablesexceptvariables

【讨论】:

感谢 Ivan,这看起来是一个可行的解决方案,我会尝试并告诉您。

以上是关于如何设置动态 gitlab-ci 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 gitlab-ci.yml 文件中通过 ssh 设置变量值

如何让 gitlab-runner 从指定文件中读取而不是 .gitlab-ci.yml?

如何使用 gitlab-ci.yml 在 gitlab 中更新 JSON 文件的内容?

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

如何使用 gitlab-ci 作业推送到 gitlab 存储库?

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