Share gitlab-ci.yml between projects

后端 未结 7 1205
面向向阳花
面向向阳花 2020-12-13 21:04

We are thinking to move our ci from jenkins to gitlab. We have several projects that have the same build workflow. Right now we use a shared library where the pipelines are

相关标签:
7条回答
  • 2020-12-13 21:36

    So, i always wanted to post, with what i came up with now:

    Right now we use a mixed approach of @stefan-van-gastel's idea of a shared ci library and the relatively new include feature of gitlab 11.7. We are very satisfied with this approach as we can now manage our build pipeline for 40+ repositories in a single repository.

    I have created a repository called ci_shared_library containing

    1. a shell script for every single build job containing the execution logic for the step.
    2. a pipeline.yml file containing the whole pipeline config. In the before script we load the ci_shared_library to /tmp/shared to be able to execute the scripts.
    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\/.*/
    

    Every project that want's to use this pipeline config has to have a .gitlab-ci.yml. In this file the only thing to do is to import the shared pipeline.yml file from the ci_shared_library repo.

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

    With this approach really everything regarding to the pipeline lives in one single repository and is reusable. We have the whole pipeline-template in one file, but i think it would even be possible to split this up to have every single job in a yml-file. This way it would be more flexible and one could create default jobs that can be merged together differently for projects that have similar jobs but not every project needing all jobs...

    0 讨论(0)
  • 2020-12-13 21:39

    Since gitlab version 12.6, it's possible define a external .gitlab-cy.yml file.

    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

    0 讨论(0)
  • 2020-12-13 21:40

    GitLab 11.7 introduces new include methods, such as include:file: https://docs.gitlab.com/ee/ci/yaml/#includefile

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

    This will allow you to create a new project on the same GitLab instance which contains a shared .gitlab-ci.yml.

    0 讨论(0)
  • 2020-12-13 21:53

    First let me start by saying: Thank you for asking this question! It triggered me to search for a solution (again) after often wondering if this was even possible myself. We also have like 20 - 30 projects that are quite identical and have .gitlab-ci.yml files of about 400 - 500 loc that have to each be changed if one thing changes.

    So I found a working solution:

    Inspired by the Auto DevOps .gitlab-ci.yml template Gitlab itself created, and where they use one template job to define all functions used and call every before_script to load them, I came up with the following setup.

    • Multiple project repo's (project-1, project-2) requiring a shared set of CI jobs / functions
    • Functions script containing all shared functions in separate repo

    Files

    So using a 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"
    }
    

    A common and generic .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
    

    You could copy-paste your file from project-1 to project-2 and it would be using the same shared Gitlab CI functions.

    These examples are pretty verbose for example purposes, optimize them any way you like.

    Lessons learned

    So after applying the construction above on a large scale (40+ projects) I want to share some lessons learned so you don't have to find out the hard way:

    • Version (tag / release) your shared ci functions script. Changing one thing can now make all pipelines fail.
    • Using different Docker images could cause an issue in the requirement for bash to load the functions (e.g. I use some Alpine-based images for CLI tool based jobs that have sh by default)
    • Use project based CI/CD secret variables to personalize build jobs for projects. Like environment URL's etc.
    0 讨论(0)
  • 2020-12-13 21:53

    Use include feature, (available from GitLab 10.6): https://docs.gitlab.com/ee/ci/yaml/#include

    0 讨论(0)
  • 2020-12-13 22:02

    You could look into the concept of Dynamic Child pipeline.

    It has evolved with 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.

    See documentation and issue.

    0 讨论(0)
提交回复
热议问题