web-dev-qa-db-fra.com

Partager gitlab-ci.yml entre les projets

Nous pensons déplacer notre ci de jenkins à gitlab. Nous avons plusieurs projets qui ont le même workflow de build. À l'heure actuelle, nous utilisons une bibliothèque partagée dans laquelle les pipelines sont définis et le fichier jenkins dans le projet n'appelle qu'une méthode définie dans la bibliothèque partagée définissant le pipeline réel. Les modifications ne doivent donc être apportées qu'à un seul point affectant plusieurs projets.

Je me demande si la même chose est possible avec gitlab ci? Pour autant que je l'ai découvert, il n'est pas possible de définir le gitlab-ci.yml en dehors du référentiel. Existe-t-il une autre façon de définir un pipeline et de partager cette configuration avec plusieurs projets pour simplifier la maintenance?

9
pyriand3r

Permettez-moi tout d'abord de dire: Merci d'avoir posé cette question! Cela m'a incité à chercher (encore) une solution après m'être souvent demandé si c'était moi-même possible. Nous avons également 20 à 30 projets qui sont assez identiques et qui ont .gitlab-ci.yml Des fichiers d'environ 400 à 500 loc qui doivent être modifiés chacun si une chose change.

J'ai donc trouvé une solution de travail:

Inspiré par le modèle Auto DevOps .gitlab-ci.yml Gitlab lui-même créé, et où ils utilisent un travail de modèle pour définir toutes les fonctions utilisées et appeler = chaque before_script pour les charger, j'ai trouvé la configuration suivante.

  • Repo de projets multiples ( project-1 , project-2 ) nécessitant un ensemble partagé de tâches/fonctions CI
  • Script de fonctions contenant toutes les fonctions partagées dans un référentiel séparé

Fichiers

Donc, en utilisant un scipt partagé d'emplois ci :

#!/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"
}

Un .gitlab-ci.yml Commun et générique:

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

Vous pouvez copier-coller votre fichier de project-1 vers project-2 et il utiliserait les mêmes fonctions partagées de Gitlab CI.

Ces exemples sont assez verbeux à des fins d'exemple, optimisez-les comme vous le souhaitez.

Leçons apprises

Donc, après avoir appliqué la construction ci-dessus à grande échelle (plus de 40 projets), je veux partager quelques leçons apprises afin que vous n'ayez pas à découvrir à la dure:

  • Version (tag/release) de votre script de fonctions ci partagé. Changer une chose peut maintenant faire échouer tous les pipelines.
  • L'utilisation de différentes images Docker peut entraîner un problème dans la nécessité pour bash de charger les fonctions (par exemple, j'utilise certaines images basées sur Alpine pour les travaux basés sur l'outil CLI qui ont sh par défaut)
  • Utilisez des variables secrètes CI/CD basées sur un projet pour personnaliser les travaux de génération pour les projets. Comme les URL d'environnement, etc.
12
Stefan van Gastel

GitLab 11.7 introduit de nouvelles méthodes include, telles que include:file: https://docs.gitlab.com/ee/ci/yaml/#includefile

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

Cela vous permettra de créer un nouveau projet sur la même instance GitLab qui contient un .gitlab-ci.yml.

8
miq

Utilisez la fonction include, (disponible à partir de GitLab 10.6): https://docs.gitlab.com/ee/ci/yaml/#include

5
Yevhen Lebid

Depuis gitlab version 12.6 , il est possible de définir un fichier externe .gitlab-cy.yml.

Pour personnaliser le chemin:

  1. Accédez aux paramètres du projet> CI/CD.
  2. Développez la section Pipelines généraux.
  3. Indiquez une valeur dans le champ Chemin de configuration du CI personnalisé.
  4. Cliquez sur Enregistrer les modifications. ...

Si la configuration CI sera hébergée sur un site externe, le lien URL doit se terminer par .yml:

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

Si la configuration CI sera hébergée dans un autre projet dans GitLab, le chemin doit être relatif au répertoire racine de l'autre projet, avec le nom du groupe et du projet ajouté à la fin:

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

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

2
Joao Vitorino

Donc, j'ai toujours voulu poster, avec ce que j'ai trouvé maintenant:

À l'heure actuelle, nous utilisons une approche mixte de l'idée de @ stefan-van-gastel d'une bibliothèque ci partagée et de la fonction include relativement nouvelle de gitlab 11.7. Nous sommes très satisfaits de cette approche, car nous pouvons désormais gérer notre pipeline de build pour plus de 40 référentiels dans un seul référentiel.

J'ai créé un référentiel appelé ci_shared_library Contenant

  1. un script Shell pour chaque tâche de génération unique contenant la logique d'exécution de l'étape.
  2. un fichier pipeline.yml contenant toute la configuration du pipeline. Dans le script précédent, nous chargeons le ci_shared_library Dans /tmp/shared Pour pouvoir exécuter les 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\/.*/

Chaque projet qui souhaite utiliser cette configuration de pipeline doit avoir un .gitlab-ci.yml. Dans ce fichier, la seule chose à faire est d'importer le fichier partagé pipeline.yml À partir du référentiel ci_shared_library.

# .gitlab-ci.yml

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

Avec cette approche, tout ce qui concerne le pipeline réside dans un seul référentiel et est réutilisable. Nous avons l'ensemble du modèle de pipeline dans un fichier, mais je pense qu'il serait même possible de le diviser pour avoir chaque tâche dans un fichier yml. De cette façon, il serait plus flexible et on pourrait créer des emplois par défaut qui peuvent être fusionnés différemment pour des projets qui ont des emplois similaires, mais pas tous les projets nécessitant tous les emplois ...

0
pyriand3r