在项目之间共享 gitlab-ci.yml

Share gitlab-ci.yml between projects

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

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

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

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

受到 Auto DevOps .gitlab-ci.yml template Gitlab itself created, and where they use one template job to define all functions used and callbefore_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 to project-2 复制粘贴您的文件,它将使用相同的共享 Gitlab CI 函数。

为了示例目的,这些示例非常冗长,请按您喜欢的方式对其进行优化。

经验教训

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

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

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

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 实例上创建一个新项目

所以,我一直想 post,我现在想到的是:

现在我们使用@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 存储库导入共享的 pipeline.yml 文件。

# .gitlab-ci.yml

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

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

自 gitlab version 12.6 以来,可以定义外部 .gitlab-cy.yml 文件。

To customize the path:

  1. Go to the project's Settings > CI / CD.
  2. Expand the General pipelines section.
  3. Provide a value in the Custom CI configuration path field.
  4. Click Save changes. ...

If the CI configuration will be hosted on an external site, the URL link must end with .yml:

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

If the CI configuration will be hosted in a different project within GitLab, the path must be relative to the root directory in the other project, with the group and project name added to the end:

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

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

你可以看看Dynamic Child pipeline的概念。

它随着GitLab 13.2 (July 2020)进化而来:

Dynamically generate Child Pipeline configurations with Jsonnet

We released Dynamic Child Pipelines back in GitLab 12.9, which allow you to generate an entire .gitlab-ci.yml file at runtime.
This is a great solution for monorepos, for example, when you want runtime behavior to be even more dynamic.

We’ve now made it even easier to create CI/CD YAML at runtime by including a project template that demonstrates how to use Jsonnet to generate the YAML.
Jsonnet is a data templating language that provides functions, variables, loops, and conditionals that allow for fully parameterized YAML configuration.

documentation and issue

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

Validate expanded GitLab CI/CD configuration with the API

Writing and debugging complex pipelines is not a trivial task. You can use the include keyword to help reduce the length of your pipeline configuration files.

However, if you wanted to validate your entire pipeline via the API previously, you had to validate each included configuration file separately which was complicated and time consuming.

Now you have the ability to validate a fully-expanded version of your pipeline configuration through the API, with all the include configuration included.
Debugging large configurations is now easier and more efficient.

See Documentation and Issue.

并且:

参见 GitLab 13.6(2020 年 11 月)

Include multiple CI/CD configuration files as a list

Previously, when adding multiple files to your CI/CD configuration using the include:file syntax, you had to specify the project and ref for each file. In this release, you now have the ability to specify the project, ref, and provide a list of files all at once. This prevents you from having to repeat yourself and makes your pipeline configuration less verbose.

See Documentation) and Issue.