【问题标题】:Share gitlab-ci.yml between projects在项目之间共享 gitlab-ci.yml
【发布时间】:2018-05-27 04:31:03
【问题描述】:

我们正在考虑将 ci 从 jenkins 转移到 gitlab。我们有几个项目具有相同的构建工作流程。现在我们使用一个共享库,其中定义了管道,项目中的 jenkinsfile 只调用定义实际管道的共享库中定义的方法。因此,只需在影响多个项目的单个点进行更改。

我想知道 gitlab ci 是否可以做到这一点?据我发现,不可能在存储库之外定义 gitlab-ci.yml 。是否有另一种方法来定义管道并与多个项目共享此配置以简化维护?

【问题讨论】:

    标签: jenkins shared-libraries jenkins-pipeline pipeline gitlab-ci


    【解决方案1】:

    首先让我先说:感谢您提出这个问题!在经常想知道这是否可能我自己之后,它触发了我(再次)寻找解决方案。我们还有大约 20 到 30 个完全相同的项目,并且有大约 400 到 500 个位置的 .gitlab-ci.yml 文件,如果一件事发生变化,则每个文件都必须更改。

    所以我找到了一个可行的解决方案:

    Auto DevOps .gitlab-ci.yml template Gitlab 本身创建的启发,他们使用一个模板作业到define all functions usedcall 每个before_script 加载它们,我想出了以下设置。

    文件

    所以使用shared ci jobs scipt

    #!/bin/bash
    
    function list_files {
      ls -lah
    }
    
    function current_job_info {
      echo "Running job $CI_JOB_ID on runner $CI_RUNNER_ID ($CI_RUNNER_DESCRIPTION) for pipeline $CI_PIPELINE_ID"
    }
    

    一个普通的通用.gitlab-ci.yml

    image: ubuntu:latest
    
    before_script:
      # Install curl
      - apt-get update -qqq && apt-get install -qqqy curl
      # Get shared functions script
      - curl -s -o functions.sh https://gitlab.com/giix/demo-shared-ci-functions/raw/master/functions.sh
      # Set permissions
      - chmod +x functions.sh
      # Run script and load functions
      - . ./functions.sh
    
    job1:
      script:
        - current_job_info
        - list_files
    

    您可以将文件从 project-1 复制粘贴到 project-2,它会使用相同的共享 Gitlab CI 函数。

    出于示例目的,这些示例非常冗长,可以按您喜欢的方式对其进行优化。

    经验教训

    因此,在大规模应用上述构造(40 多个项目)之后,我想分享一些经验教训,这样您就不必费力地去寻找:

    • 版本(标记/发布)您的共享 ci 函数脚本。改变一件事现在可以使所有管道失败。
    • 使用不同的 Docker 映像可能会导致 bash 加载函数的要求出现问题(例如,我将一些基于 Alpine 的映像用于基于 CLI 工具的作业,默认情况下具有 sh
    • 使用基于项目的 CI/CD 秘密变量来个性化项目的构建作业。像环境 URL 等。

    【讨论】:

    • 感谢您分享您的想法。看来,这是目前唯一的可能。仍然无法将新作业批量添加到管道中,但我们目前可以获得最好的。谢谢!
    • 有类似的想法,很高兴我找到了已经将它投入生产的人。在我的设置中,我在 git 子模块中有几个 bash 脚本,因此我的工作描述为 publish-java: {script: 'ci/publish-java.sh'},例如。而不是'before_script',我在顶部定义了variables: { GIT_SUBMODULE_STRATEGY: 'recursive' }gist.github.com/lordvlad/1ad18dc44479f2b90735bdb96b1d5338
    【解决方案2】:

    GitLab 11.7 引入了新的include 方法,例如include:filehttps://docs.gitlab.com/ee/ci/yaml/#includefile

    include:
      - project: 'my-group/my-project'
        ref: master
        file: '/templates/.gitlab-ci-template.yml'
    

    这将允许您在包含共享 .gitlab-ci.yml 的同一 GitLab 实例上创建一个新项目。

    【讨论】:

      【解决方案3】:

      由于 gitlab version 12.6,可以定义一个外部的.gitlab-cy.yml 文件。

      自定义路径:

      1. 转到项目的设置 > CI / CD。
      2. 展开常规管道部分。
      3. 在自定义 CI 配置路径字段中提供一个值。
      4. 单击保存更改。 ...

      如果 CI 配置将托管在外部站点上,则 URL 链接必须以 .yml 结尾:

      http://example.com/generate/ci/config.yml

      如果 CI 配置将托管在不同的项目中 GitLab,路径必须相对于另一个中的根目录 项目,组和项目名称添加到末尾:

      .gitlab-ci.yml@mygroup/another-project

      my/path/.my-custom-file.yml@mygroup/another-project

      【讨论】:

        【解决方案4】:

        使用include 功能,(可从 GitLab 10.6 获得): https://docs.gitlab.com/ee/ci/yaml/#include

        【讨论】:

          【解决方案5】:

          所以,我一直想发布我现在想出的东西:

          现在我们使用@stefan-van-gastel 的共享 ci 库想法和 gitlab 11.7 的相对较新的include 功能的混合方法。我们对这种方法非常满意,因为我们现在可以在一个存储库中管理 40 多个存储库的构建管道。

          我创建了一个名为 ci_shared_library 的存储库,其中包含

          1. 每个构建作业的 shell 脚本,其中包含步骤的执行逻辑。
          2. 包含整个管道配置的pipeline.yml 文件。在前面的脚本中,我们将ci_shared_library 加载到/tmp/shared 以便能够执行脚本。
          stages:
            - test
            - build
            - deploy
            - validate
          
          services:
            - docker:dind
          
          before_script:
            # Clear existing shared library
            - rm -rf /tmp/shared
            # Get shared library
            - git clone https://oauth2:${GITLAB_TOKEN}@${SHARED_LIBRARY} /tmp/shared
            - cd /tmp/shared && git checkout master && cd $CI_PROJECT_DIR
            # Set permissions
            - chmod -R +x /tmp/shared
            # open access to registry
            - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
          
          test:
            stage: test
            script:
              - /tmp/shared/test.sh
          
          build:
            stage: build
            script:
              - /tmp/shared/build.sh
            artifacts:
              paths:
                - $CI_PROJECT_DIR/target/RPMS/x86_64/*.rpm
              expire_in: 3h
            only:
              - develop
              - /release/.*/
          
          deploy:
            stage: deploy
            script:
              - /tmp/shared/deploy.sh
            artifacts:
              paths:
                - $CI_PROJECT_DIR/tmp/*
              expire_in: 12h
            only:
              - develop
              - /release/.*/
          
          validate:
            stage: validate
            script:
              - /tmp/shared/validate.sh
            only:
              - develop
              - /release\/.*/
          

          每个想要使用此管道配置的项目都必须有一个.gitlab-ci.yml。在这个文件中,唯一要做的就是从ci_shared_library repo 中导入共享的pipeline.yml 文件。

          # .gitlab-ci.yml
          
          include:
            - project: 'ci_shared_library'
              ref: master
              file: 'pipeline.yml'
          

          通过这种方法,与管道有关的所有内容都位于一个存储库中并且可以重复使用。我们将整个管道模板放在一个文件中,但我认为甚至可以将其拆分为 yml 文件中的每个作业。这样一来,它会更加灵活,并且可以为具有相似工作但并非每个项目都需要所有工作的项目创建可以不同方式合并在一起的默认工作......

          【讨论】:

          • 有趣!但是您在 pipeline.yml 中签出开发分支,而在 gitlab-ci.yml 中包含 master ??
          • 感谢您指出这一点。这是我已修正的错误。但另一方面,它似乎很奇怪,但正在工作。 Gitlab 从主分支的pipeline.yml 获取整个管道。如果这个文件告诉它拉 ci_shared_library 存储库的开发分支,那完全没问题。但可能有点令人困惑;)
          【解决方案6】:

          有了GitLab 13.5(2020 年 10 月),include 功能更加有用:

          使用 API 验证扩展的 GitLab CI/CD 配置

          编写和调试复杂的管道并非易事。您可以使用 include 关键字来帮助减少管道配置文件的长度。

          但是,如果您之前想通过 API 验证整个管道,则必须单独验证每个包含的配置文件,这既复杂又耗时。

          现在您可以通过 API 验证管道配置的完全扩展版本,其中包括所有 include 配置。
          调试大型配置现在更轻松、更高效。

          参见DocumentationIssue

          还有:

          GitLab 13.6(2020 年 11 月)

          包含多个 CI/CD 配置文件作为列表

          以前,当使用 include:file 语法将多个文件添加到 CI/CD 配置时,您必须为每个文件指定项目和引用。在此版本中,您现在可以一次性指定项目、引用和提供文件列表。这可以防止您重复自己,并使您的管道配置不那么冗长。

          Documentation) 和Issue

          【讨论】:

            【解决方案7】:

            你可以研究一下Dynamic Child pipeline的概念。

            随着 GitLab 13.2 (July 2020) 的发展而演变:

            使用 Jsonnet 动态生成子管道配置

            我们发布了Dynamic Child Pipelines back in GitLab 12.9,它允许您在运行时生成整个.gitlab-ci.yml 文件。
            这对于 monorepos 来说是一个很好的解决方案,例如,当您希望运行时行为更加动态时。

            现在,我们通过包含一个项目模板来演示如何使用 Jsonnet 生成 YAML,从而使在运行时创建 CI/CD YAML 变得更加容易。
            Jsonnet 是一种数据模板语言,它提供了允许完全参数化 YAML 配置的函数、变量、循环和条件。

            请参阅 documentationissue

            【讨论】:

              猜你喜欢
              • 2017-03-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-09-08
              • 2020-09-03
              • 2014-10-16
              • 2011-07-22
              相关资源
              最近更新 更多